LXML 解析器在数据事件中丢失文本
LXML parser loses text in data event
我创建了一个自定义解析器来处理复杂的 XML 转换。
它很好用。已经工作了很长一段时间。
但是我刚刚注意到,当传入的 XML 文件具有标签和数据时,例如:
<ParticipantName>STEVE O'NEILL</ParticipantName>
数据事件 return 对我来说只是NEILL...而不是 STEVE O'NEILL
甚至 STEVE O'NEILL
我一直在阅读 lxml.. 我觉得这与编码选项有关.. 但我不太确定我读过的内容。很难找到处理这些 HTML 的答案?字符...甚至不确定我会尝试尝试什么编码..
现在,我创建解析器的方式是(parser_target 是我的自定义解析器):
parser = etree.XMLParser(target=parser_target)
raw_records = etree.parse(full_path, parser)
并且在数据事件中,我只是保存值..并return它在关闭事件中。
def data(self, data):
"""catch the data event on parsing the xml file.
"""
my_variable = data
我的代码比较复杂,所以这里只展示基础知识。
有谁知道如何干净地处理传入的 XML 具有这些 HTML(我认为)字符的数据?
我无法控制我收到的文件..所以我需要在它进来时处理它。
[编辑]
好的,在构建要分享的示例时,我想我已经找到了问题。当出现此文本时,数据事件似乎被多次调用。
如果有人在创建解析器时看到任何不同的/另一种通过 'encoding' 参数处理的方式.. 让我知道。
这是我构建的示例:
main.py:
from lxml import etree
from ParserTarget import ParserTarget
def test():
parser_target = ParserTarget()
print('Parsing begins')
parser = etree.XMLParser(target=parser_target)
full_path = "/data/test.xml"
raw_records = etree.parse(full_path, parser)
print(raw_records)
if __name__ == '__main__':
test()
ParserTarget.py:
"""parser_target
data class for handling XML parsing
"""
from dataclasses import dataclass
@dataclass
class ParserTarget:
def __init__(self):
"""initialize the object variables
"""
self.mydata = ""
def start(self, tag, attrib):
"""catch the start event on parsing the xml file.
"""
print("start function: " + tag + " : " + str(attrib))
def data(self, data):
"""catch the data event on parsing the xml file.
"""
print("data function: " + data)
self.mydata = data
def end(self, tag):
"""catch the end event on parsing the xml file.
"""
print("end function: " + tag)
def close(self):
"""catch the close event on parsing the xml file.
"""
# done
return self.mydata
并将以下 xml 文件放入 /data 或根据需要更改代码中的文件夹:
test.xml:
<?xml version="1.0" encoding="UTF-8"?>
<part>
<name>STEVE O'NEILL</name>
<role tc="9">something - contingent</role>
<pct>10</pct>
<ind tc="0">False</ind>
</part>
当我运行代码时,输出是:
Parsing begins
start function: part : <lxml.etree._ImmutableMapping object at 0x000001FBCDBB9700>
data function:
start function: name : <lxml.etree._ImmutableMapping object at 0x000001FBCDBB9700>
data function: STEVE O
data function: '
data function: NEILL
end function: name
data function:
start function: role : {'tc': '9'}
data function: something - contingent
end function: role
data function:
start function: pct : <lxml.etree._ImmutableMapping object at 0x000001FBCDBB9700>
data function: 10
end function: pct
data function:
start function: ind : {'tc': '0'}
data function: False
end function: ind
data function:
end function: part
Process finished with exit code 0
因此请注意,数据函数实际上为单个“名称”标签调用了 3 次……并且它围绕这个字符被分解了。
解释为什么我只得到最后一块。
我将从现在开始追加..但是如果有更好的解析方法请告诉我。
谢谢
def data(self, data):
"""catch the data event on parsing the xml file.
"""
print("data function: " + data)
self.mydata = data
您的调试输出很清楚。文本显示为三个单独的文本节点,您只保留最后一个。
您必须跟踪标记的开头并连接在其中找到的任何文本节点。
self.mydata = data
需要
self.mydata += data
以便将标记的所有数据事件串联起来。
当然,一定要在'end'事件中清空self.mydata..或者在'start'事件中重新初始化等等
我没有听说过使用 LXML 的编码或其他选项来解释文本的任何其他方法..
我创建了一个自定义解析器来处理复杂的 XML 转换。 它很好用。已经工作了很长一段时间。 但是我刚刚注意到,当传入的 XML 文件具有标签和数据时,例如:
<ParticipantName>STEVE O'NEILL</ParticipantName>
数据事件 return 对我来说只是NEILL...而不是 STEVE O'NEILL
甚至 STEVE O'NEILL
我一直在阅读 lxml.. 我觉得这与编码选项有关.. 但我不太确定我读过的内容。很难找到处理这些 HTML 的答案?字符...甚至不确定我会尝试尝试什么编码..
现在,我创建解析器的方式是(parser_target 是我的自定义解析器):
parser = etree.XMLParser(target=parser_target)
raw_records = etree.parse(full_path, parser)
并且在数据事件中,我只是保存值..并return它在关闭事件中。
def data(self, data):
"""catch the data event on parsing the xml file.
"""
my_variable = data
我的代码比较复杂,所以这里只展示基础知识。 有谁知道如何干净地处理传入的 XML 具有这些 HTML(我认为)字符的数据? 我无法控制我收到的文件..所以我需要在它进来时处理它。
[编辑] 好的,在构建要分享的示例时,我想我已经找到了问题。当出现此文本时,数据事件似乎被多次调用。 如果有人在创建解析器时看到任何不同的/另一种通过 'encoding' 参数处理的方式.. 让我知道。
这是我构建的示例:
main.py:
from lxml import etree
from ParserTarget import ParserTarget
def test():
parser_target = ParserTarget()
print('Parsing begins')
parser = etree.XMLParser(target=parser_target)
full_path = "/data/test.xml"
raw_records = etree.parse(full_path, parser)
print(raw_records)
if __name__ == '__main__':
test()
ParserTarget.py:
"""parser_target
data class for handling XML parsing
"""
from dataclasses import dataclass
@dataclass
class ParserTarget:
def __init__(self):
"""initialize the object variables
"""
self.mydata = ""
def start(self, tag, attrib):
"""catch the start event on parsing the xml file.
"""
print("start function: " + tag + " : " + str(attrib))
def data(self, data):
"""catch the data event on parsing the xml file.
"""
print("data function: " + data)
self.mydata = data
def end(self, tag):
"""catch the end event on parsing the xml file.
"""
print("end function: " + tag)
def close(self):
"""catch the close event on parsing the xml file.
"""
# done
return self.mydata
并将以下 xml 文件放入 /data 或根据需要更改代码中的文件夹:
test.xml:
<?xml version="1.0" encoding="UTF-8"?>
<part>
<name>STEVE O'NEILL</name>
<role tc="9">something - contingent</role>
<pct>10</pct>
<ind tc="0">False</ind>
</part>
当我运行代码时,输出是:
Parsing begins
start function: part : <lxml.etree._ImmutableMapping object at 0x000001FBCDBB9700>
data function:
start function: name : <lxml.etree._ImmutableMapping object at 0x000001FBCDBB9700>
data function: STEVE O
data function: '
data function: NEILL
end function: name
data function:
start function: role : {'tc': '9'}
data function: something - contingent
end function: role
data function:
start function: pct : <lxml.etree._ImmutableMapping object at 0x000001FBCDBB9700>
data function: 10
end function: pct
data function:
start function: ind : {'tc': '0'}
data function: False
end function: ind
data function:
end function: part
Process finished with exit code 0
因此请注意,数据函数实际上为单个“名称”标签调用了 3 次……并且它围绕这个字符被分解了。 解释为什么我只得到最后一块。
我将从现在开始追加..但是如果有更好的解析方法请告诉我。 谢谢
def data(self, data):
"""catch the data event on parsing the xml file.
"""
print("data function: " + data)
self.mydata = data
您的调试输出很清楚。文本显示为三个单独的文本节点,您只保留最后一个。
您必须跟踪标记的开头并连接在其中找到的任何文本节点。
self.mydata = data
需要
self.mydata += data
以便将标记的所有数据事件串联起来。 当然,一定要在'end'事件中清空self.mydata..或者在'start'事件中重新初始化等等
我没有听说过使用 LXML 的编码或其他选项来解释文本的任何其他方法..