2015-08-17 105 views
3

我有一个简短的XML文档:Python lxml:如何为XML元素获取人类可读的XPath?

<tag1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns="http://example.com/2009/namespace"> 
    <tag2> 
     <tag3/> 
     <tag3/> 
    </tag2> 
</tag1> 

一个简短的Python程序加载这个XML文件是这样的:

from lxml import etree 

f = open('myxml.xml') 
tree = etree.parse(f) 
MY_NAMESPACE = 'http://example.com/2009/namespace' 
xpath = etree.XPath('/f:tag1/f:tag2/f:tag3', namespaces = { 'f': MY_NAMESPACE }) 
# get first element that matches xpath 
elem = xpath(tree)[0] 
# get xpath for an element 
print tree.getpath(elem) 

我期待得到一个有意义的,人类可读的XPath与此代码,然而,相反,我得到一个字符串,如/*/*/*[1]

任何想法可能导致这种情况以及我如何诊断此问题?

注意:使用Python 2.7.9和2.3 LXML

+0

它看起来像是给你绝对的XPath来访问元素,这似乎是最程序化的访问它的明智方式。虽然没有[MCVE](http://stackoverflow.com/help/mcve),但很难告诉你为什么,以及是否可以更好地完成某些任务。 – zmo

+0

@zmo该程序本身非常小,但是我用来重现问题的XML文档相当长。你认为什么是我可以在这里公布考试的最佳方式? – sneg

+0

'/ */* [1]/* [2]'是所谓的_positional_ XPath表达式。但它似乎并不是一个复杂的文件。如果你发现你的代码的行为令人费解,那么可以避免复杂性,然后重试。如果你想要任何人来诊断这个问题,我们绝对需要看到输入文档 - 最短的那个仍然会显示这种行为。 –

回答

2

它看起来像getpath()(libxml2的呼叫xmlGetNodePath底层)产生用于名称空间的文档位置的xpath表达式。 评论部分中的用户mzjn指出,自lxml v3.4.0以来,函数getelementpath()会生成具有完全限定标记名称(使用"Clark notation")的人类可读xpath。此函数通过遍历从节点到根的树来生成xpath,而不是使用libxml2 API调用。

同样,如果lxml v3.4 +不可用,可以编写自己的树遍历函数。

+0

'getelementpath()'产生的路径没有命名空间前缀;它具有完全限定的名称(使用“Clark符号”)。 – mzjn

+0

根据http://lxml.de/index.html#download,最新版本的lxml是3.4.4。在3.4.0中引入了'getelementpath'。 – mzjn

+0

谢谢@mzjn,答案已更正。 – sneg