仅获取此节点的InnerText(不包括子项)

时间:2015-11-17 09:58:28

标签: c# html string html-agility-pack

由于我还不熟悉XPath,我更喜欢LINQ和HtmlAgilityPack。我认为这是我需要XPath解决方案的情况之一。所以我需要你的帮助。

考虑这个简化的HTML代码段:

<td><b>Billing informations:</b>
    <table>
        <tr>
            <td style="color: #757575; padding-left: 10px; padding-bottom: 20px;">
                Invoice-Number:1534753<br />Transactioncode: 1WF772582A4041717
            </td>
        </tr>
    </table>
</td>

这是较大HTML页面的一部分,但它展示了我遇到的问题。我需要提取Invoice-NumberTransactionCode。有时文本是跨度的,有时直接在单元格中,就像这里一样。所以我需要一种适用于这两种情况的方法。

我试过这个:

var invoiceCell = doc.DocumentNode.Descendants("td")
    .FirstOrDefault(cell => cell.InnerText.Contains("Invoice-Number"));
if (invoiceCell != null)
{
    string text = invoiceCell.InnerText;
    // use string methods to extract both values
}

问题是invoiceCell.InnerText会返回最外面的单元格InnerText,而不是包含Invoice-Number的单元格。因此text还包含&#34;结算信息&#34;:

Billing informations:



                Invoice-Number:1534753Transactioncode: 1WF772582A4041818

虽然在这种情况下我可以使用字符串方法或正则表达式来提取两个值,但由于较大的html页面包含许多嵌套表,因此这非常容易出错。我只想要最内层单元格的InnerText。也许还有一个解决这个问题的LINQ解决方案,然后我更喜欢这个。

更新我注意到使用LastOrDefault代替FirstOrDefault可能是一种可行的解决方法,因为它似乎返回与条件匹配的最内层单元格:< / p>

var invoiceCell = doc.DocumentNode.Descendants("td")
    .LastOrDefault(cell => cell.InnerText.Contains("Invoice-Number"));

1 个答案:

答案 0 :(得分:1)

这是另一种使用XPath来覆盖这两种情况的替代方案 - 当目标文本直接位于单元格内部并且当它包含在跨度中时:

var xpath = "//td[contains(text(),'Invoice-Number') or contains(span,'Invoice-Number')]";
var invoiceCell = doc.DocumentNode.SelectSingleNode(xpath);