如何使用XPath选择以下特定XML节点?

时间:2016-05-25 04:30:35

标签: python xml python-2.7 xpath lxml

我有一个类似以下的XML文档:

<Objects>
  <object distName="a/b">  </object>
  <object distName="a/b/c1">  </object>
  <object distName="a/b/c4/d/e">  </object>
  <object distName="a/b/c2">  </object>
  <object distName="a/b/c6/d">  </object>
</Objects>

我需要选择所有路径以“c”+数字结尾的节点。例如:“ a / b / c1 ”和“ a / b / c2 ”,但不像“ a / b / c6 / d ” ,也不是“ a / b / c4 / d / e ”。

如果我尝试以下方法:

      `cNodes = xmlDoc.xpath("//object[contains(@path, `a/b/c`)]")`

然后这将包括“a / b / c6 / d”和“a / b / c4 / d / e”,这不是我要求的。

有没有办法在一行或两行代码中 。我的意思是我可以用循环和类似的东西来做,我不想这样做。那是因为真正的XML文档是数以千计的节点。

PS:Python 2.7,lxml

2 个答案:

答案 0 :(得分:1)

我担心这不能使用lxml支持的XPath版本的纯XPath 1.0来完成。

作为替代方案,您可以尝试按/拆分属性,获取最后一个拆分结果,并检查它是否以c开头,所有这一切都在列中使用列表推导,例如:

>>> raw = '''<Objects>
...   <object distName="a/b">  </object>
...   <object distName="a/b/c1">  </object>
...   <object distName="a/b/c4/d/e">  </object>
...   <object distName="a/b/c2">  </object>
...   <object distName="a/b/c6/d">  </object>
... </Objects>'''
... 
>>> from lxml import etree
>>> xmlDoc = etree.fromstring(raw)
>>> cNodes = xmlDoc.xpath("//object[contains(@path, 'a/b/c')]")
>>> result = [etree.tostring(n) for n in cNodes if n.attrib["distName"].split('/')[-1].startswith("c")]
>>> print result
['<object distName="a/b/c1">  </object>\n  ', '<object distName="a/b/c2">  </object>\n  ']

答案 1 :(得分:1)

不幸的是,使用XPath 1.0来表达匹配模式的条件并不是很简单。但是如果你可以对你正在寻找的东西做出某些假设,你可以制作这样的查询。

//object[starts-with(@distName, 'a/b/c') and substring-after(@distName, 'a/b/c') >= 0]

打破它,我们首先检查distName属性是否以a/b/c开头。然后如果该字符串之后的所有内容都是某个数根据您的需要,这可能就足够了。