Reputation: 101
I am looking to append an xml tree to another.
For example, I want the following xml:
<a>
<b>
<c/>
</b>
</a>
To have the following xml inside it:
<n:d xmlns:xsl="namespace">
<n:e>
<n:f/>
</n:e>
</n:d>
so that it looks like this:
<a>
<b>
<c/>
<n:d xmlns:n="namespace">
<n:e>
<n:f/>
</n:e>
</n:d>
</b>
</a>
The code that I have attempting and failing to do this is as follows:
$doc1 = new DOMDocument();
$doc2 = new DOMDocument();
$doc1->loadXML($xml1);
$doc2->loadXML($xml2);
$node_To_Insert = $doc2->getElementsByTagName('d')->item(0);
$node_To_Be_Inserted_To = $doc1->getElementsByTagName('b')->item(0);
$node_To_Be_Inserted_To->appendChild($doc1->importNode($node_To_Insert));
echo '<pre>'.htmlspecialchars(print_r($doc1->saveXML(),true)).'</pre>';
The current result I get from the echo:
<a>
<b>
<c/>
<n:d xmlns:n="namespace" />
</b>
</a>
I am out of ideas that aren't impossible to read, or aren't seemingly stupidly roundabout.
Any help would be appreciated. Thank you in advance.
Upvotes: 1
Views: 44
Reputation: 107642
Alternatively, the native way to handle XML transformations such as merging documents is using XSLT, the special-purpose language designed primarily for this need to re-structure, re-style, re-format XML documents for various end-use needs.
Much like another special-purpose language, SQL, is for databases, XSLT is handy with XML files. And PHP comes equipped with an XSLT processor (might need to enable the extension: php_xsl.so
) .
XSLT (save as .xsl or .xslt file)
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<!-- Identity Transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="b">
<b>
<xsl:copy-of select="c" />
<xsl:copy-of select="document('doc2.xml')"/>
</b>
</xsl:template>
</xsl:transform>
PHP (load only first doc as XSLT above loads second doc at specific node)
$doc1 = new DOMDocument();
$doc1->load('doc1.xml');
$xsl = new DOMDocument;
$xsl->load('XSLTScript.xsl');
// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);
// Transform XML source
$newXml = $proc->transformToXML($doc1);
// Save output to file
$xmlfile = 'Output.xml';
file_put_contents($xmlfile, $newXml);
OUTPUT
<?xml version="1.0" encoding="UTF-8"?>
<a>
<b>
<c/>
<n:d xmlns:n="namespace">
<n:e>
<n:f/>
</n:e>
</n:d>
</b>
</a>
Upvotes: 1
Reputation: 32511
Your solution is very close. You only need to perform a deep copy with importNode to get the result you want.
$node_To_Be_Inserted_To->appendChild($doc1->importNode($node_To_Insert, true));
Upvotes: 2