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