2008-11-17 38 views
21

我对下面的测试文档测试:为什么xpath在使用lxml处理XHTML文档时不工作(在python中)?

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
     <title>hi there</title> 
    </head> 
    <body> 
     <img class="foo" src="bar.png"/> 
    </body> 
</html> 

如果我解析使用lxml.html文件,我可以用XPath就好得到IMG:,

>>> root = lxml.html.fromstring(doc) 
>>> root.xpath("//img") 
[<Element img at 1879e30>] 

但是如果我解析文档的XML,并得到IMG标记,我得到一个空的结果:

>>> tree = etree.parse(StringIO(doc)) 
>>> tree.getroot().xpath("//img") 
[] 

我可以浏览到直接的元素:

>>> tree.getroot().getchildren()[1].getchildren()[0] 
<Element {http://www.w3.org/1999/xhtml}img at f56810> 

但当然这并不能帮助我处理任意文件。我也希望能够查询etree得到的XPath表达式将直接确定此元素,从技术上讲我可以这样做:

>>> tree.getpath(tree.getroot().getchildren()[1].getchildren()[0]) 
'/*/*[2]/*' 
>>> tree.getroot().xpath('/*/*[2]/*') 
[<Element {http://www.w3.org/1999/xhtml}img at fa1750>] 

但是,XPath是,再次,显然不是有益的解析任意文件。

显然我错过了这里的一些关键问题,但我不知道它是什么。我最好的猜测是它与命名空间有关,但唯一定义的命名空间是默认的,我不知道我还需要考虑命名空间。

那么,我错过了什么?

回答

27

问题是命名空间。当以XML解析时,img标签位于http://www.w3.org/1999/xhtml名称空间中,因为它是该元素的默认名称空间。你在没有命名空间的情况下要求提供img标签。

试试这个:

>>> tree.getroot().xpath(
...  "//xhtml:img", 
...  namespaces={'xhtml':'http://www.w3.org/1999/xhtml'} 
... ) 
[<Element {http://www.w3.org/1999/xhtml}img at 11a29e0>] 
+0

从报价http://codespeak.net/lxml/xpathxslt.html <<或者,你可以提供一个命名空间关键字参数,这应该是映射字典命名空间URI中使用的名称空间前缀>> – 2009-06-14 14:50:07

7

XPath considers all unprefixed names to be in "no namespace"

在具体的规范说:

“,在节点测试的QName使用命名空间声明从表达式上下文扩展成一个扩展名这是相同的方式膨胀是在用于元件类型名称来完成。开始和结束标签,除非不使用用xmlns声明的默认名称空间:如果QName没有前缀,则名称空间URI为空(这与属性名称的扩展方式相同)。“

请参阅这两个问题的详细解释及其解决方案:herehere。解决方案是将前缀(使用正在使用的API)与前缀关联,并将其用于在XPath表达式中前缀任何前缀无名的前缀。

希望这有助于。

干杯,

Dimitre Novatchev

2

如果你要使用标签从只有单一命名空间,因为我看到它上面的情况,你有多少使用lxml.objectify更好。

在你的情况下,它会像

from lxml import objectify 
root = objectify.parse(url) #also available: fromstring 

您可以访问节点作为

root.html 
body = root.html.body 
for img in body.img: #Assuming all images are within the body tag 

虽然它可能不是在HTML很大的帮助,它可以在良好的结构非常有用XML。

欲了解更多信息,请http://lxml.de/objectify.html

相关问题