python 在 xml 文件上使用 lxml 的 xpath 问题

problems with xpath in python using lxml on xml file

我正在尝试从 rss-feed 中解析一些数据。这是它的外观示例

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" xmlns:admin="http://webns.net/mvcb/"     xmlns:syn="http://purl.org/rss/1.0/modules/syndication/">
    <channel rdf:about="http://somelink.com">
        <!-- ordinary stuff goes here -->
    </channel>
    <item rdf:about="http://www.some/random/link/123">
        <title>title</title>
        <link>
        http://www.some/random/link/123
        </link>
        <description>
            <![CDATA[
                ..description..
                ]]>
        </description>
        <dc:date>the date</dc:date>
    </item>
</rdf:RDF>

现在,我正在尝试从 rss 提要中获取每个 item 元素,这对于普通提要没有问题,但我似乎无法从中获取任何内容这个。它只是 returns 一个空列表。

这是我正在使用的代码:

from lxml import etree
tree = etree.parse(url)
items = tree.xpath("//item")

是不是和开头的rdf:RDF,或者里面的rdf:about=....有关每个项目标签?

以防万一:
- 该文件至少正在加载,因为 etree.tostring(tree) 确实产生了整个文件。
-我尝试过使用nsmap = tree.getroot().nsmap(),但我不知道我是否做对了
-在常规的 rss 提要上,tree.getroot() 产生 -> <Element rss at 0x2fa4260>,但在这个文件上,它产生 -> <Element {http://www.w3.org/1999/02/22-rdf-syntax-ns#}RDF at 0x2fa4288>

一旦您开始使用命名空间(即使是空的命名空间前缀),您必须在 xpath 中非常明确地说明您在谈论什么命名空间。

为此,lxml 提供了一个字典,其中键是名称空间前缀(随便你喜欢什么),值是各自的名称空间(完全限定名称):

from lxml import etree

xmlstr = """
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns="http://purl.org/rss/1.0/"
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/"
    xmlns:admin="http://webns.net/mvcb/"
    xmlns:syn="http://purl.org/rss/1.0/modules/syndication/">
    <channel rdf:about="http://somelink.com">
        <!-- ordinary stuff goes here -->
    </channel>
    <item rdf:about="http://www.some/random/link/123">
        <title>title</title>
        <link>
        http://www.some/random/link/123
        </link>
        <description>
            <![CDATA[
                ..description..
                ]]>
        </description>
        <dc:date>the date</dc:date>
    </item>
</rdf:RDF>"""

xmldoc = etree.fromstring(xmlstr)
nsmap = {"purl": "http://purl.org/rss/1.0/"}
res = xmldoc.xpath("//purl:item", namespaces=nsmap)
print res

print "xml", etree.tostring(res[0])

运行 这样的代码打印:

[<Element {http://purl.org/rss/1.0/}item at 0x7fc8fb20af80>]
xml <item xmlns="http://purl.org/rss/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" xmlns:admin="http://webns.net/mvcb/" xmlns:syn="http://purl.org/rss/1.0/modules/syndication/" rdf:about="http://www.some/random/link/123">
        <title>title</title>
        <link>
        http://www.some/random/link/123
        </link>
        <description>

                ..description..

        </description>
        <dc:date>the date</dc:date>
    </item>

教训是:

  • 请随意忽略文档中的命名空间前缀,它们实际上是次要信息。请注意,XML 允许在一个文档中针对不同的完全限定名称空间多次重复使用相同的名称空间前缀(可怕的想法,但确实如此)。
  • 请注意(充分理解)您真正要使用的完全限定名称空间。
  • 带有命名空间前缀和限定名称的字典可以使用您喜欢的任何命名空间前缀。它与源 XML 文件中的前缀无关。