如何用lxml html tostring保留XML命名空间标签结构?
处理带命名空间的XML标签保留问题
问题描述
使用以下Python代码处理带命名空间的XML结构时:
from lxml import html root = html.fromstring('<ac:link> <ri:attachment filename="test.pdf"/> </ac:link>') html.tostring(root,encoding='unicode',method='xml')
实际输出为:
'<link> <attachment ri:filename="test.pdf"/> </link>'
但期望保留原始标签结构,输出为:
'<ac:link> <ri:attachment ri:filename="test.pdf"/> </ac:link>'
且无法修改原始HTML/XML结构,需要实现预期输出并了解相关源码逻辑。
解决方案
问题出在lxml.html模块是为HTML解析设计的,不支持XML命名空间的保留,HTML解析器会自动剥离标签名中的命名空间前缀。改用lxml的xml模块即可保留原始命名空间前缀:
from lxml import xml root = xml.fromstring('<ac:link> <ri:attachment filename="test.pdf"/> </ac:link>') xml.tostring(root, encoding='unicode', method='xml')
执行后会得到预期输出:
'<ac:link> <ri:attachment filename="test.pdf"/> </ac:link>'
如果一定要使用html模块(比如处理混合HTML/XML内容),可以自定义HTMLParser并禁用命名空间剥离,但这种方式复杂且不推荐,优先使用xml模块处理纯XML结构。
源码相关说明
lxml.html的解析逻辑:
在lxml/html/parser.py中的HTMLParser类,其设计遵循HTML规范——HTML本身没有命名空间概念,所以解析器会将标签名中的冒号视为普通字符的一部分,但在序列化(tostring)时,会自动剥离前缀。核心原因是html.fromstring调用的HTMLParser不会维护命名空间映射,导致标签的前缀信息在解析阶段就丢失。lxml.xml的解析逻辑:
在lxml/xml/__init__.py中的fromstring函数使用的是XMLParser,该解析器完全支持XML命名空间,会完整保留标签的前缀和命名空间映射,序列化时也会原样输出带前缀的标签。
内容的提问来源于stack exchange,提问作者TheDuck
相关产品推荐
相关产品推荐

