SimpleXML & Casting to String

php.internals

Adam Maccabee Trachtenberg

22 years ago
I know we discussed this already, but after seeing a couple of bug reports about SimpleXML, I'm worried our decision only makes sense to us and not to regular users. :) Specifically, since elements and attibutes look like strings, people expect them to act like strings. But since they're not objects instead of strings, they're completely buffled as how to handle them. Here are two examples that have come through the bug report system in the last day: $sxe = simplexml_load_string('<root a="123" />'); if ($sxe['a'] == '123') { // do something } And: $xml = simplexml_load_string(/* some valid XML string that I'm not going to cut and paste here */); foreach($xml->user as $user){ if (utf8_decode($user->login) == $login && utf8_decode($user->password) == $password) { // valid users } } Both seem like they should work, but neither do. In the first example, we're comparing an object with a string. Even though $sxe['a']->__toString() == 'a', the comparison fails. (Well, you can't actually do that, but you know what I mean.) In the second example, utf8_decode() expects a string and not an object and we again we don't autoconvert. The problems can be solved by explicitly casting the object to a string, but since you rarely need to cast elsewhere in PHP, I don't think anyone thinks of it as a necessary step. Originally, I proposed that PHP autoconvert an object to a string whenever the object has a __toString() and it's necessary to treat the variable as a string. In the first example, since we're comparing an object to a string, we would cast down the object to enable the comparison. This would work just like 1 == '1'. In the second case, since the function expects a string, we'd also do the cast. However, Andi (and others) raised some valid issues about edge cases and other potential engine problems. Is there anything we can do to help out people so that SimpleXML works as they expect, but doesn't have the potential to unleash hell on PHP and the bug system? Maybe it makes sense to have SimpleXML leaf nodes return as strings instead of SimpleXML objects? Or does this merely substitute one set of problems for another? (E.g. this breaks iteratation, what happens when there's multiple leaves, etc.) I don't know what the right answer is, but I feel that the current solution isn't perfect. It may end up to be the best possible method, but I'm not yet convinced it is. -adam
-- adam@trachtenberg.com author of o'reilly's php cookbook avoid the holiday rush, buy your copy today!

Marcus Börger

22 years ago
Hello Adam, Friday, February 27, 2004, 7:37:15 PM, you wrote:
> I know we discussed this already, but after seeing a couple of bug > reports about SimpleXML, I'm worried our decision only makes sense to > us and not to regular users. :)
> Specifically, since elements and attibutes look like strings, people > expect them to act like strings. But since they're not objects instead > of strings, they're completely buffled as how to handle them.
> Here are two examples that have come through the bug report system in > the last day:
> $sxe = simplexml_load_string('<root a="123" />'); > if ($sxe['a'] == '123') { > // do something > }
> And:
> $xml = simplexml_load_string(/* some valid XML string that I'm not > going to cut and paste here */); > foreach($xml->user as $user){ > if (utf8_decode($user->login) == $login && > utf8_decode($user->password) == $password) { > // valid users > } > }
> Both seem like they should work, but neither do.
> In the first example, we're comparing an object with a string. Even > though $sxe['a']->__toString() == 'a', the comparison fails. (Well, you > can't actually do that, but you know what I mean.)
> In the second example, utf8_decode() expects a string and not an > object and we again we don't autoconvert.
> The problems can be solved by explicitly casting the object to a > string, but since you rarely need to cast elsewhere in PHP, I don't > think anyone thinks of it as a necessary step.
> Originally, I proposed that PHP autoconvert an object to a string > whenever the object has a __toString() and it's necessary to treat the > variable as a string. In the first example, since we're comparing an > object to a string, we would cast down the object to enable the > comparison. This would work just like 1 == '1'. In the second case, > since the function expects a string, we'd also do the cast.
> However, Andi (and others) raised some valid issues about edge cases > and other potential engine problems.
> Is there anything we can do to help out people so that SimpleXML works > as they expect, but doesn't have the potential to unleash hell on PHP > and the bug system?
First of all we need to document that shit very well because it is the first extensions whose objects make use of all the possibilities of the new engine. Hence such bug reports are normal. The main problem for us is differentiating which are real bugs and wich are based on misunderstanding. Perhaps here we see that the engine capabilities make things to comples for the average php user. If that's the case then we have the cooles thing to handle xml but nobody can handle it right.
> Maybe it makes sense to have SimpleXML leaf nodes return as strings > instead of SimpleXML objects? Or does this merely substitute one set > of problems for another? (E.g. this breaks iteratation, what happens > when there's multiple leaves, etc.)
At least a think for some thoughts.
> I don't know what the right answer is, but I feel that the current > solution isn't perfect. It may end up to be the best possible method, > but I'm not yet convinced it is.
sorry me neither.
> -adam
> -- > adam@trachtenberg.com > author of o'reilly's php cookbook > avoid the holiday rush, buy your copy today!
-- Best regards, Marcus mailto:helly@php.net

Andi Gutmans

22 years ago
Basically SimpleXML should know if the property is being fetched for read or not (type is passed such as BP_VAR_R or BP_VAR_W). If the case is BP_VAR_R (read access) then SimpleXML should return the value and not an object. There might be some places in the engine which aren't covered but it's best for the SimpleXML authors to check this out first because in general it should work. At 13:37 27/02/2004 -0500, Adam Maccabee Trachtenberg wrote:

Sterling Hughes

22 years ago
BP_VAR_R just tells the engine not to through a warning when the property doesn't exist. The problem is that we need to handle cases like: $doc = simplexml_load_string('<root><name attr="foo">bar</name>'); echo $doc->name["attr"]; echo $doc->name; Both would be covered by BP_VAR_R AFAIR. What if the string is empty and they want a subnode, ie: <?php $a = $b->foo; echo $a->john; ?> -Sterling On Feb 27, 2004, at 5:33 PM, Andi Gutmans wrote:

Andi Gutmans

22 years ago
I think there isn't a problem with "echo" as it will call the string handler. However, in other cases it might be problematic. Maybe a solution is to implement an equals function so that people would do: if ($doc->name->equals("Hello")) ? I don't think we can support auto-string conversion transparently everywhere in the engine. print and echo are special cases and we also supported make_printable_zval() in PHP 4. Andi At 17:58 27/02/2004 -0500, Sterling Hughes wrote:

Sterling Hughes

22 years ago
On Feb 29, 2004, at 12:03 PM, Andi Gutmans wrote:
> I think there isn't a problem with "echo" as it will call the string > handler. However, in other cases it might be problematic. > Maybe a solution is to implement an equals function so that people > would do: > if ($doc->name->equals("Hello")) ? > > I don't think we can support auto-string conversion transparently > everywhere in the engine. print and echo are special cases and we also > supported make_printable_zval() in PHP 4.
Well, the comparison operator should be overloaded if one of the objects is an overloaded object imho. My concern lies more with functions like utf8_encode() not properly getting the contents of the XML string - but I haven't looked into it too much - I'll try and get some hacking done on the cruise. -Sterling

Andi Gutmans

22 years ago
At 12:20 29/02/2004 -0500, Sterling Hughes wrote:
>On Feb 29, 2004, at 12:03 PM, Andi Gutmans wrote: > >>I think there isn't a problem with "echo" as it will call the string >>handler. However, in other cases it might be problematic. >>Maybe a solution is to implement an equals function so that people would do: >>if ($doc->name->equals("Hello")) ? >> >>I don't think we can support auto-string conversion transparently >>everywhere in the engine. print and echo are special cases and we also >>supported make_printable_zval() in PHP 4. > > >Well, the comparison operator should be overloaded if one of the objects >is an overloaded object imho.
The problem is that user-land overloading can't be supported. C extensions might be able to be supported but I don't think it's a good idea to start hacking this into PHP. It wouldn't end at the comparison operator but people would want it to work everywhere.
>My concern lies more with functions like utf8_encode() not properly >getting the contents of the XML string - but I haven't looked into it too >much - I'll try and get some hacking done on the cruise.
The way to do it today is to do a cast to (string) although I admit it's not a beautiful solution. Andi

Sterling Hughes

22 years ago
On Feb 29, 2004, at 12:31 PM, Andi Gutmans wrote:
> At 12:20 29/02/2004 -0500, Sterling Hughes wrote: > >> On Feb 29, 2004, at 12:03 PM, Andi Gutmans wrote: >> >>> I think there isn't a problem with "echo" as it will call the string >>> handler. However, in other cases it might be problematic. >>> Maybe a solution is to implement an equals function so that people >>> would do: >>> if ($doc->name->equals("Hello")) ? >>> >>> I don't think we can support auto-string conversion transparently >>> everywhere in the engine. print and echo are special cases and we >>> also supported make_printable_zval() in PHP 4. >> >> >> Well, the comparison operator should be overloaded if one of the >> objects is an overloaded object imho. > > The problem is that user-land overloading can't be supported. C > extensions might be able to be supported but I don't think it's a good > idea to start hacking this into PHP. It wouldn't end at the comparison > operator but people would want it to work everywhere. >
I don't want user overloading - I've been consistently against that for objects of all types. I want it internally cause its important to be able to overload all operations for something like SimpleXML to properly work. The same applies to ext/mono (has the same issues as java, but even more due to field and property distinctions.)
>> My concern lies more with functions like utf8_encode() not properly >> getting the contents of the XML string - but I haven't looked into it >> too much - I'll try and get some hacking done on the cruise. > > The way to do it today is to do a cast to (string) although I admit > it's not a beautiful solution. >
Right - what I don't understand is that why doesn't convert_to_string_ex() handle this? -Sterling

Andi Gutmans

22 years ago
At 12:36 29/02/2004 -0500, Sterling Hughes wrote:
>>The problem is that user-land overloading can't be supported. C >>extensions might be able to be supported but I don't think it's a good >>idea to start hacking this into PHP. It wouldn't end at the comparison >>operator but people would want it to work everywhere. > >I don't want user overloading - I've been consistently against that for >objects of all types. I want it internally cause its important to be able >to overload all operations for something like SimpleXML to properly >work. The same applies to ext/mono (has the same issues as java, but even >more due to field and property distinctions.) > >>>My concern lies more with functions like utf8_encode() not properly >>>getting the contents of the XML string - but I haven't looked into it >>>too much - I'll try and get some hacking done on the cruise. >> >>The way to do it today is to do a cast to (string) although I admit it's >>not a beautiful solution. > >Right - what I don't understand is that why doesn't convert_to_string_ex() >handle this?
Because it's much more complicated than just changing convert_to_string_ex(). You have to modify all comparison operators to support this and god knows what else. Andi