如何在PHP中移除XML文件CDATA内HTML标签属性并保留原有格式
解决方案
直接使用preg_replace对整个XML字符串做匹配会出现格式错乱,核心原因是正则无法精准区分XML结构、CDATA边界和HTML属性,容易误改非目标内容、破坏XML原有排版。推荐使用DOM扩展分层处理,既能精准移除style属性,也能完全保留原XML的格式:
实现步骤
- 加载原XML时配置保留空白、不自动格式化,保证原有XML的缩进、换行、空格完全不变
- 提取XML中CDATA节点内的HTML内容单独处理,不触碰XML其他结构
- 解析HTML片段后遍历所有元素,移除目标属性
- 处理完成后将HTML写回CDATA节点,再保存XML
代码示例
<?php // 加载原XML,保留原始格式 $xml = new DOMDocument(); $xml->preserveWhiteSpace = true; $xml->formatOutput = false; $xml->load('你的源文件路径.xml'); // 匹配所有description标签,可根据实际需求修改目标标签名 $targetNodes = $xml->getElementsByTagName('description'); foreach ($targetNodes as $node) { foreach ($node->childNodes as $child) { // 仅处理CDATA节点 if ($child->nodeType == XML_CDATA_SECTION_NODE) { $rawHtml = $child->nodeValue; // 解析CDATA内的HTML片段 $htmlDom = new DOMDocument(); // 兼容不规范HTML,抑制非致命警告 @$htmlDom->loadHTML( mb_convert_encoding($rawHtml, 'HTML-ENTITIES', 'UTF-8'), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); // 遍历所有HTML元素,移除style属性 $allElements = $htmlDom->getElementsByTagName('*'); foreach ($allElements as $elem) { if ($elem->hasAttribute('style')) { $elem->removeAttribute('style'); } // 如需移除其他属性,可在此处新增对应判断逻辑 } // 处理完成后写回CDATA节点 $processedHtml = $htmlDom->saveHTML(); $newCdataNode = $xml->createCDATASection($processedHtml); $node->replaceChild($newCdataNode, $child); } } } // 保存处理后的文件,原有格式完全保留 $xml->save('你的输出文件路径.xml'); ?>
简单场景正则方案
如果你的HTML结构非常简单、没有属性值嵌套引号等复杂情况,也可以用正则仅对CDATA内容做匹配,避免误改XML结构:
$rawContent = file_get_contents('你的源文件路径.xml'); $processedContent = preg_replace_callback('/<!\[CDATA\[(.*?)\]\]>/s', function($matches) { // 仅对CDATA内的内容移除style属性 $cleanHtml = preg_replace('/\s+style\s*=\s*(["\'])[^\1]*?\1/i', '', $matches[1]); return '<![CDATA[' . $cleanHtml . ']]>'; }, $rawContent); file_put_contents('你的输出文件路径.xml', $processedContent);
注意:正则方案容错性低,复杂场景下仍推荐使用DOM处理。
内容的提问来源于stack exchange,提问作者user3452136
相关产品推荐
相关产品推荐

