【发布时间】:2011-10-20 10:25:22
【问题描述】:
所以我正在使用 Python 3.2.1 的 cElementTree 解析一些 XML 文件,在解析过程中我注意到一些标签缺少属性信息。我想知道是否有任何简单的方法可以在 xml 文件中获取这些元素的行号。
【问题讨论】:
标签: python xml python-3.x elementtree
所以我正在使用 Python 3.2.1 的 cElementTree 解析一些 XML 文件,在解析过程中我注意到一些标签缺少属性信息。我想知道是否有任何简单的方法可以在 xml 文件中获取这些元素的行号。
【问题讨论】:
标签: python xml python-3.x elementtree
我花了一段时间才弄清楚如何使用 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())
【讨论】:
filename 之后有不必要的)。
_start_line_number 属性的用法吗?我正在尝试tree.getroot()._start_line_number 并获得AttributeError。
_start_list 在定义 (def _start(self, *args, **kwargs):) 和调用 (element = super(self.__class__, self)._start(*args, **kwargs) ) 中都应该是 _start。
xml.etree.ElementTree 之前添加这一行:sys.modules['_elementtree'] = None。例如,您可以在脚本的开头添加sys.modules['_elementtree'] = None。那么在调用tree = ET.parse(filename, parser=LineNumberingParser())之后,tree.getroot()._start_line_number就可以工作了。
这样做的一种(hackish)方法是在解析之前将一个包含行号的虚拟属性插入每个元素。以下是我使用 minidom 的方法:
python reporting line/column of origin of XML node
这可以简单地调整为 cElementTree(或实际上任何其他 python XML 解析器)。
【讨论】:
我通过子类化 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 文件。
【讨论】:
查看文档,我发现无法使用 cElementTree 执行此操作。
不过,我对lxmls 版本的 XML 实现很幸运。
使用libxml2,它应该几乎是替代品。并且元素有一个sourceline 属性。 (以及获得许多其他 XML 功能)。
唯一需要注意的是,我只在 python 2.x 中使用过它——不确定它在 3.x 下如何/是否工作——但可能值得一看。
附录: 他们在首页上说:
lxml XML 工具包是 C 库 libxml2 的 Pythonic 绑定 和 libxslt。它的独特之处在于它结合了速度和 XML 这些库的功能完整性与简单的 原生 Python API,大部分兼容但优于众所周知的 元素树 API。最新版本适用于所有 CPython 版本 从 2.3 到 3.2。有关更多信息,请参阅介绍 lxml 项目的背景和目标。一些常见问题是 在常见问题解答中回答。
所以看起来python 3.x是可以的。
【讨论】: