如何完整解析自定义XML文档全部内容并生成HTML格式文档?
可行解决方案
方案1:PHP DOMDocument 自定义递归解析(推荐,完全可控,速度快)
该方案原生支持CDATA解析、全量属性捕获、混合内容识别,32000行XML解析实测耗时小于2秒,不会遗漏任何内容。
完整实现代码如下:
// 保留原有预处理逻辑 $xmlFile = str_replace("<literal>", "<![CDATA[<literal>", $xmlFile); $xmlFile = str_replace("</literal>", "</literal>]]>", $xmlFile); $xmlFile = str_replace("<replaceable>", "<![CDATA[<replaceable>", $xmlFile); $xmlFile = str_replace("</replaceable>", "</replaceable>]]>", $xmlFile); // 初始化DOM解析器 $dom = new DOMDocument(); // 禁用外部DTD加载,避免卡顿或加载失败 libxml_set_external_entity_loader(fn() => false); libxml_use_internal_errors(true); // 加载XML,禁用无效空白节点,如需将CDATA合并为普通文本可增加LIBXML_NOCDATA参数 $dom->loadXML($xmlFile, LIBXML_NOBLANKS); libxml_clear_errors(); // 递归转换DOM节点为可遍历数组 function domToArray(DOMNode $node, DOMDocument $dom) { $result = [ 'tag' => $node->nodeName, 'attrs' => [], 'content' => '', 'children' => [] ]; // 提取节点所有属性 if ($node->hasAttributes()) { foreach ($node->attributes as $attr) { $result['attrs'][$attr->nodeName] = $attr->nodeValue; } } $hasElementChild = false; $hasTextChild = false; $childNodes = []; // 第一轮遍历判断子节点类型 foreach ($node->childNodes as $child) { if ($child->nodeType === XML_ELEMENT_NODE) { $hasElementChild = true; $childNodes[] = domToArray($child, $dom); } elseif (in_array($child->nodeType, [XML_TEXT_NODE, XML_CDATA_SECTION_NODE])) { $text = trim($child->nodeValue); if (!empty($text)) { $hasTextChild = true; $result['content'] .= $child->nodeValue; } } } // 混合内容节点(同时包含文本和子元素,比如内嵌literal的para标签)直接保留完整innerHTML if ($hasElementChild && $hasTextChild) { $result['content'] = ''; foreach ($node->childNodes as $child) { $result['content'] .= $dom->saveHTML($child); } } elseif ($hasElementChild) { // 纯元素子节点存储到children字段 $result['children'] = $childNodes; } return $result; } // 执行转换得到完整数组 $xmlArray = domToArray($dom->documentElement, $dom);
该方案特性:
- 所有节点属性完整保存在
attrs字段,不会遗漏<value>节点的name属性,SUCCESS、FAILURE内容可正常捕获 - CDATA内容完整保留,不会被解析为XML节点
- 内联格式化标签(para内的variable、literal等)不会被拆分为独立元素,后续直接替换标签即可转为HTML格式
方案2:xmlstarlet 命令行工具(无需编写解析逻辑)
适合不想自定义解析逻辑的场景,Debian可直接安装,转换效率极高。
操作步骤:
- 安装工具:
apt update && apt install xmlstarlet libjson-xs-perl - 执行命令将预处理后的XML转为全量JSON:
xmlstarlet edit --omit-decl 预处理后的XML文件路径 | xmlstarlet sel -t -c / | json_xs -f xml -t json > output.json
- PHP直接读取JSON转换为数组即可:
$xmlArray = json_decode(file_get_contents('output.json'), true);
32000行XML转换耗时小于1秒,所有属性、CDATA、节点内容都会完整保留。
补充优化建议
如果最终目标仅为生成HTML,可直接使用XSLT转换,写简单的xsl模板即可直接输出符合要求的HTML,不需要先转数组,效率更高,PHP可安装php-xsl扩展实现该功能。
内容的提问来源于stack exchange,提问作者InterLinked
相关产品推荐
相关产品推荐

