Starting with this empty XML:
$xml = '<?xml version="1.0" encoding="utf-8" ?><email/>';
We want add it this email address:
$email = '[email protected]';
With DOMDocument:
With DOMDocument we have to init the object, to load XML, to set ->formatOutput (if we want an indented output) and to init DOMXPath to perform complex XML searches:
$dom = new DOMDocument();
$dom->loadXML( $xml );
$dom->formatOutput = True;
$xpath = new DOMXPath($dom);
Then we search for the last <field> element with id starting by “email”:
$found = $xpath->query( '(//field[starts-with(@id,"email")])[last()]' );
If the item is found (not in our case, because we have an empty XML, but sure in next case), we get id attribute and, using substr, we extract from it the last id number, then we increment it by 1 to set id of new added email. If no item is found, we set new id to “email1”:
if( $found->length )
{
$oldId = substr( $found->item(0)->getAttribute('id'), 5 );
$newId = 'email' . ( $oldId + 1 );
}
else
{
$newId = 'email1';
}
At this point, we create the <field> child node and we set id attribute:
$child = $dom->createElement( 'field' );
$child->setAttribute( 'id', $newId );
Then, we append to it the <value> node with new email as value:
$child->appendChild( $dom->createElement( 'value', $email ) );
At the end, we append $child node to main <email> node:
$dom->getElementsByTagName( 'email' )->item(0)->appendChild( $child );
To print modified XML:
echo $dom->saveXML();
In this eval.in demo you can see the result after adding two email addresses.
With SimpleXML:
With SimpleXML we can't format output, but the start is more concise. We load the XML and directly we can search for XPath pattern:
$sxml = simplexml_load_string( $xml );
$found = $sxml->xpath( '(//field[starts-with(@id,"email")])[last()]' );
In this case, the result is an array, so we perform the id check using array syntax, also for retrieve id attribute:
if( count( $found ) )
{
$oldId = substr( $found[0]['id'], 5 );
$newId = 'email' . ( $oldId + 1 );
}
else
{
$newId = 'email1';
}
The syntax for adding the child is very similar to DOMDocument:
$child = $sxml->addChild( 'field' );
$child->addAttribute( 'id', $newId );
$child->addChild( 'value', $email );
To print modified XML:
echo $sxml->asXML();
SimpleXML use a syntax more concise and comfortable than DOMDocument and, by general opinion, is faster. Conversely, DOMDocument is more powerful and customizable.
XPath pattern explained:
┌────────────────────────────────────────────────┐
│ ┌───┴────┐
│ retrieve only last node of this query
┌────────────────┴────────────────┐┌──┴───┐
(//field[starts-with(@id,"email")])[last()]
└─┬─────────────────────────────┘
┌─┘
// find following patter no matter where it is
field <field> node
[ with
starts-with ┐ attribute “id”
(@id,"email") ┘ starts with “email”
]