有没有办法从ElementTree元素获取行号

时间:2011-08-04 22:29:47

标签: python xml python-3.x elementtree

所以我使用Python 3.2.1的cElementTree解析一些XML文件,在解析过程中我注意到有些标签缺少属性信息。我想知道是否有任何简单的方法来获取xml文件中这些元素的行号。

4 个答案:

答案 0 :(得分:13)

查看文档,我认为无法使用cElementTree执行此操作。

然而,我对lxml版本的XML实现感到满意。 使用libxml2它应该几乎是替代品。元素具有sourceline属性。 (以及获得许多其他XML功能)。

唯一需要注意的是我只在python 2.x中使用它 - 不确定它是如何/如果它在3.x下工作 - 但可能值得一看。

附录: 从他们的头版他们说:

  

lxml XML工具包是C库libxml2的Pythonic绑定   和libxslt。它的独特之处在于它结合了速度和XML   这些库的完整性具有简单性   原生Python API,大多兼容但优于众所周知的   ElementTree API。最新版本适用于所有CPython版本   从2.3到3.2。有关详细信息,请参阅简介   lxml项目的背景和目标。一些常见的问题是   在FAQ中回答。

所以看起来python 3.x还可以。

答案 1 :(得分:8)

花了一段时间让我弄清楚如何使用Python 3.x(在这里使用3.3.2)这样做,所以我想总结一下:

# Force python XML parser not faster C accelerators
# because we can't hook the C implementation
sys.modules['_elementtree'] = None
import xml.etree.ElementTree as ET

class LineNumberingParser(ET.XMLParser):
    def _start_list(self, *args, **kwargs):
        # Here we assume the default XML parser which is expat
        # and copy its element position attributes into output Elements
        element = super(self.__class__, self)._start_list(*args, **kwargs)
        element._start_line_number = self.parser.CurrentLineNumber
        element._start_column_number = self.parser.CurrentColumnNumber
        element._start_byte_index = self.parser.CurrentByteIndex
        return element

    def _end(self, *args, **kwargs):
        element = super(self.__class__, self)._end(*args, **kwargs)
        element._end_line_number = self.parser.CurrentLineNumber
        element._end_column_number = self.parser.CurrentColumnNumber
        element._end_byte_index = self.parser.CurrentByteIndex
        return element

tree = ET.parse(filename, parser=LineNumberingParser())

答案 2 :(得分:2)

我通过继承ElementTree.XMLTreeBuilder在elementtree中完成了这个。然后,我可以访问self._parser(Expat),它具有属性_parser.CurrentLineNumber和_parser.CurrentColumnNumber。

http://docs.python.org/py3k/library/pyexpat.html?highlight=xml.parser#xmlparser-objects包含有关这些属性的详细信息

在解析过程中,您可以打印出信息,或将这些值放入输出XML元素属性中。

如果您的XML文件包含其他XML文件,则必须执行一些我不记得的内容,并且没有详细记录以跟踪当前的XML文件。

答案 3 :(得分:0)

这样做的一种(hackish)方法是在解析之前插入一个将行号保存到每个元素中的虚拟属性。以下是我用minidom做到这一点的方法:

python reporting line/column of origin of XML node

这可以简单地调整为cElementTree(或实际上任何其他python XML解析器)。