query XPath con discendente e il testo discendente () predicati
-
29-09-2019 - |
Domanda
Vorrei costruire una query XPath che restituirà un "div" o elemento "tavolo", fintanto che ha un discendente che contiene il testo "abc". L'unico avvertimento è che non può avere alcun discendenti div o tabella.
<div>
<table>
<form>
<div>
<span>
<p>abcdefg</p>
</span>
</div>
<table>
<span>
<p>123456</p>
</span>
</table>
</form>
</table>
</div>
Quindi l'unico risultato corretto di questa query potrebbe essere:
/div/table/form/div
Il mio migliore aspetto tentativo qualcosa di simile:
//div[contains(//text(), "abc") and not(descendant::div or descendant::table)] | //table[contains(//text(), "abc") and not(descendant::div or descendant::table)]
, ma non restituisce il risultato corretto.
Grazie per il vostro aiuto.
Soluzione
Qualcosa di diverso ::)
//text()[contains(.,'abc')]/ancestor::*[self::div or self::table][1]
Sembra molto più breve rispetto alle altre soluzioni, non è vero? :)
Tradotto in inglese semplice :. Per ogni nodo di testo nel documento che contiene la stringa di "abc"
selezionare il suo primo antenato che è o un div
o un table
Questo è più efficiente , in quanto solo una scansione completa dell'albero del documento (e non qualsiasi altro) è necessario, e l'attraversamento ancestor::*
è molto a buon mercato rispetto a un descendent::
(albero) di scansione.
Per verificare che questa soluzione "funziona davvero":
<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>
quando tale trasformazione viene effettuata sul documento XML fornito :
<div>
<table>
<form>
<div>
<span>
<p>abcdefg</p>
</span>
</div>
<table>
<span>
<p>123456</p>
</span>
</table>
</form>
</table>
</div>
The Wanted, risultato corretto è prodotto :
<div>
<span>
<p>abcdefg</p>
</span>
</div>
Nota ??strong>:. Non è necessario utilizzare XSLT - qualsiasi XPath 1.0 ospite - come DOM, deve ottenere lo stesso risultato
Altri suggerimenti
//*[self::div|self::table]
[descendant::text()[contains(.,"abc")]]
[not(descendant::div|descendant::table)]
Il problema è che le funzioni contains(//text(), "abc")
espressi insiemi nodo prendendo il primo nodo.
si potrebbe provare:
//div[
descendant::text()[contains(., "abc")]
and not(descendant::div or descendant::table)
] |
//table[
descendant::text()[contains(., "abc")]
and not(descendant::div or descendant::table)
]
fa questo aiuto?