Я пытаюсь найти таблицу в документе 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 имеют текст в первых двух строках. Это то, что я пытаюсь сопоставить.
//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()]
]