21

次のテスト ドキュメントに対してテストしています。

<?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 も、任意のドキュメントの解析には明らかに役に立ちません。

明らかに、ここでいくつかの重要な問題が欠けていますが、それが何であるかはわかりません。私の最善の推測は、名前空間と関係があるということですが、定義されている唯一の名前空間はデフォルトであり、名前空間に関して他に何を考慮する必要があるかわかりません。

それで、私は何が欠けていますか?

4

3 に答える 3

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>]
于 2008-11-17T22:45:15.247 に答える
7

XPath は、接頭辞のないすべての名前が「名前空間なし」にあると見なします

特に、仕様は次のように述べています。

「ノード テストの QName は、式コンテキストからの名前空間宣言を使用して、展開された名前に展開されます。これは、xmlns で宣言されたデフォルトの名前空間が使用されません: QName にプレフィックスがない場合、名前空間 URI は null です (これは、属性名が展開されるのと同じ方法です)。

問題とその解決策については、こちらこちらの 2 つの詳細な説明を参照してください。解決策は、接頭辞を (使用されている API に) 関連付け、それを使用して、XPath 式の接頭辞のない名前の前に付けることです。

これが役に立ったことを願っています。

乾杯、

ディミトレ・ノヴァチェフ

于 2008-11-17T23:13:07.153 に答える
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をご覧ください。

于 2011-05-12T13:06:52.507 に答える