【发布时间】:2016-02-18 15:31:57
【问题描述】:
由于我对 XPath 还不是很熟悉,所以我更喜欢带有HtmlAgilityPack 的 LINQ。我认为这是我需要 XPath 解决方案的情况之一。所以我需要你的帮助。
考虑一下这个简化的 HTML sn-p:
<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-Number 和TransactionCode。有时文本在一个跨度中,有时直接在单元格中,就像这里一样。所以我需要一种在这两种情况下都有效的方法。
我试过了:
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 还包含“账单信息”:
Billing informations:
Invoice-Number:1534753Transactioncode: 1WF772582A4041818
虽然在这种情况下我可以使用字符串方法或正则表达式来提取这两个值,但这很容易出错,因为较大的 html 页面包含许多嵌套表。我只想要最里面的单元格的InnerText。也许还有一个 LINQ 解决方案来解决这个问题,那我更喜欢那个。
更新我注意到使用 LastOrDefault 而不是 FirstOrDefault 可能是一个可行的解决方法,因为这似乎返回了与条件匹配的最里面的单元格:
var invoiceCell = doc.DocumentNode.Descendants("td")
.LastOrDefault(cell => cell.InnerText.Contains("Invoice-Number"));
【问题讨论】:
-
您可以使用
.StartsWith而不是.Contains吗? -
@LocEngineer: 也许有
InnerText.TrimStart().StartsWith因为没有Trim它不起作用。但即便如此,我也无法控制该文件。不知道它是否会在未来工作,所以我想使用Contains作为细胞过滤器。然而,有趣的想法。 -
是的,如果它总是在 td 中,LastOrDefault 可能就是这样。
标签: c# html string html-agility-pack