You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何完整解析自定义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可直接安装,转换效率极高。
操作步骤:

  1. 安装工具:apt update && apt install xmlstarlet libjson-xs-perl
  2. 执行命令将预处理后的XML转为全量JSON:
xmlstarlet edit --omit-decl 预处理后的XML文件路径 | xmlstarlet sel -t -c / | json_xs -f xml -t json > output.json
  1. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 10:54:04