我有一个要解析的XML,这对我来说非常棘手。
<bundles>
<bundle>
<bitstreams>
<bitstream>
<id>1234</id>
</bitstream>
</bitstream>
<name>FOO</name>
</bundle>
<bundle> ... </bundle>
</bundles>
我想遍历此XML并找到比特流内的所有 id 值,以获取捆绑,其中 name 元素的值为'FOO'。我对任何未命名为'FOO'的捆绑包都不感兴趣,捆绑包中可能有任意数量的捆绑包和任意数量的比特流。
我一直在使用tree.findall('./bundle/name')
来查找FOO捆绑包但这只会返回一个我无法单步执行 id 值的列表:
for node in tree.findall('./bundle/name'):
if node.text == 'FOO':
id_values = tree.findall('./bundle/bitstreams/bitstream/id')
for value in id_values:
print value.text
这打印出所有的id值,而不是捆绑'FOO'的值。
如何遍历此树,使用名称 FOO找到捆绑,使用此捆绑节点并收集 id 嵌套在其中的值?这里的XPath参数是否不正确?
我正在使用Python进行lxml
绑定 - 但我认为任何XML解析器都没问题;这些不是大型XML树。
答案 0 :(得分:6)
您可以使用xpath
来达到目的。以下Python代码完美无缺:
import libxml2
data = """
<bundles>
<bundle>
<bitstreams>
<bitstream>
<id>1234</id>
</bitstream>
</bitstreams>
<name>FOO</name>
</bundle>
</bundles>
"""
doc = xmllib2.parseDoc(data)
for node in doc.xpathEval('/bundles/bundle/name[.="FOO"]/../bitstreams/bitstream/id'):
print node
或使用lxml
(data
与上例相同):
from lxml import etree
bundles = etree.fromstring(data)
for node in bundles.xpath('bundle/name[.="FOO"]/../bitstreams/bitstream/id'):
print(node.text)
输出:
1234
如果<bitstreams>
元素始终位于<name>
元素之前,您还可以使用更高效的xpath表达式:
'bundle/name[.="FOO"]/preceding-sibling::bitstreams/bitstream/id'