LXML 解析器在数据事件中丢失文本

LXML parser loses text in data event

我创建了一个自定义解析器来处理复杂的 XML 转换。 它很好用。已经工作了很长一段时间。 但是我刚刚注意到,当传入的 XML 文件具有标签和数据时,例如:

<ParticipantName>STEVE O&apos;NEILL</ParticipantName>

数据事件 return 对我来说只是NEILL...而不是 STEVE O&apos;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&apos;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 的编码或其他选项来解释文本的任何其他方法..