向lxml元素添加行号

时间:2019-03-07 17:14:55

标签: xml python-2.7 parsing lxml

我正在尝试找到一种方法,将原始XML文本中的行号添加到python的lxml模块的XML树中构建的每个元素中。可以让我从树中获取元素并简单地对

起作用的某种东西
       line_num = element.xml_line_num

我知道lxml树元素中有一个sourceline属性,但这并不可靠。这并不总是正确的。使用python 2.7默认提供的基本ElementTree时,默认解析器具有一个名为GetInputContext()的方法,我可以通过在原始XML文本中的行之间循环并与从该输入上下文方法获得的文本进行比较来使用该方法。我很快从默认解析器中发现CurrentLineNumber不可靠。必须诉诸XML源字符串比较。

无论如何,我对模块的子类化和使事情正常工作的理解还不够。成熟且广泛使用的Python模块在使用Python的许多方面时,往往会变得非常彻底和广泛,当您谈到要处理基础基类的C代码实现时,就会感到困惑。因此,我们将不胜感激一些帮助,也许还有一些示例代码。提前致谢!

让我添加一些说明。我希望有这样的代码:

from lxml import etree as ET


xml_tree = ET.fromstringlist(xml_file_lines)

for xml_element in xml_tree.iter():

    line_num = xml_element.xml_line_num

'xml_file_lines'是从文件中读取的XML文件行的列表。其中一些是空行。关于正在处理的文件中的XML行,我可以说的是,非空白行和未注释的行确实显示为打开,关闭,自关闭或打开/关闭元素。就是这样说的:

<tag>text</tag>
<tag1 />
<tag2 id = "yum" />
<tag2 id = "delicious" name = "tasty">text</tag>
<tag3>
     <tag4>hungry</tag4>
<tag3>

在这些XML文件的任何一行上,XML标记的开头或结尾都不得超过一个。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

好的,所以我知道了。如果您从XML文件行的字符串列表中将XML数据加载到lxml etree中,然后使用feed解析器,则可以获取lxml etree元素的sourceline属性来获取每个XML元素所源自的XML文件行。下面的代码演示了我的工作:

from lxml import etree as ET

class LineNumberingParser(ET.XMLParser):

      def __init__(self, *args, **kwargs):

          super(self.__class__, self).__init__(*args, **kwargs)

      def feed(self, data):

           line = data.strip() + "\n"
           super(self.__class__, self).feed(line)     

然后您需要做的就是告诉lxml使用行解析器:

from lxml import etree as ET

class LineNumberingParser(ET.XMLParser):

      def __init__(self, *args, **kwargs):

          super(self.__class__, self).__init__(*args, **kwargs)

      def feed(self, data):

           line = data.strip() + "\n"
           super(self.__class__, self).feed(line)     

with open(file.xml, "rU") as FILE:
     xml_file_lines = FILE.readlines()

xml_tree = ET.fromstringlist(xml_file_lines, parser=LineNumberingParser()) 

for xml_element in xml_tree.iter():
    print "XML tag " + xml_element.tag + " found on file line " + str(xml_element.sourceline) + "\n" 

甚至没有必要将lxml XMLParser子类化。可能需要做的就是将XML文件的行作为字符串列表读取,并使用etree.fromstringlist()只要每行的末尾都有换行符,我认为一切都很好。