2012-03-19 30 views
0

Python用のlxmlチュートリアルでxpathを実行した後、私にバグのような2つの動作を理解することは難しいと思っています。第1に、xpath式が1つの要素だけを明確に選択していてもlxmlがリストを返すように見えます.2つ目の.xpathは、直接的なxpath検索式で選択された要素自体ではなく要素の親を返します。.xpathのlxmlバグ?

XPathについての私の理解は間違っているのですか、またはlxmlには本当にバグがありますか?

私が話している行動を複製するスクリプト:

from lxml.html.soupparser import fromstring 
doc = fromstring(""" 
    <html> 
     <head></head> 
     <body> 
      <p>Paragraph 1</p> 
      <p>Paragraph 2</p> 
     </body> 
    </html> 
""") 

print doc.xpath("//html") 
#[<Element html at 1f385e0>] 
#(This makes sense - return a list of all possible matches for html) 

print doc.xpath("//html[1]") 
#[<Element html at 1f385e0>] 
#(This doesn't make sense - why do I get a list when there 
#can clearly only be 1 element returned?) 

print doc.xpath("body") 
#[<Element body at 1d003e8>] 
#(This doesn't make sense - according to 
#http://www.w3schools.com/xpath/xpath_syntax.asp if I use a tag name 
#without any leading/I should get the *child* nodes of the named 
#node, which in this case would mean I get a list of 
#p tags [<Element p at ...>, <Element p at ...>] 

答えて

0

すべてのpタグがnodenameは、すべての子ノードを選択表現のガイドを1としてdoc.findall(".//p")

、あるべきという名前のノード。 したがって、nodename(末尾の/なし)のみを使用するには、名前付きノードを選択する必要があります(親ノードを名前付きノードとして選択し、ドットを使用する)。

+0

私の問題は、lxmlを使ってすべてのpタグを選択する方法を理解できないということではありません。私の問題は、lxmlがXPathチュートリアルに基づいて期待していたものとは異なる動作をしているので、なぜlxmlにバグがないのかを知ることです。 – Trindaz

3

docのコンテキストノードが'html'ノードであるからです。 doc.xpath('body')を使用する場合は、子要素'body''html'に選択します。これは準拠XPath 1.0 standard

+0

'doc.xpath()は常にリストを返しますすべきだ。これは '.xpath()'を使うコードを単純化します。通常は、同じプロトコル(この場合は一連の要素)に確認するオブジェクトを常に返すことをお勧めします。 – jfs

0

事実、doc.xpath("//html[1]")は、あなたの例とは異なる入力文書を持つ複数のノードを返すことができます。そのパスは// htmlと一致する最初の兄弟を選択します。一致する非兄弟要素がある場合、それぞれの兄弟要素の最初の兄弟を選択します。
XPath:(//html)[1]は、異なる評価順序を強制します。ドキュメント内のすべての一致する要素を選択し、最初の要素を選択します。

しかし、いずれの場合でも、常にリストを返す方が優れたAPI設計です。そうでなければ、コードは常にリストを処理する前に単一値またはなし値をテストする必要があります。

関連する問題