XPATH - 获取父母和孩子的元组

时间:2018-01-24 12:42:30

标签: python xml xpath

假设这是我的XML:

<animals>
   <mammals> 
      <an>dog</an>
      <an>cat</an>
   </mammals>
   <reptiles>
      <an>snake</an>
   </reptiles>
</animals>

我想要的是使用xpath来获取这样的元组:

(mammals,dog)
(mammals,cat)
(reptiles,snake)

要分别获取每个,或者两个查询都很容易。 我想知道是否有办法在1 xpath查询中获得它(或非常相似的输出)。

任何帮助将不胜感激!

4 个答案:

答案 0 :(得分:2)

使用lxml

from io import StringIO

from lxml import etree

xml = """<animals>
   <mammals> 
      <an>dog</an>
      <an>cat</an>
   </mammals>
   <reptiles>
      <an>snake</an>
   </reptiles>
</animals>"""

tree = etree.parse(StringIO(xml))

for x in tree.xpath("/animals/*"):
    for y in x:
        print((x.tag, y.text))

输出:

('mammals', 'dog')
('mammals', 'cat')
('reptiles', 'snake')

答案 1 :(得分:1)

尝试在python中使用xml模块

from xml.etree import  ElementTree

def parse_data(xml_str):
    output = []
    tree = ElementTree.fromstring(xml_str)
    for m in tree.getchildren():
        for n in m.getchildren():
           output.append((m.tag, n.text,))
    return output

xml_str = '''
<animals>
   <mammals> 
      <an>dog</an>
      <an>cat</an>
   </mammals>
   <reptiles>
      <an>snake</an>
   </reptiles>
</animals>'''

print parse_data(xml_str)
# output: [('mammals', 'dog'), ('mammals', 'cat'), ('reptiles', 'snake')]

答案 2 :(得分:1)

在XPath 2.0或更高版本中,您可以使用for构造(demo):

for $x in /animals/*/*
return concat($x/parent::*/name(), ',', $x/text())

但是在仅支持XPath 1.0的lxml中,我们需要用python的for循环替换它:

from lxml import etree

raw = """<animals>
   <mammals> 
      <an>dog</an>
      <an>cat</an>
   </mammals>
   <reptiles>
      <an>snake</an>
   </reptiles>
</animals>"""
root = etree.fromstring(raw)

for x in root.xpath("/animals/*/*"):
    print (x.getparent().tag, x.text)

答案 3 :(得分:0)

此xpath返回请求的字符串,但仅针对第一个元素。使用纯XPath可能很难

'concat("(", local-name(//animals/*), ",", //animals/*/an/text(), ")")'

xmllint --xpath 'concat("(", local-name(//animals/*), ",", //animals/*/an/text(), ")")' ~/tmp/test.xml
(mammals,dog)