Question

Je voudrais construire une requête XPath qui renverra un « div » ou élément « de table », tant qu'il a un descendant contenant le texte « abc ». L'une mise en garde est qu'il ne peut pas avoir de div ou descendants de table.

<div>
  <table>
    <form>
      <div>
        <span>
          <p>abcdefg</p>
        </span>
      </div>
      <table>
        <span>
          <p>123456</p>
        </span>
      </table>
    </form>
  </table>
</div>

Ainsi, le seul résultat correct de cette requête serait:

/div/table/form/div 

Mon meilleur ressemble à quelque chose comme tentative ceci:

//div[contains(//text(), "abc") and not(descendant::div or descendant::table)] | //table[contains(//text(), "abc") and not(descendant::div or descendant::table)]

mais ne retourne pas le résultat correct.

Merci pour votre aide.

Était-ce utile?

La solution

Quelque chose de différent ::)

//text()[contains(.,'abc')]/ancestor::*[self::div or self::table][1]

Il semble beaucoup plus court que les autres solutions, non? :)

Traduit en anglais simple :. Pour tout nœud de texte dans le document qui contient la chaîne "abc" sélectionner son premier ancêtre qui est soit un div ou table

Ceci est plus efficace , comme une seule analyse complète de l'arborescence des documents (et non tout autre) est nécessaire, et la traversal ancestor::* est vraiment pas cher par rapport à une analyse descendent:: (arbre).

Pour vérifier que cette solution "fonctionne vraiment":

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
  <xsl:copy-of select=
  "//text()[contains(.,'abc')]/ancestor::*[self::div or self::table][1] "/>
 </xsl:template>
</xsl:stylesheet>

lorsque cette transformation est effectuée sur le document XML fourni :

<div>
  <table>
    <form>
      <div>
        <span>
          <p>abcdefg</p>
        </span>
      </div>
      <table>
        <span>
          <p>123456</p>
        </span>
      </table>
    </form>
  </table>
</div>

le résultat voulu, correct produit :

<div>
   <span>
      <p>abcdefg</p>
   </span>
</div>

Remarque :. Il ne faut pas utiliser XSLT - ANY XPath 1.0 hôte - comme DOM, doit obtenir le même résultat

Autres conseils

//*[self::div|self::table] 
   [descendant::text()[contains(.,"abc")]]  
   [not(descendant::div|descendant::table)]

Le problème est que les fonctions contains(//text(), "abc") cast ensembles de nœuds prenant le premier noeud.

vous pouvez essayer:

//div[
  descendant::text()[contains(., "abc")] 
  and not(descendant::div or descendant::table)
] | 
//table[
  descendant::text()[contains(., "abc")] 
  and not(descendant::div or descendant::table)
]

est-ce que l'aide?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top