Requête XPath 'HTML Agility Pack' avec AND logique

c# html-agility-pack xpath

Question

J'essaie de trouver une table dans un document HTML avec les 2 premières lignes contenant 3 colonnes avec du texte.

J'ai expérimenté en essayant d'utiliser la requête suivante, que je veux renvoyer le noeud qui a les 2 premières lignes du tableau contient du texte dans la première colonne

string xpath = @"//table//table[//tr[1]//td[1]//*[contains(text(), *)] and //tr[2]//td[1]//*[contains(text(), *)]]";
HtmlNode temp = doc.DocumentNode.SelectSingleNode(xpath);

Ça ne marche pas bien, mec.

Voici un exemple de code HTML, qui correspond au tableau que je tente d’apparier:

    <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>

Vous remarquez que les colonnes 1,3,5 ont du texte dans les 2 premières lignes. C'est ce que j'essaye d'égaler.

Réponse acceptée

//table//table[//tr[1]//td[1]//*[contains(text(), *)] and //tr[2]//td[1]//*[contains(text(), *)]]

Il y a beaucoup de problèmes avec cette expression XPath :

  1. //table//table sélectionne toute table qui est un descendant d'une table . Cependant, dans le document XML fourni, il n'y a pas de tables imbriquées.

  2. table[//tr[1]//td[1]//*[contains(text(), *)] . Le //tr à l'intérieur du prédicat est une expression Xpath absolue - il sélectionne tous les éléments tr dans l' ensemble du document - et pas seulement dans le sous-arbre à la racine de cet élément de table . Très probablement, vous voulez .//tr au lieu de //tr .

  3. //td[1] sélectionne tout élément td qui est le premier enfant td de son parent - mais vous ne souhaiterez probablement que le premier élément td descendant. Si c'est le cas, vous devez utiliser cette expression XPath: (//td)[1]

  4. //*[contains(text(), *)] sélectionne tout élément dont le premier enfant de noeud de texte contient la valeur de chaîne du premier enfant d'élément - mais vous voulez simplement vérifier qu'un td a un noeud d'enfant de texte descendant - ceci peut être correctement sélectionné avec: td[.//text()]

En combinant les corrections de toutes ces questions, vous voulez probablement quelque chose comme :

  //table
     [(.//tr)[1]/td[1][.//text()]
    and
      (.//tr)[2]/td[1][.//text()]
     ]

Alternativement, on pourrait écrire une expression équivalente mais plus compréhensible et moins sujette aux erreurs, comme ceci:

//table
  [descendant::tr[1]/td[1][descendant::text()]
 and
   descendant::tr[1]/td[1][descendant::text()]
  ]



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi