lxml解析XML时自动转换
为\n导致校验和不一致的解决方法咨询
解决lxml解析XML时保留原始实体(如

)导致校验和不一致的问题 我遇到过完全一样的问题——lxml默认会把XML中的数值字符引用(比如
)解析成对应的实际字符,这直接导致了校验和不匹配。这里有两种可靠的解决方案,你可以根据自己的场景选择:
方案1:解析时保留原始实体(推荐)
通过配置lxml的XMLParser,禁用实体解析功能,这样lxml会完全保留XML中的原始实体字符串,不会转换成对应的字符,从根源上解决校验和不一致的问题。
示例代码:
from lxml.etree import tostring, fromstring, XMLParser import hashlib document = "<root><note><body>Some text, text 
text text text</body></note></root>" # 创建解析器,禁用实体解析 parser = XMLParser(resolve_entities=False) tree = fromstring(document, parser=parser) # 获取需要计算校验和的元素 body_element = tree.find("note/body") # 序列化后的内容会完整保留原始的
 serialized_body = tostring(body_element) print(serialized_body) # 输出: b'<body>Some text, text 
text text text</body>' # 计算校验和,结果与客户端完全一致 checksum = hashlib.sha256(serialized_body).hexdigest() print(checksum) # 输出: 9f7cb6989df55572968be655fb86e461c257a74f8cc40019d1315a5c10978cd8
注意:这个参数会禁用所有实体的解析,包括自定义实体。但如果你的业务场景中客户端传入的XML只包含标准数值字符引用和预定义实体(如
&、<),这完全符合需求——因为客户端正是基于这些原始实体字符串计算校验和的。
方案2:序列化时转换特定字符
如果你确定只需要处理
这类特定的字符引用,也可以在序列化后把解析后的字符再转换回原始实体格式。这种方案适合场景单一、已知仅需处理少数字符的情况。
示例代码:
from lxml.etree import tostring, fromstring import hashlib document = "<root><note><body>Some text, text 
text text text</body></note></root>" tree = fromstring(document) body_element = tree.find("note/body") # 先序列化元素,再把换行符替换回
 serialized_body = tostring(body_element).replace(b'\n', b'
') print(serialized_body) # 输出: b'<body>Some text, text 
text text text</body>' # 计算校验和,结果与客户端一致 checksum = hashlib.sha256(serialized_body).hexdigest() print(checksum) # 输出: 9f7cb6989df55572968be655fb86e461c257a74f8cc40019d1315a5c10978cd8
不过要注意,这个方案只处理了你已知的字符,如果XML中还有其他数值引用(比如
回车符),就需要额外添加替换逻辑,覆盖范围远不如方案1全面。
内容的提问来源于stack exchange,提问作者Przemek
相关产品推荐
相关产品推荐

