gpt4 book ai didi

php - 如何在不使用迭代的情况下提取 DOM 子节点或重命名元素?

转载 作者:可可西里 更新时间:2023-10-31 23:34:37 24 4
gpt4 key购买 nike

$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 节点/元素替换为 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>

最佳答案

正如 Mark 已经指出的那样,使用 XSLT 操作 XML 最简单。而且您不必编写任何循环,思考由您选择的 XSLT 处理器完成。

XSLT 的简单操作方法

这是 XSLT 的样子(谷歌搜索“Identity transform XSLT”的一些教程)。

基础知识很简单:这种类型的 XSLT 转换按原样复制所有内容,除非有指定异常(exception)的特定规则(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 调用 XSLT

这相对简单,因为 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。与手动执行此操作相比,这可以省去很多麻烦。

关于php - 如何在不使用迭代的情况下提取 DOM 子节点或重命名元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5070630/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com