gpt4 book ai didi

python - 当输入开始标记时,lxml 的解析器目标不会立即触发 'start' 回调

转载 作者:数据小太阳 更新时间:2023-10-29 02:41:55 27 4
gpt4 key购买 nike

我试图使用 lxml 的 parser target interface逐步将 XML 解析为“自定义”树,我遇到了以下问题:如果您实例化解析器并立即将根元素的开始标记提供给它,则目标的“开始”回调不会触发,直到任何其他事件发生(例如传入数据、结束标记、另一个开始标记等)。这似乎不会发生在任何其他(嵌套)元素上。

演示:

class EchoTarget(object):
def start(self, tag, attrib):
print("start %s %s" % (tag, attrib))
def end(self, tag):
print("end %s" % tag)
def data(self, data):
print("data %r" % data)
def comment(self, text):
print("comment %s" % text)
def close(self):
print("close")
return "closed!"

>>> p = etree.XMLParser(target=EchoTarget())
>>> p.feed('<a>') # nothing happens
>>> p.feed(' ') # suddenly..
start a {}
>>> p.feed('<b>') # works as expected
data u' '
start b {}

有一种方法可以解决这个问题:

>>> p = etree.XMLParser(target=EchoTarget())
>>> p.feed(' ')
>>> p.feed('<a>')
start a {}

请问这是怎么解释的?解决方法“有效”吗?也就是说,依靠这种行为来确保流中的第一个开始标记将触发“开始”回调是否安全?

顺便说一句,还有另一种方法可以达到这个结果:

>>> p = etree.XMLParser(target=EchoTarget())
>>> p.feed('<a')
>>> p.feed('>')
start a {}

但是,将流分成 2 个字符长度的 block 似乎有点矫枉过正。

最佳答案

从阅读文档来看,这似乎是预期的行为(引自 http://lxml.de/parsing.html#the-feed-parser-interface):

"If you do not call close(), the parser will stay locked and subsequent feeds will keep appending data, usually resulting in a non well-formed document and an unexpected parser error. So make sure you always close the parser after use, also in the exception case."

因此解析器正在“等待”更多内容被提供或关闭。您可以通过调用 close 方法来验证您提供的内容不是有效的 XML(目前):

>>> p.feed('<a>')
>>> p.close()
start a {}
close
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "parser.pxi", line 1171, in lxml.etree._FeedParser.close (src/lxml/lxml.etree.c:79791)
File "parsertarget.pxi", line 128, in lxml.etree._TargetParserContext._handleParseResult (src/lxml/lxml.etree.
c:88895)
File "parser.pxi", line 590, in lxml.etree._raiseParseError (src/lxml/lxml.etree.c:74696)
XMLSyntaxError: Extra content at the end of the document, line 1, column 4

因此,例如关闭打开的标签(有效的 XML)将产生:

>>> p = etree.XMLParser(target=EchoTarget())
>>> p.feed('<a>')
>>> p.feed('</a>')
start a {}
end a

希望这对您有所帮助。

关于python - 当输入开始标记时,lxml 的解析器目标不会立即触发 'start' 回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10734277/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com