如何从php中的xml文件中删除html属性?

How can I remove html attributes from xml file in php?

提问人:user3452136 提问时间:6/18/2021 最后编辑:user3452136 更新时间:7/17/2021 访问量:485

问:

我有一个包含 HTML 的 XML 文件。在 HTML 标签中,有一些我想删除的属性,但我需要保留所有标签。例如:

<description><![CDATA[<div><span style='font-size: 40px'>Testing123</span></div>]]></description>

我想删除“style”属性,以便输出为:

 <description><![CDATA[<div><span>Testing123</span></div>]]></description>

我能够使用 preg_replace 来解决这个问题,但是当我去保存文件时,格式就偏离了。换句话说,我想在解析/剥离文件后保留 XML 文件的格式。

编辑:我提供的初始示例数据不包括我的 XML 文件中的 CDATA。我修改了它。

php xml xml html 解析 simplexml

评论

0赞 Nigel Ren 6/18/2021
您是要删除所有属性,还是仅从特定标签中删除特定属性?
0赞 Yitzhak Khabinsky 6/18/2021
使用 XSLT 的解决方案最适合完成此任务。
0赞 user3452136 6/20/2021
@NigelRen - 我想移动除一个标签之外的所有属性。如何做到这一点?例如,假设我想保留 <div id=“SomeId>contents</div>,但对于所有其他 HTML 标签,我想删除这些属性。有什么简单的解决方案吗?

答:

1赞 Jack Fleeting 6/18/2021 #1

我不确定格式,但请尝试使用 simplexml 和 unset() 函数:

$string = "<div><span style='font-size: 40px'>Testing123</span></div>";                                                                       
$xml = simplexml_load_string($string);
$target = $xml->xpath("//span/@style");
foreach ($target as $node) {
    unset($node[0]);
}

echo $xml->asXML();

输出:

<?xml version="1.0"?>
<div><span>Testing123</span></div>
0赞 Michael Kay 6/19/2021 #2

XSLT 3.0 解决方案:

<transform xmlns="http://www.w3.org/1999/XSL/Transform" version="3.0"/>
 <mode on-no-match="shallow-copy"/>
 <template match="span/@style"/>
</transform>

您可以扩展匹配模式,或添加其他模板规则,具体取决于要删除的属性。

当然,XSLT 1.0 也是可能的,只是它更冗长一些。

0赞 hakre 6/21/2021 #3

您必须将 cdata 元素中的字符串加载为 XML(更正确:HTML),然后删除所有属性,例如使用 xpath:

$xml = simplexml_load_string($buffer);
$cdata = simplexml_load_string((string)$xml);
foreach ($cdata->xpath('@*[name(.) != "id"]|*/@*') as $attribute) {
    unset($attribute[0]);
}

(比较:在 SimpleXML for PHP 中对 Remove a child with a specific attribute(删除具有特定属性的子项)的回答)

然后,如果需要保留 CDATA 元素,则必须执行 DOM 往返,因为 SimpleXML 没有 CDATA 部分,但 DOMDocument 具有:

    if ($n = dom_import_simplexml($el)) {
        $cd = $n->ownerDocument->createCDATASection($data);
        $n->appendChild($cd);
    }

(比较:如何使用 SimpleXmlElement 编写 CDATA?;查看 PHP 手册了解更多细节)

您还需要从中创建 XML,但您希望删除第一行,因为它包含 XML 声明$cdata

    rtrim(explode("\n", $el->asXML(), 2)[1]);

(比较:SimpleXML Type Cheatsheet 中的 SimpleXML 行分隔符)

给定一个输入,如下所示:

$buffer=<<<XML
<description><![CDATA[<div id="2" style="all: inherit;"><span style='font-size: 40px'>Testing123</span></div>]]></description>
XML;

结果是:

<?xml version="1.0"?>
<description><![CDATA[<div id="2"><span>Testing123</span></div>]]></description>

3v4l.org 的例子;7.3.0 - 7.3.29、7.4.0 - 7.4.21、8.0.0 - 8.0.8 的输出:

<?xml version="1.0"?>
<description><![CDATA[<div id="2"><span>Testing123</span></div>]]></description>