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
相关产品推荐
相关产品推荐

