如何将父节点复制到SimpleXml的当前节点

How to copy parent nodes into current node of SimpleXml

我想将一个 XML 拆分成更小的块以便进一步处理。 为了能够自给自足地导入,每个块都必须包含其范围之外的所有信息。

假设我将 < ITEM > 配置为包含所有内容的新根:

<ROOT>
    <SUBROOT>
        <MOVEME>moveme</MOVEME>
        <ITEM>
            <AAA>111</AAA>
        </ITEM>
        <ITEM>
            <AAA>111</AAA>
        </ITEM>
    </SUBROOT>
</ROOT>

应该变成

<NEWROOT>
        <ITEM>
            <MOVEME>moveme</MOVEME>
            <AAA>111</AAA>
        </ITEM>
        <ITEM>
            <MOVEME>moveme</MOVEME>
            <AAA>111</AAA>
        </ITEM>
</NEWROOT>

什么是高性能解决方案? 谢谢!

考虑 XSLT (sibling to XPath), the special-purpose language designed to transform XML files into other XML, HTML, even txt files. PHP can run XSLT 1.0 scripts with its php-xsl class(确保在 .ini 文件中启用它)。

对于中小型 XML 文件,XSLT 是一个高性能选项,因为您甚至可以避免 foreach 循环和 if 逻辑和重建树(即 importNode) 在应用层。具体来说,下面的 XSLT 解析到 ITEM 级别,并使用 XPath 的 ancestor::* 映射到父 SUBROOT 需要的项目。在脚本中调整为实际节点名称。

XSLT (另存为.xsl文件,一个特殊的.xml文件)

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes" />

    <xsl:template match="/ROOT">   
        <NEWROOT>
            <xsl:apply-templates select="SUBROOT"/>
        </NEWROOT>
    </xsl:template>

    <xsl:template match="SUBROOT">      
        <xsl:apply-templates select="ITEM"/>
    </xsl:template>

    <xsl:template match="ITEM">
        <xsl:copy>
            <xsl:copy-of select="ancestor::SUBROOT/MOVEME" />
            <xsl:copy-of select="*"/>
        </xsl:copy>
    </xsl:template>
</xsl:transform>

PHP

# LOAD XML AND XSL FILES
$xml = new DOMDocument;
$xml->load('/path/to/input.xml');

$xsl = new DOMDocument;
$xsl->load('/path/to/xslt_script.xsl');

// CONFIGURE TRANSFORMER
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl);

// RUN TRANSFORMATION
$newXML = new DOMDocument;
$newXML = $proc->transformToXML($xml);

// OUTPUT NEW XML
echo $newXML;

// SAVE NEW DOM TREE TO FILE
file_put_contents('/path/to/output.xml', $newXML);

XSLT Demo