How can I set text value of SimpleXmlElement without using its parent?
22,229
Solution 1
You can do with a SimpleXMLElement self-reference:
$firstC->{0} = "Victory!!"; // hackity, hack, hack!
// -or-
$firstC[0] = "Victory!!";
found after looking at
var_dump((array) reset($xml->xpath("(//c)[3]")))
This also works with unset
operations as outlined in an answer to:
Solution 2
The real answer is: you kind of can't.
On the other hand you can use DOM for it, e.g.
dom_import_simplexml($node)->nodeValue = 'foo';
Related videos on Youtube
Author by
Kamil Szot
I'm mostly PHP developer. But I am interested in a lot of things.
Updated on July 09, 2022Comments
-
Kamil Szot almost 2 years
I want to set text of some node found by xpath()
<?php $args = new SimpleXmlElement( <<<XML <a> <b> <c>text</c> <c>stuff</c> </b> <d> <c>code</c> </d> </a> XML ); // I want to set text of some node found by xpath // Let's take (//c) for example // convoluted and I can't be sure I'm setting right node $firstC = reset($args->xpath("//c[1]/parent::*")); $firstC->c[0] = "test 1"; // like here: Found node is not actually third in its parent. $firstC = reset($args->xpath("(//c)[3]/parent::*")); $firstC->c[2] = "test 2"; // following won't work for obvious reasons, // some setText() method would be perfect but I can't find nothing similar, $firstC = reset($args->xpath("//c[1]")); $firstC = "test"; // maybe there's some hack for it? $firstC = reset($args->xpath("//c[1]")); $firstC->{"."} = "test"; // nope, just adds child named . $firstC->{""} = "test"; // still not right, 'Cannot write or create unnamed element' $firstC["."] = "test"; // still no luck, adds attribute named . $firstC[""] = "test"; // still no luck, 'Cannot write or create unnamed attribute' $firstC->addChild('','test'); // grr, 'SimpleXMLElement::addChild(): Element name is required' $firstC->addChild('.','test'); // just adds another child with name . echo $args->asXML(); // it outputs: // // PHP Warning: main(): Cannot add element c number 2 when only 1 such elements exist // PHP Warning: main(): Cannot write or create unnamed element // PHP Warning: main(): Cannot write or create unnamed attribute // PHP Warning: SimpleXMLElement::addChild(): Element name is required // <?xml version="1.0"? > // <a> // <b> // <c .="test">test 1<.>test</.><.>test</.></c> // <c>stuff</c> // </b> // <d> // <c>code</c> // <c>test 2</c></d> // </a>
-
hakre over 10 yearsWhy is that the kind of real answer?
-
Josh Davis over 10 yearsThat's because at the time of writing there was no supported way to do it, and I don't think it's changed. The fact that setting the value of a non-existing node named "0" changes a node's textContent may be a side effect, the result of sheer luck. It may unexpectedly stop working.
-
hakre over 10 yearsThe supported way of doing that is outlined in the accepted answer which was there already at the time you answered here for quite some time (just asked to learn more). That way actually is supported and it's documented in PHP's src, you find the implementation here: lxr.php.net/xref/PHP_5_3/ext/simplexml/… - the zero offset is always available for all element nodes. Also your answer misses to check the node-type of a SimpleXMLElement object and risks to produce errors and also side-effects.
-
Josh Davis over 10 yearsThat's still an implementation detail though. The fact that you had to link to the (uncommented) source code rather than the manual only makes it clearer. Get the developer to officially support it by documenting it and I'll consider it an official feature. Otherwise, to me it's literally an undocumented behaviour.
-
quickshiftin about 10 yearsThis should be the correct answer as it is the technique prescribed by php since a long time ago. The accepted answer is a hack and use-at-your-own-risk 'solution'.
-
Christian Studer over 6 yearsNote that the first variant using the object notation doesn't seem to work anymore in PHP 7.