lxml目标接口拆分非ASCII字符,如何获取完整字符串?
解决lxml解析含非ASCII字符文本时的拆分问题
测试文件 test.xml
<?xml version="1.0" encoding="UTF-8"?> <list> <entry>data</entry> <entry>Łódź</entry> <entry>data Łódź</entry> </list>
原解析脚本
from lxml import etree class ParseTarget: def __init__(self): self.entries = [] def start(self, tag, attrib): pass def end(self, tag): pass def data(self, data): str = data.strip() if str != '': self.entries.append(data) def close(self): # Reset parser entries = self.entries self.entries = [] # And return results return entries target = etree.XMLParser(target=ParseTarget(), # Including/removing this makes no difference encoding='UTF-8') tree = etree.parse("./test.xml", target) # 预期结果: # ['data', 'Łódź', 'data Łódź'] # 实际结果: # ['data', 'Łódź', 'data ', 'Łódź']
问题说明
运行上述脚本后,预期得到3个元素的列表,但实际得到4个元素。原因是lxml的SAX风格解析器会将包含非ASCII字符(且开头有ASCII字符)的文本拆分为多个片段,多次调用data方法传递,导致原本属于同一个<entry>的文本被拆成两个元素存入结果列表。
解决方案
核心思路是维护一个临时缓冲区,拼接同一个文本节点的所有分段内容,直到元素结束时再统一处理:
from lxml import etree class ParseTarget: def __init__(self): self.entries = [] self.current_text = [] # 临时缓冲区,用于拼接分段文本 def start(self, tag, attrib): # 进入新元素时重置缓冲区 self.current_text = [] def end(self, tag): # 离开元素时,拼接完整文本并处理 full_text = ''.join(self.current_text).strip() if full_text: self.entries.append(full_text) self.current_text = [] def data(self, data): # 仅将文本片段追加到缓冲区,不直接存入结果 self.current_text.append(data) def close(self): entries = self.entries self.entries = [] return entries target = etree.XMLParser(target=ParseTarget(), encoding='UTF-8') tree = etree.parse("./test.xml", target) # 此时tree的值为预期的 ['data', 'Łódź', 'data Łódź']
关键修改点
- 新增
current_text列表作为临时缓冲区,接收每次data方法传递的文本片段。 start方法中重置缓冲区,确保每个元素的文本收集从头开始。end方法中完成文本拼接、去空处理后,再将完整文本加入结果列表。
内容的提问来源于stack exchange,提问作者modallyFragile
相关产品推荐
相关产品推荐

