2017-07-13 22 views
0

ポップクイズ!私は複数の行と一意の識別子のないテーブルを持っています。一意の行を識別する唯一の方法は、2つ以上の値を一致させることです(1 following-siblingと1 preceding-siblingは機能しません)。以下は、私がTest 2を必要と私は私と一緒に以下のデータを持っているサンプルxpathの複数の兄弟または先行兄弟

<tr> 
    <td>Map</td> 
    <td>First</td> 
    <td>Second</td> 
    <td>Third</td> 
    <td>A01</td> 
    <td><a href='test0'>Test 0</a></td> 
</tr> 
<tr> 
    <td>Map</td> 
    <td>First</td> 
    <td>Tenth</td> 
    <td>Third</td> 
    <td>A03</td> 
    <td><a href='test1'>Test 1</a></td> 
</tr> 
<tr> 
    <td>Map</td> 
    <td>Second</td> 
    <td>Fifth</td> 
    <td>Forth</td> 
    <td>A02</td> 
    <td><a href='test2'>Test 2</a></td> 
</tr> 

です。 A02

ある Forth

td[5]あるFifth

td[4]あるSecond

td[3]

あるMap

td[2]ある

これは私が試したのXPathです:

//td/a[contains(., 'Test 2')][preceding-sibling::td[1][contains(., 'Map')] and td[2][contains(., 'Second')] and td[3][contains(., 'Fifth')] and td[4][contains(., 'Forth')] and td[5][contains(., 'A02')]] 

を、私はこのための解決策を見つけることに怒っています!助けが大いにありがとう!

+0

あなたは何を試してみましたか – Andersson

+2

彼は怒っていると言いました。 – kjhughes

+1

現在の問題を解決する奇妙なアプローチ – Andersson

答えて

1

いくつかの子要素を含む要素を取得する:いくつかのことで要素を取得するために

tag[./child[condition]] 

[@id='someId']または[contains(text(),'some text')]:のような条件を満たしているいくつかの属性を持つ子供を持つ要素を取得するために

tag[./child] 

を条件:

tag[condition1][condition2] 

これを1ロケータに集めます。

//tr[./td[text()='Map']] 

そう繰り返すパターンは次のとおりです:のは言わせ、

//tr[./td[text()='Map']][./td[text()='Second']][./td[text()='Fifth']] 

あなたが簡単に作成できます。[./td[text()='text']]

はのは、いくつかの他の必要な子を追加しましょうだから、テキストと子が含まれている要素を取得しますこのためのjavaメソッドは、内部テキストをparamsとして取得し、完全なパスを構築します:

public static String getPath(String... innerText) { 
     StringBuilder path = new StringBuilder("//tr"); //before tr - table could be specified 
     Arrays.stream(innerText).forEach(
       text -> path.append("[./td[text()='").append(text).append("']]") 
     ); 
     return path.toString(); 
    } 

ここで、必要な内部テキストを含むtrを取得します。今度はaタグを検索することができます。 //a/text()

だから結果は次のとおりです:あなたはテキストが必要な場合//a をまたは:ちょうどロケータの末尾に追加

//tr[./td[text()='Map']][./td[text()='Second']][./td[text()='Fifth']]//a 
+0

私のパターはこれより長くなっています: '' tr [td = 'text1'] ... [td = 'textN'] 'ダニエル・ヘイリーによって提供されていますので、短絡した方が良いでしょう) –

+0

私は説明が大好きです。私の時間を保存してくれてありがとう。チャームのように働いた! – user3287400

1

あなたはtrに述語を置けば、それが簡単かもしれません...

//tr[td[1]='Map' and td[2]='Second' and td[3]='Fifth' and td[4]='Forth' and td[5]='A02']/td[6]/a 

または

//tr[td[1]='Map'][td[2]='Second'][td[3]='Fifth'][td[4]='Forth'][td[5]='A02']/td[6]/a 

コンテキストはaaですので、あなたのオリジナルの試みがうまくいかなかった理由はまったく先行兄弟を持っていないです。先行の兄弟を使用するときは、

//a[../preceding-sibling::td[5]='Map' and ../preceding-sibling::td[4]='Second' and ../preceding-sibling::td[3]='Fifth' and ../preceding-sibling::td[2]='Forth' and ../preceding-sibling::td[1]='A02'] 

も位置が後方にあることに注意してください... ../preceding-sibling::tdを行う必要があります。

+0

この回答は鉱山に似ていますが、//tr[td='text1']...[td='textN ']は私が使用したより短いパターンです=)well done –

+0

@ VitaliyMoskalyuk-ありがとう。複数の述部バージョンは、単一の述部で "and"を使用するよりも短くなります。私はそのバージョンも追加しました。また、私はそれらが重要であると仮定したので、元の質問に含まれていたので、位置述語だけを含めました。 –

関連する問題