SimpleXMLElement::addAttribute
(PHP 5 >= 5.1.3)
SimpleXMLElement::addAttribute — Adds an attribute to the SimpleXML element
Description
$name
[, string $value
[, string $namespace
]] )Adds an attribute to the SimpleXML element.
Parameters
-
name
-
The name of the attribute to add.
-
value
-
The value of the attribute.
-
namespace
-
If specified, the namespace to which the attribute belongs.
Return Values
No value is returned.
Examples
Note:
Listed examples may include example.php, which refers to the XML string found in the first example of the basic usage guide.
Example #1 Add attributes and children to a SimpleXML element
<?php
include 'example.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();
?>
The above example will output something similar to:
<?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>
- Функция SimpleXMLElement::addAttribute() - Добавляет атрибут к SimpleXML-элементу
- Функция SimpleXMLElement::addChild() - Добавляет дочерний элемент к узлу XML
- Функция SimpleXMLElement::asXML() - Возвращает сформированный XML документ в виде строки используя SimpleXML элемент
- Функция SimpleXMLElement::attributes() - Возвращает атрибуты элемента
- Функция SimpleXMLElement::children() - Поиск дочерних элементов данного узла
- Функция SimpleXMLElement::__construct() - Создание нового SimpleXMLElement объекта
- Функция SimpleXMLElement::count() - Считает количество дочерних элементов у текущего элемента
- Функция SimpleXMLElement::getDocNamespaces() - Возвращает объявленное пространство имен в документе
- Функция SimpleXMLElement::getName() - Получение имени XML элемента
- Функция SimpleXMLElement::getNamespaces() - Получение пространств имен, используемых в документе
- Функция SimpleXMLElement::registerXPathNamespace() - Создает префикс/пространство имен контекста для следующего XPath запроса
- Функция SimpleXMLElement::saveXML() - Псевдоним SimpleXMLElement::asXML
- Функция SimpleXMLElement::__toString() - Returns the string content
- Функция SimpleXMLElement::xpath() - Запускает XPath запрос к XML данным
Коментарии
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>
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);
?>
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>
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>
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">
?>
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.
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/>
?>