requête XPath avec descendant et texte descendant () prédicats
-
29-09-2019 - |
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.
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?