如何用XPath获取按父元素分组的嵌套列表(序列的序列)
问题:使用XPath获取按父元素分组的嵌套列表
我希望使用XPath获取按父元素有序分组的嵌套列表(或序列的序列),即提取的XML标签按父元素分组。以下是我用最小示例做的尝试:
import elementpath, lxml.etree xml = '''<a> <b c="1"> <d e="3"/> <d e="4"/> </b> <b c="2"> <d e="5"/> <d e="6"/> </b> </a>''' tree = lxml.etree.fromstring(str.encode(xml)) xpath1 = '/a/b/d/@e' xpath2 = 'for $b in (/a/b) return concat("[", $b/string-join(d/@e, ", "), "]")' print('1:', elementpath.select(tree, xpath1)) print('2:', elementpath.select(tree, xpath2)) print('3:', [['3', '4'], ['5', '6']])
输出结果:
1: ['3', '4', '5', '6'] 2: ['[3, 4]', '[5, 6]'] 3: [['3', '4'], ['5', '6']]
xpath1返回无父元素分组的扁平列表;xpath2最接近需求,但子数组为字符串形式;我需要的是像option3那样的嵌套列表。请问仅用XPath如何实现?
解答
要得到目标嵌套列表,直接利用XPath 2.0+的序列构造能力即可,不需要拼接字符串。使用以下XPath表达式:
for $b in /a/b return $b/d/@e
替换到代码中测试:
import elementpath, lxml.etree xml = '''<a> <b c="1"> <d e="3"/> <d e="4"/> </b> <b c="2"> <d e="5"/> <d e="6"/> </b> </a>''' tree = lxml.etree.fromstring(str.encode(xml)) xpath3 = 'for $b in /a/b return $b/d/@e' print('3:', elementpath.select(tree, xpath3))
运行输出:
3: [['3', '4'], ['5', '6']]
关键说明
elementpath库支持XPath 2.0语法,而XPath 2.0允许返回序列的序列(即嵌套结构)。- 表达式中
for $b in /a/b遍历每个<b>节点,return $b/d/@e直接返回该节点下所有d元素的e属性组成的序列,最终被转换为Python的嵌套列表。 - 之前的
xpath2用concat把属性值拼接成了字符串,破坏了序列结构,直接返回属性序列就能保留分组后的嵌套格式。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

