現在のコンテキストノードから最も近い一致を見つける方法

c# html-agility-pack xpath

質問

私はC#アプリケーションとHtmlAgilityPackを使用して解析しようとしているかなり大きなXMLファイルを持っています。 XMLは次のようになります。

...
<tr>
<td><b>ABC-123</b></td>
<td>15</td>
<td>4</td>
</tr>
<tr>
<td>AB-4-320</td>
<td>11</td>
<td>2</td>
</tr>
<tr>
<td><b>ABC-123</b></td>
<td>15</td>
<td>4</td>
</tr>
<tr>
<td>AB-4-320</td>
<td>11</td>
<td>2</td>
</tr>
<tr>
<td>CONTROLLER1</td>
<td>4</td>
<td>3</td>
</tr>
<td>CONTROLLER2</td>
<td>4</td>
<td>3</td>
</tr>
...

基本的に、一連のテーブル行と列が繰り返されます。私は最初にコントローラを検索しています:

...
<tr>
<td><b>ABC-123</b></td>
<td>15</td>
<td>4</td>
</tr>
<tr>
<td>AB-4-320</td>
<td>11</td>
<td>2</td>
</tr>
<tr>
<td><b>ABC-123</b></td>
<td>15</td>
<td>4</td>
</tr>
<tr>
<td>AB-4-320</td>
<td>11</td>
<td>2</td>
</tr>
<tr>
<td>CONTROLLER1</td>
<td>4</td>
<td>3</td>
</tr>
<td>CONTROLLER2</td>
<td>4</td>
<td>3</td>
</tr>
...

正しいノードを返します。今度は、テキスト「ABC」で始まる最初の(最も近い)一致する<td>ノードを後方に(上に)検索します。

...
<tr>
<td><b>ABC-123</b></td>
<td>15</td>
<td>4</td>
</tr>
<tr>
<td>AB-4-320</td>
<td>11</td>
<td>2</td>
</tr>
<tr>
<td><b>ABC-123</b></td>
<td>15</td>
<td>4</td>
</tr>
<tr>
<td>AB-4-320</td>
<td>11</td>
<td>2</td>
</tr>
<tr>
<td>CONTROLLER1</td>
<td>4</td>
<td>3</td>
</tr>
<td>CONTROLLER2</td>
<td>4</td>
<td>3</td>
</tr>
...

これは、最も近いものだけでなく、すべての一致するノードを返します。このXPath文字列の最後に[1]を追加しようとすると、動作しないように見えました。このような軸関数で使用される述語を示す例は見つかりませんでした。あるいは、おそらく、私は間違っています。助言がありますか?

受け入れられた回答

このXPathを使用することができます:

/parent::tr/preceding-sibling::tr[td[starts-with(.,'ABC-')]][1]/td[starts-with(.,'ABC-')]

それは、子<td>が 'ABC-'で始まる最も近い先行する<tr>を検索します。次に、特定の<td>要素を取得します。

HtmlAgilityPackを使用するときは、少なくとも2つの方法があります。

/parent::tr/preceding-sibling::tr[td[starts-with(.,'ABC-')]][1]/td[starts-with(.,'ABC-')]

人気のある回答

HAPの代わりにLINQ-to-XMLを使用できるのであれば、これはうまくいきます:

var node = xml.Root.Elements("tr")
    .TakeWhile(tr => !tr.Elements("td")
        .Any(td => td.Value.StartsWith("CONTROLLER2")))
    .SelectMany(tr => tr.Elements("td"))
    .Where(td => td.Value.StartsWith("ABC-"))
    .Last();

私はこの結果を得た:

var node = xml.Root.Elements("tr")
    .TakeWhile(tr => !tr.Elements("td")
        .Any(td => td.Value.StartsWith("CONTROLLER2")))
    .SelectMany(tr => tr.Elements("td"))
    .Where(td => td.Value.StartsWith("ABC-"))
    .Last();

(私は最初のノードではなく、サンプル内の2番目に一致するノードをチェックしました)。




ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ