2011-01-05 7 views
1

xpath経由の要素の復元力がありますか?私の前の質問から

how does this xpath behave?

は私が

html//p//table//tr//td/a 

は、上記のXPathの間に表示任意の予期せぬ要素を扱うことができることを見出しました。上記のXPathが扱うことができる。例えば

html/p/div/table/tr/td/a 
html/p/table/tr/td/b/div/a 

はしかし、どのように私は不足している/予想外の要素に完全に弾力がXPathを策定することができますか?

/html/table/tr/td/a (p is missing) 
/html/div/span/table/tr/td/a (p is missing and position replaced with `div/span/`) 

XPath構文は、上記の場合に対処するために存在しています:

は例えば、冒頭で述べたXPathは、次の処理できませんか?もしそうでなければ、代替アプローチは何でしょうか?

xpathだけでは不可能なので、擬似コードを使用して次のアルゴリズムを利用しています。

基本的には、与えられたxpathを分割し、それぞれの祖先の直下の子を探します。予想される子が存在しないか、または他の要素である場合、現在の祖先のすべての子を掘り下げ、期待される子を発見しようとします。

function searchElement(){ 
elements[] = "/html/p/table/tr/td/a".split("/"); 
thisElement = ""; 

for (element in elements) { 
if (firstItem){ 
    thisElement = findElementByXpath(element); 
}else{ 
try{ 
thisElement.findElementByXpath(element); //look for this element inside previous element (from previous iteration); 
}catch(NotFoundException e){ //if element is not found, search all elements inside previous element, and look for it. 

foundElement = false; 
discoveredElement = thisElement.findElementByXpath("*"); 
while(foundElement != true){ 

    if (discoveredElement.findEleemntByXpath(element) != null){ 
    //successful, element found, overwrite. 
    thisElement = thisElement.findElementByXpath("*").findEleemntByXpath(element); 
    foundElement = true; 
    }else{ 
    //not successful, keep digging. 
    discoveredElement = discoveredElement.findElementByXpath("*"); 
    } 

} 
} 
} 
} 

return thisElement; 
} 

これは最適なアプローチですか?私は "*"を探し、各要素を掘ることはむしろ非効率であると心配しています。

「xpath」以外にこの質問にタグを付けるべきかどうかわかりません。編集を自由にしてください。

ありがとうございます。

+0

この質問は非常に不明です。あなたは達成したいと思っていることを明確にしていません。私はあなたが選択したいすべてのノードを指定し、従うルールを説明し、次にこれらのノードを選択するXPath式を尋ねる必要があると思います。この情報を指定できない場合、任意のノードを選択する汎用XPath式は次のようになります。 '// node()' –

答えて

1

にある要素を拾うだろうということを意味

次に、あなたの表現:/html//p//table//tr//td/a

それは次のようになります。

//a[(self::*|parent::td)[1] 
     [(self::*|ancestor::tr)[1] 
      [(self::*|ancestor::table)[1] 
       [(self::*|ancestor::p)[1] 
         [ancestor::html[not(parent::*)]] 
       ] 
      ] 
     ] 
    ] 

しかし、これは同じです:

/html//a | 
/html//td/a | 
/html//tr//a | 
/html//tr//td/a | 
/html//table//a | 
/html//table//td/a | 
/html//table//tr//a | 
/html//table//tr//td/a | 
/html//p//a | 
/html//p//td/a | 
/html//p//tr//a | 
/html//p//tr//td/a | 
/html//p//table//a | 
/html//p//table//td/a | 
/html//p//table//tr//a | 
/html//p//table//tr//td/a | 

/html//aそれがどんなa

を選択することになるように一般的です
+1

yes!これらはオプションの祖先ですが、私はあなたのxpath構文をかなり細かくすることはできません。もっと具体的には、 'self :: *'は何を示していますか? '|'は明らかにORを意味します...これはうまくいくかもしれません。これは、私が探している解決策に近いです。このxpathは私の質問で上記のすべてのxpathを処理する必要がありますか? – heymona

+0

@heymona:自分の編集を確認してください。 –

+1

@Alejandro:あなたの表現は、 '/ html // a'と同じです。 –

1

これは可能ですが、本当に悪い考えです。

//は、「任意の数の要素をスキップする」という意味です。したがって、//tdのパスを使用して、DOMのどこにいても「td」要素を見つけることができます。あなたは私が正しくあなたを理解していれば、あなたが特定のオプションの祖先を命じたとa要素を選択したい/html/body/im/not/what/you/want/td

関連する問題