2010-05-06 17 views
2

Comment puis-je sélectionner les nœuds précédents d'un nœud de texte à partir d'un nœud spécifique dont je connais l'identifiant au lieu d'obtenir les nœuds de texte à partir du nœud racine? Lorsque j'appelle la pièce ci-dessous à partir d'une correspondance de modèle de noeud de texte, j'obtiens tous les nœuds de texte précédents à partir de la racine. Je veux modifier la pièce au-dessus du code pour ne sélectionner que les nœuds de texte qui apparaissent après le nœud ayant un identifiant spécifique dire quelque chose comme 123.-à-dire // * [@ id = « 123 »]Comment puis-je sélectionner les nœuds précédents d'un nœud de texte à partir d'un nœud spécifique et non le nœud racine?

  <xsl:template match="text()[. is $text-to-split]"> 
      <xsl:variable name="split-index" as="xsd:integer" 
      select="$index - sum(preceding::text()/string-length(.))"/> 
      <xsl:value-of select="substring(., 1, $split-index - 1)"/> 
      <xsl:copy-of select="$new"/> 
      <xsl:value-of select="substring(., $split-index)"/> 
      </xsl:template> 

     <xsl:variable name="text-to-split" as="text()?" 
     select="descendant::text()[sum((preceding::text(), .)/string-length(.)) ge $index][1]"/> 

Comment j'inclus la condition dans les endroits où j'utilise previous :: text inorder pour sélectionner les noeuds de texte précédents par rapport à l'identifiant du noeud spécifique que je connais?

+0

Bonne question (+1). Voir ma réponse pour trois solutions différentes. :) –

+0

@DimitreNovatchev Avez-vous oublié de réellement +1? ;) – Izkata

+0

+1 de moi parce que la question a donné des idées sur la façon de résoudre mon propre problème ... – Izkata

Répondre

1

Voici quelques variantes que vous pouvez utiliser:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:strip-space elements="*"/> 
<xsl:output method="text"/> 

<xsl:variable name="vStart" select="/*/*[@myId='123']/text()"/> 
<xsl:variable name="vEnd" select="/*/*[last()]"/> 

    <xsl:template match="/"> 
     <xsl:value-of select= 
     "*/*[last()] 
      /sum(preceding::text() 
       intersect 
        $vStart/following::text() 
       ) 
    "/> 
--------------- 
     <xsl:value-of select= 
     "*/*[last()] 
      /sum(preceding::text()[. >> $vStart]) 
    "/> 
--------------- 
     <xsl:value-of select= 
     "sum(/*/*[. >> $vStart and . &lt;&lt; $vEnd]) 
    "/> 
    </xsl:template> 
</xsl:stylesheet> 

Lorsque cette transformation est appliquée sur le document XML suivant:

<nums> 
    <num>01</num> 
    <num>02</num> 
    <num>03</num> 
    <num>04</num> 
    <num myId='123'>05</num> 
    <num>06</num> 
    <num>07</num> 
    <num>08</num> 
    <num>09</num> 
    <num>010</num> 
</nums> 

sont les résultats escomptés :

30 
--------------- 
     30 
--------------- 
     30 
+0

C'est génial. Merci. J'ai utilisé normalize-space() pendant que je trouve la longueur du contenu du texte afin qu'aucun espace supplémentaire entre les balises ne soit compté mais si j'ai des espaces de tabulation dans le xhtml il est compté. Comment je l'ignore. Il est compté même si j'utilise un espace de strip. Tout comme j'ai ajouté un prédicat pour normaliser l'espace, puis-je ajouter un prédicat pour ignorer l'espace de tabulation, alors que je compte la longueur du contenu du texte. Comment ceci peut être fait? – Rachel

+0

@Rachel: Utiliser: 'translate ($ yourText, ' ',' ') –

1

Dans XPath 2.0, vous pouvez utiliser les opérateurs << et >> pour comparer l'ordre des nœuds. Par exemple:

preceding-sibling::text()[. >> $foo] 

sélectionnerait tous les nœuds de texte frères et soeurs précédant celui en cours, qui suivent le nœud $foo dans l'ordre du document. Bien sûr, vous pouvez utiliser une expression au lieu de $foo - dans votre cas, //*[@id='123'] - bien que la liaison à la variable puis l'utilisation de celle-ci dans le filtre soit plus facile à optimiser pour le processeur XSLT.

Voir this pour la spécification détaillée de ces opérateurs.

+0

J'ai utilisé normalize-space() pendant que je trouve la longueur du contenu du texte afin qu'aucun espace supplémentaire entre les balises ne soit compté mais si j'ai des espaces de tabulation dans le xhtml il est compté. Comment je l'ignore. Il est compté même si j'utilise un espace de strip. Tout comme j'ai ajouté un prédicat pour normaliser l'espace, puis-je ajouter un prédicat pour ignorer l'espace de tabulation, alors que je compte la longueur du contenu du texte. Comment ceci peut être fait? – Rachel

+0

Pouvez-vous donner un exemple d'entrée XML qui expose votre problème et mettre en évidence les nœuds d'espaces que vous voulez supprimer? –

+0

Existe-t-il un moyen d'accomplir cela dans XPath 1.0? J'ai posté une question similaire ici: http://stackoverflow.com/q/11037979/107277 –