Выбор узлов с помощью Html Agility Pack

c# html html-agility-pack

Вопрос

У меня есть текущий макет HTML

<table> //table[1]
</table>
<table> //table[2]
<tbody>
   <tr>
      <td>
         <p>
            &nbsp;
         </p>
      </td>
   </tr>
   <tr>
      <td>
         <table> //table[1]//table[1]
            <tbody>
               <tr>
                  <td>
                     <p>
                        INFO 1
                     </p>
                  </td>
                  <td>
                     <p>
                        INFO 2
                     </p>
                  </td>
                  <td>
                     <p>
                        INFO 3
                     </p>
                  </td>
                  <td>
                     <p>
                        INFO 4
                     </p>
                  </td>
               </tr>
            </tbody>
         </table>
      </td>
   </tr>
   <tr>
      <td>
         <table> //table[1]//table[2]
            <tbody>
               <tr>
                  <td>
                     <p><strong>Name</strong></p>
                  </td>
                  <td>
                     <p><strong>Quantity</strong></p>
                  </td>
               </tr>
               <tr>
                  <td>
                     <p>Apples </p>
                  </td>
                  <td>10</td>
               </tr>
            </tbody>
         </table>
      </td>
   </tr>
   <tr>
      <td>
         <table>  //table[1]//table[3]
         </table>
      </td>
   </tr>
</tbody>
</table>

Я пытаюсь получить данные в //table[1]//table[2] , но я продолжаю получать нулевой HtmlNode ( System.NullReferenceException ) для следующего:

не работает: doc.DocumentNode.SelectSingleNode("//table[2]//tbody//tr//td//table[2]//tbody//tr"); ,

Я не уверен, почему это происходит, когда я пытаюсь получить данные для //table[1]//table[1] это прекрасно работает с этим синтаксисом

works: doc.DocumentNode.SelectSingleNode("//table[2]//tbody//tr//td//table[1]//tbody//tr");

Я не понимаю, как работает индексация с Html Agility Pack?

Принятый ответ

//table[2] возвращает второй элемент <table> внутри одного и того же родителя, потому что в XPath:

( [] ) Имеет более высокий приоритет (приоритет), чем ( // и / ). [ Для справки ]

В вашем случае в каждом <td> есть только одна <table> <td> , поэтому выражение Xpath ничего не возвращает. Одним из возможных решений является установка скобок для изменения приоритета:

(//table[2]//tbody//tr//td//table)[2]//tbody//tr

Выше Xpath получает 2-й элемент <table> из всех <table> s, возвращаемых внутренней //table[2]//tbody//tr//td//table XPath //table[2]//tbody//tr//td//table . Затем из этой <table> продолжайте возвращать потомки //tbody//tr элементов.


Популярные ответы

Я закончил тем, что должен был основывать это на том, что tr не уверен, почему мой другой способ не работает, но этот способ действительно работает.

В основном я переместил мою индексацию на следующий уровень выше моей таблицы. Таким образом, в первом tbody каждая таблица после этого находится внутри инструкции tr / td, и я просто построил свой HtmlNode для индексации tr . Возможно, Agility Pack работает лучше, если вы расширяете процесс выбора? ИДК.

В любом случае ...

Для table[2]//table[1] я использовал:

HtmlNode table = doc.DocumentNode.SelectSingleNode("//table[2]//tbody//tr[2]//table");
foreach (var cell in table.SelectNodes(".//tr//td/p"))
...

Я выбрал tr [2], поскольку раньше я имел tr / td с пробелом, если вы заметили пример HTML выше

Для table[2]//table[2] я использовал

HtmlNode table = doc.DocumentNode.SelectSingleNode("//table[2]//tbody//tr[3]//table[1]");
foreach (var cell in table.SelectNodes(".//tr//td"))
...

Для тех, у кого есть проблемы, попробуйте переместить поиск в более широкий выбор, нажав конкретные теги на более широкие.



Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow