ElementTree for Python(2.6)的标准实现不提供指向父节点的父节点的指针.因此,如果需要父母,建议循环过父母而不是孩子.
考虑我的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
这似乎是广度优先的.
因此,这提出了两个问题.
>这是正确和预期的行为吗?
>如果必须保留文档顺序,那么当子项必须属于某种类型但父项可以是任何项时,如何提取(父项,子项)元组.我不认为运行两个循环并将(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”元素进行snarf,每个元素在流过时都会引用其父元素(如果有).
这可以很好地包含在生成器小工具中:
>>> 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
>>>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。