$xml = '<p><a>1</a><b><c>1</c></b></p>';
$dom = new DomDocument;
$dom->loadXML($xml);
$p = $dom->childNodes->item(0);
echo $dom->saveXML($p);
以上将打印回来
<p>
<a>1</a>
<b><c>1</c></b>
</p>
假设需要将p
节点/ eleemnt替换为new_p
什么是理想的方式,除了像下面的循环? (下面是可行的)
$fragment = '';
foreach ($p->childNodes as $a)
{
$fragment .= $dom->saveXML($a);
}
$new_doc = new DomDocument;
$new_doc->loadXML('<new_node/>');
$f = $new_doc->createDocumentFragment();
$f->appendXML($fragment);
$new_doc->documentElement->appendChild($f);
echo $new_doc->saveXML();
预期结果
<new_node><a>1</a><b><c>1</c></b></new_node>
答案 0 :(得分:3)
正如Mark已经指出的那样,使用XSLT操作XML是最简单的。而且你不必编写任何循环,思考是由你选择的XSLT处理器完成的。
以下是XSLT的外观(对于某些教程,Google为“Identity transform XSLT”)。
基础知识很简单:这种类型的XSLT转换按原样复制所有内容,除非有特定规则(XSLT中的模板匹配)指定异常(在本例中为<p>
元素)。注意:嵌入p标签的深度并不重要,这使其成为转换XML的理想选择。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- identity transform -->
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- rename "p" with "new_p", copy everything inside p -->
<xsl:template match="p">
<new_p>
<xsl:apply-templates select="@* | node()"/>
</new_p>
</xsl:template>
</xsl:stylesheet>
这是相对简单的,因为PHP有一个内置的XSL模块。这是你如何做到的(here's more information):
// create an XSLT processor and load the stylesheet as a DOM
$xproc = new XsltProcessor();
$xslt = new DomDocument;
$xslt->load('yourstylesheet.xslt'); // this contains the code from above
$xproc->importStylesheet($xslt);
// your DOM or the source XML (copied from your question)
$xml = '<p><a>1</a><b><c>1</c></b></p>';
$dom = new DomDocument;
$dom->loadXML($xml);
// do the transformation
if ($xml_output = $xproc->transformToXML($dom)) {
echo $xml_output;
} else {
trigger_error('Oops, XSLT transformation failed!', E_USER_ERROR);
}
输出符合预期(可以使用<xsl:output indent="yes"/>
设置可选缩进:
<new_p>
<a>1</a>
<b><c>1</c></b>
</new_p>
如您所见:没有循环或迭代;)
PS:XSLT是一种广泛采用且稳定的标准。您不必担心正确转义,解析CDATA部分或实体的问题,因为XSLT保证输出是有效的XML。与手工操作相比,这节省了许多麻烦。
答案 1 :(得分:2)
XSLT不适合这种操作吗?
答案 2 :(得分:-3)
虽然循环是一个明显的解决方案,但某些情况可能会阻止这种情况或使其不适用;虽然我不知道一个。或者,可以通过操作字符串,输入XML字符串或$new_doc->saveXML()
方法的输出XML来实现,具体取决于您可以使用的方法。
如果标签包含属性,我会使用str_ireplace
或正则表达式,特别是preg_replace
带i
修饰符标志,用于不区分大小写的搜索。如果你对这种技术感兴趣,我可以提供一些例子。