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

libxml2遇含空格XML无法美化打印?如何解决该问题?

问题描述
  • 向libxml2传入无任何格式或空格的XML(示例代码:const char *xml= "<root><a>test</a></root>";)时,调用带参数1的xmlNodeDump()可正常实现美化打印。
  • 传入预格式化或含空格的XML(示例代码:const char *xml = "<root>" " <a>" " test" " </a>" "</root>";)时,libxml2无法进行美化打印。

解析代码

#define MY_PARSER_OPTIONS (XML_PARSE_RECOVER | XML_PARSE_NOENT | XML_PARSE_DTDLOAD | XML_PARSE_DTDATTR | XML_PARSE_HUGE)
...

doc = xmlReadDoc((const xmlChar *) xml, NULL, NULL, MY_PARSER_OPTIONS);
...
xmlNodePtr root = xmlDocGetRootElement(doc);
xmlBufferPtr buf = xmlBufferCreate();
xmlNodeDump(buf, doc, root, 0, 1);

输入输出对比

含空格的输入输出

<root>  <a>    test  </a></root>

无空格的输入输出

<root>
  <a>test</a>
</root>

疑问

这是libxml2的bug吗?如何实现正确的美化打印?


解答

这不是libxml2的bug,是默认行为:预格式化XML中的空格会被解析为独立的文本节点,xmlNodeDump()在美化时会保留这些已存在的文本节点内容,不会自动清理后重新格式化。

解决方案

方案1:解析时添加XML_PARSE_NOBLANKS选项

该选项会忽略XML中仅包含空白的独立文本节点(不会移除元素内文本前后的有意义空格),修改解析选项宏定义即可:

#define MY_PARSER_OPTIONS (XML_PARSE_RECOVER | XML_PARSE_NOENT | XML_PARSE_DTDLOAD | XML_PARSE_DTDATTR | XML_PARSE_HUGE | XML_PARSE_NOBLANKS)

修改后,无论传入哪种格式的XML,xmlNodeDump()都能输出统一美化后的结果。

方案2:手动移除空白文本节点

如果需要保留部分有意义的空白,可手动遍历节点树,移除所有仅含空白的文本节点,再执行美化:

void removeBlankNodes(xmlNodePtr node) {
    xmlNodePtr current = node;
    xmlNodePtr next;
    while (current != NULL) {
        next = current->next;
        if (current->type == XML_TEXT_NODE && xmlIsBlankNode(current)) {
            xmlUnlinkNode(current);
            xmlFreeNode(current);
        } else if (current->type == XML_ELEMENT_NODE) {
            removeBlankNodes(current->children);
        }
        current = next;
    }
}

// 使用方式:获取root节点后、调用xmlNodeDump前执行
removeBlankNodes(root);

优化后输出

两种输入都会得到如下格式化结果:

<root>
  <a>test</a>
</root>

内容的提问来源于stack exchange,提问作者codenamezero

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 18:05:13