1

I have some XML that I want to read into a SimpleXMLElement, the element values are then used as strings by casting the elements to string. For each SimpleXMLELement I'd like to change the element string before returning it. Rather than repeating the manipulation everywhere an element is accessed I'd like to do this in one place.

My first thought was to override SimpleXMLElement__toString but this seems to be only called with print and not by casting to string with (string).

Is there something else I should be overriding or is there a better approach to this?

<?php
$string_xml = "<?xml version='1.0' encoding='UTF-8'?>
<foo>
    <bar>baz</bar>
</foo>";

$xml = simplexml_load_string($string_xml, 'ToStringTest');
print "cast ";
$s = (string)$xml->bar;
print $s;
// "cast baz" is printed
print "\nprint ";
print $xml->bar;
// "print uses __toStringbazfoo" is printed

class ToStringTest extends SimpleXMLElement
{   
    public function __toString()
    {   
        print "uses __toString";
        return parent::__toString() . 'foo';
    }
}
dsas
  • 1,650
  • 18
  • 30
  • 1
    The logic for SimpleXML is written in C, not PHP, so probably doesn't call out to the PHP function for things like that. Rather than overloading `__toString()`, you could add an extra method, like `->getManipulatedString()`. – IMSoP Apr 16 '14 at 12:06
  • Ideally I'd like to avoid that approach, apart from constructing the SimpleXMLElement I'd like the rest of the app to be able to treat it as it would any other SimpleXMLElement – dsas Apr 16 '14 at 12:35
  • There wasn't a better suggestion, if this is added as an answer I'll accept it. – dsas Apr 29 '14 at 16:42

1 Answers1

-1

Did you try swapping your class definition and usage of simplexml_load_string?

<?php
$string_xml = "<?xml version='1.0' encoding='UTF-8'?>
<foo>
    <bar>baz</bar>
</foo>";

class ToStringTest extends SimpleXMLElement
{   
    public function __toString()
    {   
        print "uses __toString";
        return parent::__toString() . 'foo';
    }
}

$xml = simplexml_load_string($string_xml, 'ToStringTest');
print "cast ";
$s = (string)$xml->bar;
print $s;
// "cast baz" is printed
print "\nprint ";
print $xml->bar;
// "print uses __toStringbazfoo" is printed

You might have the problem that class ToStringTest is not defind when you call "simplexml_load_string" and then there is no function available to override __toString() with and the program is sticking with the known definition in the base class ofcourse.

Because PHP cannot overload functions except for class inheritance it is most likely that it works silent here and doesnt really takes care if your class exists, but ofcourse the result is different.

Steini
  • 2,753
  • 15
  • 24
  • 1
    Thanks but that's not the case here, PHP doesn't work like that, also that wouldn't explain why print works and (string) doesn't. – dsas Apr 16 '14 at 12:37