I needed a way to update an attribute, but I could not find any documented way to do this.
After much experimentation, here's my findings of what works - the answer was so simple it took me 8 tries to figure it out :-)
Given the following example:
<?php
$xml = <<<EOF
<?xml version="1.0" encoding="utf-8" ?>
<Animals>
<Dog/>
</Animals>
EOF;
$animals = new SimpleXMLElement($xml);
echo $animals->Dog->asXML();
// <Dog/>
?>
Test #6 - maybe directly modifying the attributes() Iterator like an array will secretly call __set() magic method?
TL;DR: yep
<?php
...
$animals->Dog->addAttribute('breed', "chihuahua");
echo $animals->Dog->asXML();
// <Dog breed="chihuahua">
$dogAttrs = $animals->Dog->attributes();
// object(SimpleXMLElement)#4 (1) {
// ["@attributes"]=>
// array(1) {
// ["breed"]=>
// string(9) "chihuahua"
// }
// }
$dogAttrs['breed'] = "poodle";
// works!
echo $animals->Dog->asXML();
// <Dog breed="poodle">
?>
Test #7 - maybe I don't even need to call attributes() at all?
TL;DR: I sure don't!
<?php
...
$animals->Dog->addAttribute('breed', "chihuahua");
echo $animals->Dog->asXML();
// <Dog breed="chihuahua">
$animals->Dog['breed'] = "poodle";
// works!
echo $animals->Dog->asXML();
// <Dog breed="poodle">
?>
Test #8 - Maybe I never needed to call addAttribute() in the first place?
TL;DR: nope, I can skip that altogether!
<?php
...
$animals->Dog['breed'] = "chihuahua";
// works!
echo $animals->Dog->asXML();
// <Dog breed="chihuahua">
$animals->Dog['breed'] = "poodle";
// works!
echo $animals->Dog->asXML();
// <Dog breed="poodle">
?>
FYI: I also submitted another separate note with what does NOT work just in case you, like me, are curious and tempted to try another way.SimpleXMLElement::addAttribute
Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.
SimpleXMLElement::addAttribute
Референца за `simplexmlelement.addattribute.php` со подобрена типографија и навигација.
SimpleXMLElement::addAttribute
(PHP 5 >= 5.1.3, PHP 7, PHP 8)
SimpleXMLElement::addAttribute — Додава атрибут на SimpleXML елементот
= NULL
$qualifiedName, string $value, ?string $namespace = null): voidДодава атрибут на SimpleXML елементот.
Параметри
qualifiedName-
Името на атрибутот што треба да се додаде.
value-
Вредноста на атрибутот.
namespace-
Ако е наведено, просторот на имиња на кој припаѓа атрибутот.
Вратени вредности
Не се враќа вредност.
Примери
Забелешка:
Наведените примери може да вклучуваат
examples/simplexml-data.php, што се однесува на XML стринг пронајден во првиот пример од основна употреба guide.
Пример #1 Додавање атрибути и деца на SimpleXML елемент
<?php
include 'examples/simplexml-data.php';
$sxe = new SimpleXMLElement($xmlstr);
$sxe->addAttribute('type', 'documentary');
$movie = $sxe->addChild('movie');
$movie->addChild('title', 'PHP2: More Parser Stories');
$movie->addChild('plot', 'This is all about the people who make it work.');
$characters = $movie->addChild('characters');
$character = $characters->addChild('character');
$character->addChild('name', 'Mr. Parser');
$character->addChild('actor', 'John Doe');
$rating = $movie->addChild('rating', '5');
$rating->addAttribute('type', 'stars');
echo $sxe->asXML();
?>Горниот пример ќе прикаже нешто слично на:
<?xml version="1.0" standalone="yes"?>
<movies type="documentary">
<movie>
<title>PHP: Behind the Parser</title>
<characters>
<character>
<name>Ms. Coder</name>
<actor>Onlivia Actora</actor>
</character>
<character>
<name>Mr. Coder</name>
<actor>El ActÓr</actor>
</character>
</characters>
<plot>
So, this language. It's like, a programming language. Or is it a
scripting language? All is revealed in this thrilling horror spoof
of a documentary.
</plot>
<great-lines>
<line>PHP solves all my web problems</line>
</great-lines>
<rating type="thumbs">7</rating>
<rating type="stars">5</rating>
</movie>
<movie>
<title>PHP2: More Parser Stories</title>
<plot>This is all about the people who make it work.</plot>
<characters>
<character>
<name>Mr. Parser</name>
<actor>John Doe</actor>
</character>
</characters>
<rating type="stars">5</rating>
</movie>
</movies>
Белешки од корисници Управување со PDO конекции
You cannot use this to update an existing attribute's value.
Instead, get a DOM version of the SimpleXMLElement and use setAttribute, as per:
$XML = '<element a="aa">Text</element>';
$snode = new simple_xml_element($XML);
$dnode = dom_import_simplexml($snode);
$dnode->setAttribute('a', 'bb');
Resulting XML for the node is:
<element a="bb">Text</element>If the attribute already exists, addAttribute does nothing.
example:
<?php
$xml_string = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item id="foo">
<root>
XML;
$xml = simplexml_load_string($xml_string);
$xml->item->addAttribute('id', 'bar');
echo $xml->asXML();
?>
The above examples will output:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<item id="foo">
<root>Just found another gem. Need to remove an attribute? That's simple too!
<?php
$xml = <<<EOF
<?xml version="1.0" encoding="utf-8" ?>
<Animals>
<Dog breed="chihuahua"/>
</Animals>
EOF;
$animals = new SimpleXMLElement($xml);
echo $animals->Dog->asXML();
// <Dog breed="chihuahua"/>
unset($animals->Dog['breed']);
echo $animals->Dog->asXML();
// <Dog/>
?>If you need an Namespace, you must write a Prefix of the Namespace + the Name of the Attribute ("prefix:name") as the first parameter AND the uri as the third one. (I don't know why?!)
Example code:
<?php
$xml = new SimpleXMLElement("<packagedElement></packagedElement>");
$xml->addAttribute("xmi:type", "uml:Class", "http://schema.omg.org/spec/XMI/2.1");
echo $xml->asXml();
?>
Output:
<packagedElement xmlns:xmi="http://schema.omg.org/spec/XMI/2.1" xmi:type="uml:Class"></packagedElement>I needed a way to update an attribute, but I could not find any documented way to do this.
TL;DR: It's not only possible, but unbelievably simple. See the other note I submitted for what actually works (sorry, I could not fit it all in a single note due to the 4095 character limit).
After much experimentation, here's my findings of what does NOT work; hopefully, it saves you the time and frustration it cost me.
Given the following example:
<?php
$xml = <<<EOF
<?xml version="1.0" encoding="utf-8" ?>
<Animals>
<Dog/>
</Animals>
EOF;
$animals = new SimpleXMLElement($xml);
echo $animals->Dog->asXML();
// <Dog/>
?>
Test #1 - attempt to call addAttribute() twice
TL;DR: PHP Warning: SimpleXMLElement::addAttribute(): Attribute already exists
<?php
...
$animals->Dog->addAttribute('breed', "chihuahua");
echo $animals->Dog->asXML();
// <Dog breed="chihuahua"/>
$animals->Dog->addAttribute('breed', "poodle");
// PHP Warning: SimpleXMLElement::addAttribute(): Attribute already exists
echo $animals->Dog->asXML();
// <Dog breed="chihuahua"/>
?>
Test #2 - attempt to iterate attributes() (an Iterator) by reference
TL;DR: An iterator cannot be used with foreach by reference
<?php
...
$animals->Dog->addAttribute('breed', "chihuahua");
echo $animals->Dog->asXML();
// <Dog breed="chihuahua">
try {
foreach ($animals->Dog->attributes() as $attr => &$value) {
if ("breed" === $attr) {
$value = "poodle";
}
}
} catch (Throwable $e) {
echo $e->getMessage();
// An iterator cannot be used with foreach by reference
}
echo $animals->Dog->asXML();
// <Dog breed="chihuahua">
?>
Test #3 - attempt to re-parse child element and then call addAttribute() on the newly parsed element, as suggested in a note I found here
TL;DR: PHP Warning: SimpleXMLElement::addAttribute(): Attribute already exists
<?php
...
$animals->Dog->addAttribute('breed', "chihuahua");
echo $animals->Dog->asXML();
// <Dog breed="chihuahua">
$animals->Dog = new SimpleXMLElement($animals->asXML());
$animals->Dog->addAttribute('breed', "poodle");
// PHP Warning: SimpleXMLElement::addAttribute(): Attribute already exists
echo $animals->Dog->asXML();
// <Dog breed="chihuahua">
?>
Test #4 - attempt to modify @attributes array element
TL;DR: PHP Notice: Indirect modification of overloaded element of SimpleXMLElement has no effect
<?php
...
$animals->Dog->addAttribute('breed', "chihuahua");
echo $animals->Dog->asXML();
// <Dog breed="chihuahua">
$dogAttrs = $animals->Dog->attributes();
// object(SimpleXMLElement)#4 (1) {
// ["@attributes"]=>
// array(1) {
// ["breed"]=>
// string(9) "chihuahua"
// }
// }
$dogAttrs['@attributes']['breed'] = "poodle";
// PHP Notice: Indirect modification of overloaded element of SimpleXMLElement has no effect
echo $animals->Dog->asXML();
// <Dog breed="chihuahua">
?>
Test #5 - cast attributes() to array and set value of 'breed' element
TL;DR: does not update value in original object
<?php
...
$animals->Dog->addAttribute('breed', "chihuahua");
echo $animals->Dog->asXML();
// <Dog breed="chihuahua">
$dogAttrs = (array) $animals->Dog->attributes();
// array(1) {
// ["@attributes"]=>
// array(1) {
// ["breed"]=>
// string(9) "chihuahua"
// }
// }
$dogAttrs['@attributes']['breed'] = "poodle";
echo $animals->Dog->asXML();
// <Dog breed="chihuahua">
?>You can access a node child with his name this way :
<?php
$root = new SimpleXMLElement($filePath);
echo $root->nodeName->attributes;
// It works recursivly so this will work too
echo $root->nodeName->subNodeName->attributes();
?>
But if you want to ADD an attribute to a children you MUST use the children() method to access and modfiy it or it will modify the parent's attributes.
<?php
// Add a subnode
$element->nodeName->addChild('subNodeName', "whatever you want");
// Get the pos in the childrens of the parent node
$lastNodePos = $element->nodeName->count()-1;
// Get the parents node childrens
$nodeChildrens = $element->nodeName->children();
// Add an attribute to the last created
$nodeChildrens[$lastNodePos]->addAttribute('attributeName', "The attribute value);
?>