gpt4 book ai didi

python - 使用 Python ElementTree 迭代多个(父,子)节点

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

ElementTree for Python (2.6) 的标准实现不提供从子节点到父节点的指针。因此,如果需要 parent ,建议循环 parent 而不是 child 。

考虑我的 xml 的形式:

<Content>
<Para>first</Para>
<Table><Para>second</Para></Table>
<Para>third</Para>
</Content>

以下查找所有“Para”节点而不考虑父节点:

(1) paras = [p for p in page.getiterator("Para")]

这(改编自 effbot)通过遍历父节点而不是子节点来存储父节点:

(2) paras = [(c,p) for p in page.getiterator() for c in p]

这非常有意义,并且可以使用条件进行扩展以实现与 (1)(假设)相同的结果,但添加了父信息:

(3) paras = [(c,p) for p in page.getiterator() for c in p if c.tag == "Para"]

ElementTree documentation建议 getiterator() 方法进行深度优先搜索。在不查找父 (1) 的情况下运行它会产生:

first
second
third

但是,从 (3) 中的段落中提取文本会产生:

first, Content>Para
third, Content>Para
second, Table>Para

这似乎是广度优先的。

因此,这提出了两个问题。

  1. 这是正确且符合预期的行为吗?
  2. 当子项必须是某种类型而父项可以是任何类型时,您如何提取(父项、子项)元组,如果必须保持文档顺序。我不认为运行两个循环并将 (3) 生成的(父、子)映射到 (1) 生成的订单是理想的。

最佳答案

考虑一下:

>>> xml = """<Content>
... <Para>first</Para>
... <Table><Para>second</Para></Table>
... <Para>third</Para>
... </Content>"""
>>> import xml.etree.cElementTree as et
>>> page = et.fromstring(xml)
>>> for p in page.getiterator():
... print "ppp", p.tag, repr(p.text)
... for c in p:
... print "ccc", c.tag, repr(c.text), p.tag
...
ppp Content '\n '
ccc Para 'first' Content
ccc Table None Content
ccc Para 'third' Content
ppp Para 'first'
ppp Table None
ccc Para 'second' Table
ppp Para 'second'
ppp Para 'third'
>>>

旁白:列表推导式非常棒,直到您想确切地看到正在迭代的内容:-)

getiterator 正在按广告顺序生成“ppp”元素。但是,您是从附属的“ccc”元素中提取您感兴趣的元素,这些元素不是您想要的顺序。

一种解决方案是进行自己的迭代:

>>> def process(elem, parent):
... print elem.tag, repr(elem.text), parent.tag if parent is not None else None
... for child in elem:
... process(child, elem)
...
>>> process(page, None)
Content '\n ' None
Para 'first' Content
Table None Content
Para 'second' Table
Para 'third' Content
>>>

现在您可以在“Para”元素流过时捕获每个元素及其父元素(如果有的话)。

这可以很好地包装在生成器小工具中:

>>> def iterate_with_parent(elem):
... stack = []
... while 1:
... for child in reversed(elem):
... stack.append((child, elem))
... if not stack: return
... elem, parent = stack.pop()
... yield elem, parent
...
>>>
>>> showtag = lambda e: e.tag if e is not None else None
>>> showtext = lambda e: repr((e.text or '').rstrip())
>>> for e, p in iterate_with_parent(page):
... print e.tag, showtext(e), showtag(p)
...
Para 'first' Content
Table '' Content
Para 'second' Table
Para 'third' Content
>>>

关于python - 使用 Python ElementTree 迭代多个(父,子)节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4720476/

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