使用libxml2解析深层节点失败:255层div嵌套丢失img标签问题
问题:libxml解析超254层嵌套HTML时丢失内部节点
我生成了一段被255层div标签嵌套包裹的img标签HTML内容,使用libxml解析该HTML并输出结果时,发现img标签丢失;但当div嵌套层数为254层时,解析结果正常,img标签可正常显示。尝试多种标签均出现相同情况,怀疑是节点层级过深导致,请问该问题的原因是什么?如何修复?
原代码:
NSString* html = @"<img src='https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png'>"; for (int i = 0; i < 255; i++) { html = [NSString stringWithFormat:@"<div>%@</div>", html]; } NSData* data = [html dataUsingEncoding:NSUTF8StringEncoding]; xmlDocPtr _doc = htmlReadMemory([data bytes], (int)[data length], "", NULL, HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR); if (_doc == NULL) { NSLog(@"Unable to parse."); return; } xmlXPathContextPtr _context = xmlXPathNewContext(_doc); if(_context == NULL) { NSLog(@"Unable to create XPath context."); return; } xmlNodePtr rootNode = xmlDocGetRootElement(_doc); xmlBufferPtr buffer = xmlBufferCreate(); if (rootNode == NULL || buffer == NULL) { return; } xmlNodeDump(buffer, rootNode->doc, rootNode, 0, 0); NSString *htmlContent = [NSString stringWithCString:(const char *)buffer->content encoding:NSUTF8StringEncoding]; xmlBufferFree(buffer); xmlXPathFreeContext(_context); xmlFreeDoc(_doc); NSLog(@"%@", htmlContent);
原因分析
- libxml默认设置了节点嵌套深度上限为254(从根节点开始计数),当嵌套层数超过这个值时,超出部分的节点会被解析器自动丢弃。这是libxml为避免栈溢出、内存耗尽等风险设置的安全限制。
- 你使用了
HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR参数屏蔽了解析器的警告和错误输出,因此没有收到深度超限的提示,无法直观定位问题。
修复方案
1. 调整libxml的全局深度限制
在调用htmlReadMemory解析HTML之前,调用xmlSetTreeDepth函数设置更大的允许深度,比如设置为1000,足以覆盖大多数嵌套场景:
// 增加这一行,设置最大允许的节点深度 xmlSetTreeDepth(1000); xmlDocPtr _doc = htmlReadMemory([data bytes], (int)[data length], "", NULL, HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR);
2. 可选:开启解析器提示(便于排查)
移除HTML_PARSE_NOWARNING | HTML_PARSE_NOERROR参数,这样解析器会输出深度超限的警告信息,帮助你快速定位类似问题:
xmlDocPtr _doc = htmlReadMemory([data bytes], (int)[data length], "", NULL, 0);
内容的提问来源于stack exchange,提问作者a_adler
相关产品推荐
相关产品推荐

