2015-08-14 85 views
0

我试图解析rss-feed中的一些数据。这是它的外观在xml文件中使用lxml的xpath中xpath的问题

<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源,这是一个正常的饲料没有问题,每项目元素的例子,但我似乎无法得到任何东西都来自这个。它只是返回一个空列表。

这是我使用的代码:

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

是否有做的RDF:在开始RDF,或RDF:在每一个约= ....物品标签?

以防万一:
-The文件至少装载监守etree.tostring(tree)没有得到整个文件。
-I've尝试使用nsmap = tree.getroot().nsmap(),但我不知道如果我这样做是正确的
-On常规RSS提要的tree.getroot()收益率 - ><Element rss at 0x2fa4260>,但在这个文件中,它产生 - ><Element {http://www.w3.org/1999/02/22-rdf-syntax-ns#}RDF at 0x2fa4288>

回答

1

只要开始使用名称空间(即使是空名称空间前缀),您也必须在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允许在一个文档中多次重复使用相同的名称空间前缀,用于不同的完全限定名称空间(可怕的想法,但是是true)。
  • 不要小心(理解不错),你真正要使用的完全合格的命名空间。
  • 带有名称空间前缀和限定名称的字典可能使用任何您喜欢的名称空间前缀。它与源XML文件中的前缀无关。
+0

非常感谢!感谢您的好答复,并且您的代码像魅力一样工作,尽管我不明白为什么某些事情已经完成,但我想我很快就会发现它。无论如何,我现在试图迭代我发现的每个项目,我将如何从每个项目获得标题/链接/等?普通的'item.find(“title”)'不起作用,'purl:item',nsmap'也不起作用。但再次感谢 – theusual

+0

没关系,我设法弄清楚了。 'item.xpath(“./ purl:title”,namespaces = nsmap)',我错过了意外的时间段(。)。 – theusual