1

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.

2 Answers 2

2

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));
Sign up to request clarification or add additional context in comments.

Comments

1

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.