SimpleXMLElement::addChild

(PHP 5 >= 5.1.3, PHP 7, PHP 8)

SimpleXMLElement::addChild Adds a child element to the XML node

Description

public SimpleXMLElement::addChild(string $qualifiedName, ?string $value = null, ?string $namespace = null): ?SimpleXMLElement

Adds a child element to the node and returns a SimpleXMLElement of the child.

Parameters

qualifiedName

The name of the child element to add.

value

If specified, the value of the child element.

namespace

If specified, the namespace to which the child element belongs.

Return Values

The addChild method returns a SimpleXMLElement object representing the child added to the XML node on success; null on failure.

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&#xD3;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>

See Also

add a note

User Contributed Notes 12 notes

up
41
frosty dot z at freesbee dot fr
11 years ago
To complete Volker Grabsch's comment, stating :
"Note that although addChild() escapes "<" and ">", it does not escape the ampersand "&"."

To work around that problem, you can use direct property assignment such as :

<?php
$xmlelement
->value = 'my value < > &';
// results in <value>my value &lt; &gt; &amp;</value>
?>

instead of doing :

<?php
$xmlelement
->addChild('value', 'my value < > &');
// results in <value>my value &lt; &gt; &</value> (invalid XML)
?>

See also: http://stackoverflow.com/questions/552957 (Rationale behind SimpleXMLElement's handling of text values in addChild and addAttribute)

HTH
up
27
alex dot feraud at gmail dot com
13 years ago
Here is a class with more functions for SimpleXMLElement :

<?php
/**
*
* Extension for SimpleXMLElement
* @author Alexandre FERAUD
*
*/
class ExSimpleXMLElement extends SimpleXMLElement
{
/**
* Add CDATA text in a node
* @param string $cdata_text The CDATA value to add
*/
private function addCData($cdata_text)
{
$node= dom_import_simplexml($this);
$no = $node->ownerDocument;
$node->appendChild($no->createCDATASection($cdata_text));
}

/**
* Create a child with CDATA value
* @param string $name The name of the child element to add.
* @param string $cdata_text The CDATA value of the child element.
*/
public function addChildCData($name,$cdata_text)
{
$child = $this->addChild($name);
$child->addCData($cdata_text);
}

/**
* Add SimpleXMLElement code into a SimpleXMLElement
* @param SimpleXMLElement $append
*/
public function appendXML($append)
{
if (
$append) {
if (
strlen(trim((string) $append))==0) {
$xml = $this->addChild($append->getName());
foreach(
$append->children() as $child) {
$xml->appendXML($child);
}
} else {
$xml = $this->addChild($append->getName(), (string) $append);
}
foreach(
$append->attributes() as $n => $v) {
$xml->addAttribute($n, $v);
}
}
}
}
?>
up
13
johninen at gmail dot com
9 years ago
In the docs for google sitemaps it is required an element for mobile sitemaps that looks like this: <mobile:mobile/>

I used some time to figure out how to make it, but it is quite simple when understood.

$mobile_schema = 'http://www.google.com/schemas/sitemap-mobile/1.0';

//Create root element
$xml_mobile = new SimpleXMLElement('
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:mobile="'.$mobile_schema.'"></urlset>
');

//Add required children
$url_mobile = $xml_b_list_mobile->addChild('url');
$url_mobile->addChild('loc', 'your-mobile-site-url');
$url_mobile->addChild('mobile:mobile', null, $mobile_schema);

For this to work properly the attribute xmlns:mobile must be set in the root node, and then used as namespace(third argument) when creating the mobile:mobile child with null as value.
up
3
nwarap
6 years ago
Want to continue the ampersand (&) chain problem.

Sometimes, you would want to assign (=) addChild.
This trick will helps you to do this.

<?php
$webOrders
= new SimpleXMLElement('<?xml version="1.0"?><WebOrders></WebOrders>');
$webOrder = $webOrders->addChild('WebOrder');
$product = $webOrder->addChild('Product');
$product[0] = 'T&M';
$product->addAttribute('price', 19.99);
$product->addAttribute('qty', 2);
var_dump($webOrders->asXML());
?>

OUTPUT would be:

<?xml version="1.0" encoding="UTF-8"?>
<WebOrders>
<WebOrder>
<Product price="19.99" qty="2">T&amp;M</Product>
</WebOrder>
</WebOrders>
up
7
Volker Grabsch
13 years ago
Note that although addChild() escapes "<" and ">", it does not escape the ampersand "&".

So addChild() is unsuited to handle user-defined input!

Instead, you will have to replace all "&" with "&amp;" before calling addChild().

Or, use htmlspecialchars() which also replaces other characters, but won't do any harm as addChild() won't replace those again.
up
1
ivan dot kakurov at gmail dot com
11 years ago
Here's my solution for creating XML from Multidimensional Array.
<?php
//DATA
$xmlDAta = array(
array(
"name" => "nameVal",
"value" => "valVal",
"css" => "cssVal"
),
array(
"name" => "name1Val",
"value" => "val1Val",
"css" => "css1Val"
),
"tname" => array(
array(
"iTname" => "iTname",
"iTname2" => "iTname1",
"iTname2" => "iTname2",
"iTbname3" => array(
"iiTbname" => "tbName",
"iiTbname1" => "tbName1",
),
),
),
"tdata" => "otheerDAta"
);

/**
* Create XML using string or array
*
* @param mixed $data input data
* @param SimpleXMLElement $xml
* @param string $child name of first level child
*
* @return adding Xml formated data into SimpleXmlElement
*/

function data2XML(array $data, SimpleXMLElement $xml, $child = "items")
{

foreach(
$data as $key => $val) {
if(
is_array($val)) {

if(
is_numeric($key)) {
$node = $xml->addChild($child);
$nodes = $node->getName($child);
} else {

$node = $xml->addChild($key);
$nodes = $node->getName($key);
}

$node->addChild($nodes, self::data2Xml($val, $node));
} else {
$xml->addChild($key, $val);
}
}

}

//Use

$xml = new SimpleXMLElement("<root/>");
Util::data2XML($xmlDAta, $xml, "Items");

?>
up
1
fluxlicious at gmail dot com
1 year ago
The class below allows you to write CDATA and to add additional attributes.

<?php
class SimpleXMLElementExtended extends \SimpleXMLElement
{
public function
addChildWithCData($name, $value)
{
$child = parent::addChild($name);
$element = dom_import_simplexml($child);
$docOwner = $element->ownerDocument;
$element->appendChild($docOwner->createCDATASection($value));
return
$child;
}
}
?>

Example:
<?php
$xml
= new SimpleXMLElementExtended('<xml></xml>');
$content = $xml->addChildWithCData('content', 'Title of the page');
$content->addAttribute('id', 1);
$content->addAttribute('enabled', 'true');

// Output:
// <xml>
// <content id="1" enabled="true"><![CDATA[Title of the page]]></content>
// </xml>
?>
up
1
caffeinatedbits
1 year ago
Just in case anyone else, like me, was trying to figure out a way to remove child elements...

<?php

$xml
= <<<EOF
<?xml version="1.0" encoding="utf-8" ?>
<Animals>
<Dog breed="chihuahua"/>
<Dog breed="poodle"/>
<Dog breed="invalid"/>
</Animals>
EOF;

$animals = new SimpleXMLElement($xml);

unset(
$animals->Dog[2]);

echo
$animals->asXML();

// <?xml version="1.0" encoding="utf-8"?>
// <Animals>
// <Dog breed="chihuahua"/>
// <Dog breed="poodle"/>
//
// </Animals>

?>

Note: you cannot remove elements while iterating children, otherwise it will break the Iterator. Example:

<?php

$xml
= <<<EOF
<?xml version="1.0" encoding="utf-8" ?>
<Animals>
<Dog breed="chihuahua"/>
<Dog breed="poodle"/>
<Dog breed="invalid"/>
</Animals>
EOF;

$animals = new SimpleXMLElement($xml);

$allowed_breeds = [
'chihuahua',
'poodle'
];

try {
$index = 0;
foreach (
$animals->Dog as $dog) {
if (!
in_array($dog['breed'], $allowed_breeds)) {
unset(
$animals->Dog[$index]);
}
$index++;
}
} catch (
Throwable $e) {
echo
$e->getMessage();
// SimpleXMLElement is not properly initialized
}

?>
up
0
carlos dot eduardo dot debiasi at gmail dot com
3 years ago
I create this function so you can through and array build the XML, this allows multiple keys with the same value.
The structure must follow

[
'key' => 'nameOfTheKey',
'attributes' => ['id' => '1'],
'fields' => [
['key' => 'fieldSamName', 'value' => '1'],
['key' => 'fieldSamName', 'value' => '1'],
['key' => 'fieldSamName', 'value' => '2'],
['key' => 'fieldWithChild', 'fields' => [
['key' => 'car', 'value' => '2'],
['key' => 'human', 'value' => '3'],
]],
]
];

Function:
function toXml(\SimpleXMLElement $node, array $data)
{
foreach ($data as $key => $value) {
$key = $value['key'];
if (isset($value['value'])) {
$newNode = $node->addChild($key, $value['value']);
if (isset($value['attributes'])) {
foreach ($value['attributes'] as $keyAttr => $valueAttr) {
$newNode->addAttribute($keyAttr, $valueAttr);
}
}
} else {
$newNode = $node->addChild($key);
if (isset($value['attributes'])) {
foreach ($value['attributes'] as $keyAttr => $valueAttr) {
$newNode->addAttribute($keyAttr, $valueAttr);
}
}
}
if (isset($value['fields'])) {
foreach ($value['fields'] as $keyField => $valueField) {
$this->toXml($newNode, [$keyField => $valueField]);
}
}
}
}
up
0
passerbyxp at gmail dot com
11 years ago
Be aware that simply because you can <?php $dom->addChild();?> doesn't mean your XML is valid under simple XML itself:

<?php
$dom
=simplexml_load_string("<test></test>");
$dom->addChild("3D","1,2,3");
$xml=$dom->asXML();
echo
$xml;
/* echos:
<?xml version="1.0"?>
<test><3D>1,2,3</3D></test>
*/

$dom=simplexml_load_string($xml);
/*
generates a whole lots of warnings,
and refuses to create an object.
*/
?>

Same in PHP 5.3 and 5.4
up
0
felipenmoura at gmail dot com
13 years ago
This method returns a reference to the specific SimpleXMLElement.
If you use:
<?php
$xml
= new SimpleXMLElement('<root></root>');
$xml->father['name']= 'Fathers name'; // creates automatically a father tag with attribute name
$son= $xml->father->addChild('son'); // uses the first father tag
$son['name']= 'first son';
$otherSon= $xml->father->addChild('son'); // uses the first father tag but now, in a second son tag
$otherSon['name']= 'second son';

echo
htmlentities($xml->asXML());
?>

The result will be
<root>
<father>
<son name='first son' />
<son name='second son' />
</father>
</root>

So, once you change something to the just added child, you are actually accessing the element inside the SimpleXMLElement as a reference.
up
-3
jerikojerk
13 years ago
If you're looking for a way to append children you may be interested in this:

<?php
$x
= new SimpleXMLElement('<root name="toplevel"></root>');
$f1 = new SimpleXMLElement('<child pos="1">alpha</child>');
$f2 = new SimpleXMLElement('<child pos="2">beta</child>');
$f3 = new SimpleXMLElement('<child pos="3">gamma</child>');

$x->{$f1->getName()} = $f1;
$x->{$f2->getName()}[] = $f2;
$x->{$f3->getName()}[] = $f3;

echo
'count child=',$x->count(),"\n";
echo
$x->asXML();

foreach (
$x->children() as $foo )
{
var_dump($foo);
}

?>
To Top