我有一个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树.
解决方法:
您可以使用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(数据与上例中的相同):
from lxml import etree
bundles = etree.fromstring(data)
for node in bundles.xpath('bundle/name[.="FOO"]/../bitstreams/bitstream/id'):
print(node.text)
输出:
1234
如果<比特流>元素始终位于< name>之前在元素中,您还可以使用更高效的xpath表达式:
'bundle/name[.="FOO"]/preceding-sibling::bitstreams/bitstream/id'