我有一个类似以下的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
答案 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
开头。然后如果该字符串之后的所有内容都是某个数根据您的需要,这可能就足够了。