【问题标题】:Python: libxml2 xpath returns empty listPython:libxml2 xpath 返回空列表
【发布时间】:2011-05-04 22:18:17
【问题描述】:

我想使用 xpath 使用 Python 的 libxml2 解析 XML 内容,我关注了 this examplethat tutorial。 XML 文件是:

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://purl.org/atom/ns#" version="0.3">
<title>Gmail - Inbox for myemailaddress@gmail.com</title>
<tagline>New messages in your Gmail Inbox</tagline>
<fullcount>1</fullcount>
<link rel="alternate" href="http://mail.google.com/mail" type="text/html"/>
<modified>2011-05-04T18:56:19Z</modified>
</feed>

此 XML 存储在一个名为“atom”的文件中,我尝试以下操作:

>>> import libxml2
>>> myfile = open('/pathtomyfile/atom', 'r').read()
>>> xmldata = libxml2.parseDoc('myfile')
>>> data.xpathEval('/fullcount')
[]
>>>

现在你可以看到它返回一个空列表。无论我可以为 xpath 提供什么,它都会返回一个空列表。但是,如果我使用 * 通配符,我会得到所有节点的列表:

>>>> data.xpathEval('//*')
[<xmlNode (feed) object at 0xb73862cc>, <xmlNode (title) object at 0xb738650c>, <xmlNode (tagline) object at 0xb73865ec>, <xmlNode (fullcount) object at 0xb738660c>, <xmlNode (link) object at 0xb738662c>, <xmlNode (modified) object at 0xb738664c>]

现在我不明白,从上面的工作示例来看,为什么 xpath 找不到“fullcount”节点或任何其他节点:毕竟我使用的是相同的语法......

有什么想法或建议吗?谢谢。

【问题讨论】:

  • 我为什么要这样做? :) 我现在正在查看 lxml 文档。谢谢。
  • 它是 libxml2 的绑定。我什至不知道有替代绑定,但 lxml 非常直观。

标签: python list xpath libxml2


【解决方案1】:

您的 XPath 失败,因为您需要在节点上指定 purl 命名空间

import libxml2
tree = libxml2.parseDoc(data)
xp = tree.xpathNewContext()
xp.xpathRegisterNs("purl", "http://purl.org/atom/ns#")
print xp.xpathEval('//purl:fullcount')

结果:

[<xmlNode (fullcount) object at 0x7fbbeba9ef80>]

(另外:查看 lxml,它有一个更好、更高级别的界面)。

【讨论】:

  • 工作答案谢谢 :) 现在,什么是 purl 命名空间?你能解释一下吗?
  • @Benjamin 这是文档的默认命名空间,在提要标签上定义:&lt;feed xmlns="http://purl.org/atom/ns#" version="0.3"&gt;。这是将文档中的所有节点分配给该命名空间的快捷方式。因此,每当您向 libxml2 询问本文档中的某个节点并且未能包含命名空间时,它都不知道您的意思。 :-)
  • 谢谢,我是命名空间概念的新手。命名空间究竟提供了什么定义?
  • @Benjamin 命名空间是 XML 标准的一部分,它允许来自不同世界的元素和属性一起存在于一个文档中而不会发生冲突。例如,节点image 可能意味着两个不同的东西,具体取决于命名空间,例如foo:imagebar:image。命名空间通常对应于定义一种文档类型的某些 DTD 或模式,例如 Atom 提要格式,它将定义您应该期望在使用该命名空间的文档中看到哪些元素/属性。
【解决方案2】:

首先:

/fullcount 是一个绝对路径,因此它会在文档根目录中查找 &lt;fullcount&gt; 元素,而该元素实际上是在 &lt;feed&gt; 元素中。

其次:

您需要指定命名空间。这就是您使用lxml 的方式:

import lxml.etree as etree

tree = etree.parse('/pathtomyfile/atom')

fullcounts = tree.xpath('//ns:fullcount',
                namespaces={'ns': "http://purl.org/atom/ns#"})

print etree.tostring(fullcounts[0])

这会给你:

<fullcount xmlns="http://purl.org/atom/ns#">1</fullcount>

【讨论】:

    猜你喜欢
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 2016-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多