我正在尝试在HTML文档中找到一个表,前两行包含3列文本。
我已尝试使用以下查询,我希望返回表格的前2行包含第一列中的文本的节点:
string xpath = @"//table//table[//tr[1]//td[1]//*[contains(text(), *)] and //tr[2]//td[1]//*[contains(text(), *)]]";
HtmlNode temp = doc.DocumentNode.SelectSingleNode(xpath);
它无法正常工作,mon。
以下是一些示例HTML,这是我要匹配的表格:
<table width="100%" cellpadding="0" border="0">
<tbody>
<tr>
<td width="27%" valign="center"><b><font size="1" face="Helvetica">SOME TEXT<br></font></b></td>
<td width="1%"></td>
<td width="9%" valign="center"><font size="1" face="Helvetica">SOME TEXT<br></font></td>
<td width="1%"></td>
<td width="25%" valign="center"><font size="1" face="Helvetica">SOME TEXT<br></font></td>
<td width="37%"></td>
</tr>
<tr>
<td valign="center"><font size="1" face="Helvetica">SOME TEXT<br></font></td>
<td></td>
<td valign="center"><font size="1" face="Helvetica">1<br></font></td>
<td></td>
<td valign="center"><font size="1" face="Helvetica">SOME TEXT<br></font></td>
<td></td>
</tr>
</tbody>
</table>
您注意到列1,3,5在前两行中有文本。这就是我想要匹配的东西。
答案 0 :(得分:1)
//table//table[//tr[1]//td[1]//*[contains(text(), *)] and //tr[2]//td[1]//*[contains(text(), *)]]
此XPath表达式存在许多问题:
//table//table
选择table
后代的任何table
。但是,在提供的XML文档中没有嵌套表。
table[//tr[1]//td[1]//*[contains(text(), *)]
。谓词中的//tr
是绝对 Xpath表达式 - 它选择整个文档中的所有tr
元素 - 不仅在子树中以此table
元素为根。您最有可能想要.//tr
而不是//tr
。
//td[1]
选择任何td
元素作为其父级的第一个td
子元素 - 但最有可能只需要第一个后代td
元素。如果是这样,您需要使用此XPath表达式:(//td)[1]
//*[contains(text(), *)]
这会选择第一个文本节点子节点包含第一个元素子节点的字符串值的任何元素 - 但您只想验证td
是否有后代文本子节点 - 可以使用以下选项正确选择:td[.//text()]
结合所有这些问题的更正,你可能想要的是:
//table
[(.//tr)[1]/td[1][.//text()]
and
(.//tr)[2]/td[1][.//text()]
]
或者,可以编写一个等效但更容易理解且不易出错的表达式,如下所示:
//table
[descendant::tr[1]/td[1][descendant::text()]
and
descendant::tr[1]/td[1][descendant::text()]
]