有没有办法从ElementTree元素中获取行号
我正在用Python 3.2.1的cElementTree来解析一些XML文件。在解析的过程中,我发现有些标签缺少属性信息。我在想,有没有简单的方法可以获取这些元素在XML文件中的行号呢?
4 个回答
我在使用elementtree的时候,通过继承ElementTree.XMLTreeBuilder来实现这个功能。然后在我可以访问self._parser(Expat)的地方,它有两个属性,分别是_parser.CurrentLineNumber和_parser.CurrentColumnNumber。
http://docs.python.org/py3k/library/pyexpat.html?highlight=xml.parser#xmlparser-objects 里有关于这些属性的详细信息。
在解析过程中,你可以打印出一些信息,或者把这些值放到输出的XML元素属性里。
如果你的XML文件中包含了其他的XML文件,你需要做一些我不太记得的事情,而且文档也没有很好地说明,来跟踪当前的XML文件。
我花了一些时间才弄明白如何在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())
我查看了文档,发现用cElementTree似乎没有办法做到这一点。
不过,我在使用lxml的XML实现时运气不错。这个库应该可以直接替代cElementTree,因为它是基于libxml2的。而且,元素还有一个sourceline
属性。(此外,它还提供了很多其他XML功能。)
唯一需要注意的是,我只在python 2.x中使用过这个库,不确定它在3.x中是否能正常工作,但值得一试。
补充说明:在他们的首页上,他们提到:
lxml是一个Python的工具包,它是对C语言库libxml2和libxslt的绑定。它的独特之处在于,它将这些库的速度和XML功能的完整性与简单易用的Python API结合在一起,基本上兼容但优于大家熟知的ElementTree API。最新版本支持从2.3到3.2的所有CPython版本。有关lxml项目的背景和目标的更多信息,请查看介绍部分。常见问题在FAQ中有解答。
所以看起来python 3.x是可以的。