XML节点的python报告行/原始列
我目前正在使用xml.dom.minidom在python中解析一些xml。解析之后,我将对内容进行一些报告,并希望报告标记在源XML文档中开始的行(和列),但我不认为这是可能的 如果可能的话,我希望继续使用xml.dom/xml.dom.minidom,但是如果我需要使用SAX解析器来获取源信息,我可以做到这一点——理想的情况是使用SAX跟踪节点位置,但最终还是使用dom进行后期处理XML节点的python报告行/原始列,python,xml,dom,sax,Python,Xml,Dom,Sax,我目前正在使用xml.dom.minidom在python中解析一些xml。解析之后,我将对内容进行一些报告,并希望报告标记在源XML文档中开始的行(和列),但我不认为这是可能的 如果可能的话,我希望继续使用xml.dom/xml.dom.minidom,但是如果我需要使用SAX解析器来获取源信息,我可以做到这一点——理想的情况是使用SAX跟踪节点位置,但最终还是使用dom进行后期处理 有什么建议吗?希望我只是忽略了文档中的一些内容,这非常简单。通过MonkeyPatch minidom内容处理
有什么建议吗?希望我只是忽略了文档中的一些内容,这非常简单。通过MonkeyPatch minidom内容处理程序,我能够记录每个节点的行数和列数(作为“parse_position”属性)。这有点脏,但我看不到任何“官方认可”的方法:)这是我的测试脚本:
from xml.dom import minidom
import xml.sax
doc = """\
<File>
<name>Name</name>
<pos>./</pos>
</File>
"""
def set_content_handler(dom_handler):
def startElementNS(name, tagName, attrs):
orig_start_cb(name, tagName, attrs)
cur_elem = dom_handler.elementStack[-1]
cur_elem.parse_position = (
parser._parser.CurrentLineNumber,
parser._parser.CurrentColumnNumber
)
orig_start_cb = dom_handler.startElementNS
dom_handler.startElementNS = startElementNS
orig_set_content_handler(dom_handler)
parser = xml.sax.make_parser()
orig_set_content_handler = parser.setContentHandler
parser.setContentHandler = set_content_handler
dom = minidom.parseString(doc, parser)
pos = dom.firstChild.parse_position
print("Parent: '{0}' at {1}:{2}".format(
dom.firstChild.localName, pos[0], pos[1]))
for child in dom.firstChild.childNodes:
if child.localName is None:
continue
pos = child.parse_position
print "Child: '{0}' at {1}:{2}".format(child.localName, pos[0], pos[1])
另一种解决问题的方法是在解析文档之前将行号信息修补到文档中。我的想法是:
LINE_DUMMY_ATTR = '_DUMMY_LINE' # Make sure this string is unique!
def parseXml(filename):
f = file.open(filename, 'r')
l = 0
content = list ()
for line in f:
l += 1
content.append(re.sub(r'<(\w+)', r'<\1 ' + LINE_DUMMY_ATTR + '="' + str(l) + '"', line))
f.close ()
return minidom.parseString ("".join(content))
很明显,这种方法有它自己的缺点,如果您真的也需要列号,那么在中对其进行修补将更加复杂。此外,如果要提取文本节点或注释,或使用Node.toXml()
,则必须确保从任何意外匹配中删除行\u DUMMY\u ATTR,如下所示
与aknuds1的答案相比,此解决方案的一个优点是它不需要处理minidom内部结构。
xmlparser
fromxml.parsers.expat
支持行号/列号<代码>lxml.etree支持行号。
LINE_DUMMY_ATTR = '_DUMMY_LINE' # Make sure this string is unique!
def parseXml(filename):
f = file.open(filename, 'r')
l = 0
content = list ()
for line in f:
l += 1
content.append(re.sub(r'<(\w+)', r'<\1 ' + LINE_DUMMY_ATTR + '="' + str(l) + '"', line))
f.close ()
return minidom.parseString ("".join(content))
int (element.getAttribute (LINE_DUMMY_ATTR))