$xml = '<p><a>1</a><b><c>1</c></b></p>';
$dom = new DomDocument;
$dom->loadXML($xml);
$p = $dom->childNodes->item(0);
echo $dom->saveXML($p);
the above will print back
<p>
<a>1</a>
<b><c>1</c></b>
</p>
assume need to replace the p node/eleemnt to new_p
what is the ideal way except do a loop like below? (below is doable)
$fragment = '';
foreach ($p->childNodes as $a)
{
$fragment .= $dom->saveXML($a);
}
$new_doc = new DomDocument;
$new_doc->loadXML('<new_node/>');
$f = $new_doc->createDocumentFragment();
$f->appendXML($fragment);
$new_doc->documentElement->appendChild($f);
echo $new_doc->saveXML();
expected results
<new_node><a>1</a><b><c>1</c></b></new_node>
As Mark already pointed out, manipulating XML is easiest with XSLT. And you don’t have to write any loops, the thinking is done by the XSLT processor of your choice.
A simple how-to with XSLT
Here’s how the XSLT might look like (Google for “Identity transform XSLT” for some tutorials).
The basics are simple: this type of XSLT transformation copies everything as-is, unless there’s a specific rule (template-match in XSLT) that specifies an exception (in this case for
<p>elements). Note: it doesn’t matter how deep your p-tags are nested, which makes it ideal for transforming XML.Calling XSLT from PHP
This is relatively straightforward, since PHP has a built-in module for XSL. Here’s how you can do it (here’s more information):
Output is as expected (optional indentation can be set with
<xsl:output indent="yes"/>:As you can see: no loops or iterations 😉
PS: XSLT is a widely adopted and stable standard. You don’t have to worry about proper escaping, parsing issues with CDATA sections or entities, because XSLT guarantees the output to be valid XML. This saves a whole lot of headaches as opposed to doing this by hand.