PHP中的XML克隆节点

PHP中的XML克隆节点

问题描述:

I have to clone an XML node and its childs and append it to a new XML in a specifics tag.

Ie:

Source XML:

<root>
  <element>
    <back>
    <item1>ABC</item1>
    <item2>DEF</item2>
    <more>
      <moreitem>GHI</moreitem>
    </more
    </back>
  </element>
</root>

Destination XML:

<root>
  <base1>
    <item1>FOO</item1>
    <item2>BAR</item2>
  <base2>
    **<back>From source XML and all its childs here</back>**
  </base2>
  </base1>
<root>

我必须克隆XML节点及其子节点,并将其附加到特定标签中的新XML。 p>

即 p>

源XML: p>

 &lt; root&gt; 
&lt; element&gt; \  n&lt; back&gt; 
&lt; item1&gt; ABC&lt; / item1&gt; 
&lt; item2&gt; DEF&lt; / item2&gt; 
&lt; more&gt; 
&lt; moreitem&gt; GHI&lt; / moreitem&gt; 
&lt; / more  
&lt; / back&gt; 
&lt; / element&gt; 
&lt; / root&gt; 
  code>  pre> 
 
 

目标XML: p>

 &lt; root&gt; 
&lt; base1&gt; 
&lt; item1&gt; FOO&lt; / item1&gt; 
&lt; item2&gt; BAR&lt; / item2&gt; 
&lt; base2&gt; 
 **&lt; back&gt; 来自源XML及其所有子项&lt; / back&gt; ** 
&lt; / base2&gt; 
&lt; / base1&gt; 
&lt; root&gt; 
  code>  pre> 
  div>

DOMXpath::evaluate() allows you to fetch nodes using Xpath expressions. DOMDocument::importNode() duplicates a node and imports a node into a target document. DOMNode::cloneNode() create a duplicate of node to add in the same document. DOMNode::appendChild() allows you to append the imported/cloned node.

$source = <<<'XML'
<root>
  <element>
    <back>
    <item1>ABC</item1>
    <item2>DEF</item2>
    <more>
      <moreitem>GHI</moreitem>
    </more>
    </back>
  </element>
</root>
XML;

$target = <<<'XML'
<root>
  <base1>
    <item1>FOO</item1>
    <item2>BAR</item2>
    <base2>
    </base2>
  </base1>
</root>
XML;

$sourceDocument = new DOMDocument();
$sourceDocument->loadXml($source);
$sourceXpath = new DOMXpath($sourceDocument);

$targetDocument = new DOMDocument();
$targetDocument->loadXml($target);
$targetXpath = new DOMXpath($targetDocument);

foreach ($targetXpath->evaluate('/root/base1/base2[1]') as $targetNode) {
  foreach ($sourceXpath->evaluate('/root/element/back') as $backNode) {
    $targetNode->appendChild($targetDocument->importNode($backNode, TRUE));
  }
}

echo $targetDocument->saveXml();

Output:

<?xml version="1.0"?>
<root>
  <base1>
    <item1>FOO</item1>
    <item2>BAR</item2>
    <base2>
      <back>
        <item1>ABC</item1>
        <item2>DEF</item2>
        <more>
          <moreitem>GHI</moreitem>
        </more>
      </back>
    </base2>
  </base1>
</root>

This is an easy way to do this:

$src = new DOMDocument();
$dst = new DOMDocument();

$src->loadXML($src_xml);
$dst->loadXML($dst_xml);

$back = $src->getElementsByTagName('back')->item(0);
$base = $dst->getElementsByTagName('base2')->item(0);

$base->appendChild( $dst->importNode( $back, true ) );
echo $dst->saveXML();

Of course you can use XSLT, the native programming language to restructure XML documents to any nuanced needs. Specifically here, you require pulling XML content from an external source XML file. And PHP like other general purpose languages (Java, C#, Python, VB) maintain libraries for XSLT processing.

XSLT (save as .xsl or .xslt file to be used in PHP below and be sure Source and Destination XML files are in same directory)

<?xml version="1.0" ?> 
<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="back">
   <back>
    <xsl:copy-of select="document('Source.xml')"/>
   </back>
  </xsl:template>

</xsl:transform>

PHP (loading XML and XSL files externally but can be embedded as string)

$destinationdoc = new DOMDocument();
$doc1->load('Destination.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 = 'FinalOutput.xml';
file_put_contents($xmlfile, $newXml);

OUTPUT (using your above posted Source and Destination xml)

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <base1>
    <item1>FOO</item1>
    <item2>BAR</item2>
    <base2>
      <back>
        <root>
          <element>
            <back>
              <item1>ABC</item1>
              <item2>DEF</item2>
              <more>
                <moreitem>GHI</moreitem>
              </more>
            </back>
          </element>
        </root>
      </back>
    </base2>
  </base1>
</root>