【问题标题】:Python lxml: how to get human-readable XPath for XML element?Python lxml:如何为 XML 元素获取人类可读的 XPath?
【发布时间】:2015-08-17 11:39:41
【问题描述】:

我有一个简短的 XML 文档:

<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 和 lxml 2.3

【问题讨论】:

  • 看起来它为您提供了访问元素的绝对 XPath,这似乎是访问它的最明智的编程方式。虽然没有MCVE,但很难告诉你为什么以及你是否能得到更好的东西。
  • @zmo 程序本身很小,但是我用来重现该问题的 XML 文档却很长。您认为我可以将其张贴在这里进行检查的最佳方式是什么?
  • 设法用一个很小的 ​​XML 文件重现!问题已更新。
  • 我编写了一个小型 C 程序,使用底层 C 调用 xmlGetNodePath 在 libxml2 中尝试此操作,我观察到相同的行为。请注意,如果我去掉命名空间,生成的 xpath 是 /tag1/tag2/tag3[1] 而不是 /*/*/*[1]
  • getelementpath(),结果是{http://example.com/2009/namespace}tag2/{http://example.com/2009/namespace}tag3[1](不包括根元素)。

标签: python xpath lxml


【解决方案1】:

看起来 getpath()(底层 libxml2 调用 xmlGetNodePath)为命名空间文档生成位置表达式 xpath。 cmets 部分中的用户 mzjn 指出,从 lxml v3.4.0 开始,函数 getelementpath() 会生成一个具有完全限定标签名称的人类可读 xpath(使用 "Clark notation")。此函数通过从节点到根遍历树而不是使用 libxml2 API 调用来生成 xpath。

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

【讨论】:

  • getelementpath()产生的路径没有命名空间前缀;它具有完全限定的名称(使用“克拉克符号”)。
  • 根据lxml.de/index.html#download,lxml的最新版本是3.4.4。而getelementpath 是在 3.4.0 中引入的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-05
  • 2020-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多