标签?
" />
lxml 的 XMLPullParser 在解析非标准或结构不完整的内容时,若误用 HTML 解析逻辑(如未指定严格 XML 解析器),可能将文本片段错误地包裹为 标签——根本原因在于混合了 HTML 容错解析行为与 XHTML 文档的预期。
lxml 为何在解析 xhtml 时自动插入 `
` 标签?
当你使用 lxml 解析 XHTML 文件却意外得到大量孤立 <p></p> 标签(如 <p> T </p>
<p>></p>…),这通常并非 lxml 的“bug”,而是解析器类型误配或输入内容不符合 XML 语法规范所致。
关键原因有两点:
-
误用了 HTML 解析逻辑:
lxml 默认的etree.parse()或etree.fromstring()在检测到类似 HTML 的内容时,可能自动切换至HTMLParser(尤其当文档缺少<?xml ?>声明或 DOCTYPE 不严谨时)。HTML 解析器会主动修复“破损”结构——例如将连续文本按空白或符号切分,并用<p></p>包裹段落。而你的原始 XHTML 是合法 XML,理应由严格 XML 解析器处理。立即学习“前端免费学习笔记(深入)”;
html-to-pptx-converter下载使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
输入字符串本身存在 XML 语法错误:
如答案中指出,>(缺少分号)和<是非法实体引用,在 XML 中必须写作>和<。当 lxml 的 XML 解析器遇到此类错误时,部分版本可能退化为容错模式,或触发底层 libxml2 的恢复策略,导致文本被错误分段并包装为块级元素(如<p></p>)。
✅ 正确做法如下:
-
始终显式使用 XML 解析器:
from lxml import etree as et # ✅ 强制 XML 解析(禁用 HTML 自动检测) parser = et.XMLParser(recover=False, strip_cdata=False) tree = et.parse("input.xhtml", parser) root = tree.getroot() -
确保输入是合规的 UTF-8 编码 XML 字节串,且实体完整:
# ✅ 正确的 XHTML 片段(注意 > < & 等必须带分号) xml_bytes = b'<body>T > 85C : 10ms 85 => T > 30C : 100ms T < 30 : 1s</body>' # 使用 XMLPullParser 时也需绑定 XMLParser target = et.TreeBuilder() parser = et.XMLPullParser(target=target, recover=False) parser.feed(xml_bytes) parser.close() root = target.close() print(et.tostring(root, encoding="utf-8").decode()) # 输出: <body>T > 85C : 10ms 85 => T > 30C : 100ms T < 30 : 1s</body>
⚠️ 注意事项:
- 避免直接对未转义的 HTML 字符串调用
etree.fromstring()—— 它会默认启用 HTML 模式; - 若源文件为 XHTML,建议先用
xmllint --noout input.xhtml验证其有效性; - 在 DITA 转换流程中,推荐统一使用
etree.XMLParser(load_dtd=False, no_network=True)提升安全性和一致性; -
XMLPullParser的recover=False(默认)可防止静默纠错,便于早期暴露格式问题。
总结:lxml 插入 <p></p> 标签本质是解析器对“非标准输入”的适应性响应。坚持使用严格 XML 解析、校验实体合法性、避免混用 HTML/XHTML 解析上下文,即可彻底规避该现象。


















