【问题标题】:XML Clone node in PHPPHP 中的 XML 克隆节点
【发布时间】:2016-02-19 08:47:15
【问题描述】:

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

即:

源 XML:

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

目标 XML:

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

【问题讨论】:

  • 我认为解决方案在 DOMXPATH 中,但我无法理解。
  • 我已经看过了。看起来导入节点的方式是我需要的,但如果我理解得很好,他并没有将导入的节点附加到现有 XML 的特定标签上。

标签: php xml clone domdocument


【解决方案1】:

当然,您可以使用XSLT,这是一种本地编程语言,可根据任何细微的需求重新构建 XML 文档。具体来说,您需要从外部源 XML 文件中提取 XML 内容。并且 PHP 与其他通用语言(Java、C#、Python、VB)一样维护用于 XSLT 处理的库。

XSLT (另存为 .xsl 或 .xslt 文件以便在下面的 PHP 中使用,并确保源和目标 XML 文件在同一目录中)

<?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 (外部加载 XML 和 XSL 文件,但可以嵌入为字符串)

$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);

输出 (使用您上面发布的源和目标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>

【讨论】:

    【解决方案2】:

    这是一个简单的方法:

    $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();
    

    【讨论】:

      【解决方案3】:

      DOMXpath::evaluate() 允许您使用 Xpath 表达式获取节点。 DOMDocument::importNode() 复制一个节点并将一个节点导入到目标文档中。 DOMNode::cloneNode() 创建节点的副本以添加到同一文档中。 DOMNode::appendChild() 允许您附加导入/克隆的节点。

      $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();
      

      输出:

      <?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>
      

      【讨论】:

      • 某处 XSLT 程序员有点哭了!
      • 我经常使用 XSLT。 :-)
      • 抱歉让 XSLT 程序员哭了,但它对我有用 :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-18
      • 2023-02-25
      • 1970-01-01
      相关资源
      最近更新 更多