如何從當前上下文節點查找最接近的匹配項

c# html-agility-pack xpath

我有一個相當大的XML文件,我試圖使用C#應用程序和HtmlAgilityPack進行解析。 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>
...

基本上是一系列重複的表行和列。我首先使用以下方法搜索控制器:

string xPath = @"//tr/td[starts-with(.,'CONTROLLER2')]";
HtmlNodeCollection nodes = doc.DocumentNode.SelectNodes(xPath);
foreach (HtmlNode link in nodes) { ... }

返回正確的節點。現在我想向後(向上)搜索以文本“ABC”開頭的第一個(最近的)匹配<td>節點:

string xPath = @link.XPath + @"/parent::tr/preceding-sibling::tr/td[starts-with(.,'ABC-')]";

這將返回所有匹配的節點,而不僅僅是最近的節點。當我試圖將[1]添加到此XPath字符串的末尾時,它似乎不起作用,我發現沒有示例顯示謂詞與這樣的軸函數一起使用。或者,更有可能的是,我做錯了。有什麼建議麼?

一般承認的答案

您可以使用此XPath:

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

這將搜索具有子<td>以“ABC-”開頭的最近的<tr> 。然後獲取特定的<td>元素。

使用HtmlAgilityPack時,您可以選擇至少兩種方法:

foreach (HtmlNode link in nodes)
{
    //approach 1 : notice dot(.) at the beginning of the XPath
    string xPath1 = 
        @"./parent::tr/preceding-sibling::tr[td[starts-with(.,'ABC-')]][1]/td[starts-with(.,'ABC-')]";
    var n1 = node.SelectSingleNode(xPath1);
    Console.WriteLine(n1.InnerHtml);

    //approach 2 : appending to XPath of current link
    string xPath2 = 
        @"/parent::tr/preceding-sibling::tr[td[starts-with(.,'ABC-')]][1]/td[starts-with(.,'ABC-')]";
    var n2 = node.SelectSingleNode(link.XPath + xPath2);
    Console.WriteLine(n2.InnerHtml);
}

熱門答案

如果您能夠使用LINQ-to-XML而不是HAP,那麼這可以:

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();

我得到了這個結果:

<td>
  <b>ABC-123</b>
</td>

(我檢查的是樣本中的第二個匹配節點,而不是第一個。)



許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因