使用 DOMDocuments 将 xml 树附加到 PHP 中的另一个 xml 树
Append xml tree to another xml tree in PHP using DOMDocuments
我想将一棵 xml 树附加到另一棵树上。
比如我想要下面的xml:
<a>
<b>
<c/>
</b>
</a>
里面有以下xml:
<n:d xmlns:xsl="namespace">
<n:e>
<n:f/>
</n:e>
</n:d>
所以它看起来像这样:
<a>
<b>
<c/>
<n:d xmlns:n="namespace">
<n:e>
<n:f/>
</n:e>
</n:d>
</b>
</a>
我尝试并未能做到这一点的代码如下:
$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>';
我从回显得到的当前结果:
<a>
<b>
<c/>
<n:d xmlns:n="namespace" />
</b>
</a>
我的想法并非不可读,也不是看似愚蠢的迂回。
如有任何帮助,我们将不胜感激。提前谢谢你。
您的解决方案非常接近。你只需要执行一次deep copy with importNode就可以得到你想要的结果。
$node_To_Be_Inserted_To->appendChild($doc1->importNode($node_To_Insert, true));
或者,处理 XML 转换(例如 merging documents)的本机方法是使用 XSLT,这是一种主要为此设计的专用语言,需要重新构造、重新样式化、重新格式 XML 文档以满足各种最终使用需求。
与另一种用于数据库的专用语言 SQL 非常相似,XSLT 对于 XML 文件很方便。 PHP 配备了 XSLT 处理器(可能需要启用扩展:php_xsl.so
)。
XSLT (另存为 .xsl 或 .xslt 文件)
<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 (仅加载第一个文档,因为上面的 XSLT 在特定节点加载第二个文档)
$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);
输出
<?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>
我想将一棵 xml 树附加到另一棵树上。
比如我想要下面的xml:
<a>
<b>
<c/>
</b>
</a>
里面有以下xml:
<n:d xmlns:xsl="namespace">
<n:e>
<n:f/>
</n:e>
</n:d>
所以它看起来像这样:
<a>
<b>
<c/>
<n:d xmlns:n="namespace">
<n:e>
<n:f/>
</n:e>
</n:d>
</b>
</a>
我尝试并未能做到这一点的代码如下:
$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>';
我从回显得到的当前结果:
<a>
<b>
<c/>
<n:d xmlns:n="namespace" />
</b>
</a>
我的想法并非不可读,也不是看似愚蠢的迂回。
如有任何帮助,我们将不胜感激。提前谢谢你。
您的解决方案非常接近。你只需要执行一次deep copy with importNode就可以得到你想要的结果。
$node_To_Be_Inserted_To->appendChild($doc1->importNode($node_To_Insert, true));
或者,处理 XML 转换(例如 merging documents)的本机方法是使用 XSLT,这是一种主要为此设计的专用语言,需要重新构造、重新样式化、重新格式 XML 文档以满足各种最终使用需求。
与另一种用于数据库的专用语言 SQL 非常相似,XSLT 对于 XML 文件很方便。 PHP 配备了 XSLT 处理器(可能需要启用扩展:php_xsl.so
)。
XSLT (另存为 .xsl 或 .xslt 文件)
<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 (仅加载第一个文档,因为上面的 XSLT 在特定节点加载第二个文档)
$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);
输出
<?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>