lxml のパーサー ターゲット インターフェイスを使用して、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 文字の長さのチャンクに分割するのは少しやり過ぎのようです。