2009-09-10 3 views
19

Quelqu'un peut-il s'il vous plaît suggérer un format d'expression XPath qui retourne une valeur de chaîne contenant les valeurs concaténées de certains nœuds enfants de qualification d'un élément, mais en ignorant les autres:XPath pour revenir concaténation de chaîne de nœud enfant admissible valeurs

<div> 
    This text node should be returned. 
    <em>And the value of this element.</em> 
    And this. 
    <p>But this paragraph element should be ignored.</p> 
</div> 

La valeur renvoyée doit être une seule chaîne:

This text node should be returned. And the value of this element. And this. 

Est-ce possible dans une seule expression XPath?

Merci.

Répondre

16

Dans XPath 1.0:

Vous pouvez utiliser

/div//text()[not(parent::p)] 

pour capturer les nœuds de texte recherchés. La concaténation elle-même ne peut pas être faite dans XPath 1.0, je recommande de le faire dans l'application hôte.

+3

Merci - vous avez absolument raison.Je viens de lire la référence XPath et j'ai découvert que toutes les fonctions de chaîne fonctionnent implicitement sur le premier nœud d'un ensemble de nœuds, il n'y a donc aucun moyen de combiner sélection et concaténation. –

+1

Dans Xpath 2.0, cela se fait facilement - voir ma réponse :) –

+0

Belle et élégante. Bien sur vous! – Aaron

5

Ce regard qui fonctionne:

En utilisant comme contexte /div/:

text() | em/text() 

ou sans l'utilisation du contexte:

/div/text() | /div/em/text() 

Si vous voulez concaténer les deux premières chaînes de caractères, ceci:

concat(/div/text(), /div/em/text()) 
+1

Merci. C'est un bon pas dans la bonne direction. Mais je ne vois pas comment concaténer les résultats. Lorsque je l'enveloppe dans un appel à la fonction chaîne(), il renvoie uniquement la valeur du premier nœud sélectionné. –

+0

Oui, et, comme vous pouvez le voir, ma solution fait la même chose que la solution "correcte" .. ¬¬ Vous pouvez concaténer (...) des nœuds, mais vous ne verrez pas le troisième "texte". Essayez ceci: concat (/ div/text(),/div/em/text()) – eLZahR

6
/div//text() 

forces double barre oblique pour extraire le texte indépendamment des noeuds intermédiaires

+0

Ceci est un peu lié et pratique à savoir. Merci. – Aaron

+0

@Aaron vous êtes les bienvenus – Dewfy

26

Dans XPath 2.0:

string-join(/*/node()[not(self::p)], '')

+10

+1 Traditionnellement, je vous laisse les réponses XPath 2.0. ;-) – Tomalak

+0

Mais la fonction imbriquée n'est pas supportée dans string-join() comme string-join (normalize-space (// un [@ class = "title"] // text())) – SIslam

+0

@SIslam, Ce n'est pas un problème de "fonction imbriquée", mais juste que "normalize-space()" prend un seul argument - pas une séquence. Vous pouvez utiliser cette expression à la place: 'string-join (// a [@ class = 'title']/normalize-space())'. Bien sûr, vous devez ajouter un second argument à l'appel de 'string-join()' –

-2

Vous pouvez utiliser une boucle for-each ainsi et assembler les valeurs dans une variable comme celui-ci

<xsl:variable name="newstring"> 
    <xsl:for-each select="/div//text()"> 
     <xsl:value-of select="."/> 
    </xsl:for-each> 
    </xsl:variable> 
+1

Non pertinent. Affiche posée à propos de XQuery. – Alberto

0

Si vous voulez tous les enfants sauf p, vous pouvez essayer ce qui suit ...

string-join(//*[name() != 'p']/text(), "") 

qui retourne ...

This text node should be returned. 
And the value of this element. 
And this. 
Questions connexes