2010-10-27 4 views
3

Je dispose d'un fichier xml qui ressemble à ceci:xslt texte concaténer des nœuds

<args> 
    <sometag value="abc" /> 
    <anothertag value="def" /> 
    <atag value="blah" /> 
</args> 

garder à l'esprit que les noms d'étiquette dans args pourrait être quelque chose nommé (je ne sais pas à l'avance) maintenant i avoir ce fichier xml stocké dans une variable appelée $ data que j'ai chargée en utilisant un appel document() dans la feuille de style xslt (ce n'est pas la sauvegarde du fichier xslt)

Je veux prendre ces données et produire la sortie suivante : sometag = abc & othertag = def & atag = bl ah

donc (une verison très simplifiée ressemble à ceci:

<xsl:template> 
<xsl:variable name="data" select="document('/path/to/xml')" /> 

    <xsl:call-template name='build_string'> 
    <xsl:with-param name='data' select='$data' /> 

    </xsl:call-template> 

</xsl:template> 

<!-- here is where i need help --> 
<xsl:template name="build_string"> 
    <xsl:param name='data'> 
    <xsl:value-of select='name($data/.)' />=<xsl:value-of select='$data/@value' /> 

    <xsl:if test='$data/following-sibling::node()'> 
    <xsl:text>&#38;</xsl:text> 
    <xsl:call-template name="build_str"> 
    <xsl:with-param name="data" select='$nodes/following-sibling::node()' /> 
    </xsl:call-template> 
    </xsl:if> 


</xsl:template> 

Cette quasi-œuvres, mais elle imprime aussi des nœuds de texte à partir du fichier d'entrée et je ne veux pas correspondre à des nœuds de texte ..

+0

Votre fichier XML est mal formé. Les trois nœuds internes doivent être auto-fermants, par exemple '' – Phil

+0

Selon l'outil xslt du w3, votre code est en désordre. – Lachezar

+0

désolé mon xslt réel est dans un fichier avec des tonnes d'autres choses en cours, je l'ai écrit à la main dans le débordement de la pile de l'éditeur afin que son probaby a des erreurs .. –

Répondre

14

Cette transformation:

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

<xsl:template match="/*/*"> 
    <xsl:value-of select="concat(name(),'=',@value)"/> 

    <xsl:if test="not(position()=last())"> 
    <xsl:text>&amp;</xsl:text> 
    </xsl:if> 
</xsl:template> 
</xsl:stylesheet> 

lorsqu'il est appliqué sur le X fourni ML Document:

<args> 
    <sometag value="abc"/> 
    <anothertag value="def"/> 
    <atag value="blah"/> 
</args> 

produit le résultat souhaité, correct:

sometag=abc&anothertag=def&atag=blah 
+0

Comment ferais-je cela si j'avais des données dans une variable Je voulais faire une chaîne –

+1

@Matt: Ce n'est pas clair - vous devez mettre à jour votre question et montrer exactement ce qui est contenu dans la variable '$ data'. En fonction de cette information inconnue, la réponse peut être différente. @matt: change l'attribut de correspondance de template en 'match =" args/* "', ajoute probablement un 'mode =" build-string "', puis d'un autre template, << –

+0

la variable $ data contient le –

3

J'ai fini par réaliser que je pouvais utiliser une boucle for-each .. je ne sais pas pourquoi je Je n'ai pas utilisé ça pour commencer. Je me demande encore comment je pourrais récurer récursivement une liste de nœuds adjacents comme je le faisais auparavant (qui ne fonctionnait pas correctement car il attrapait aussi des nœuds de texte et faisait d'autres choses bizarres que je ne comprenais pas). Voici ma solution (j'ai également ajouté une variable de séparateur)

<xsl:template name='string_builder'> 
    <xsl:param name='data' /> 
    <xsl:param name='separator' />   
    <xsl:for-each select='$data/*'> 
     <xsl:value-of select='name()'/>=<xsl:value-of select='@value'/> 
     <xsl:if test='position() != last()'> 
      <xsl:value-of select='$separator'/> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:template> 
+1

la raison pour laquelle votre implémentation récursive attrapait des nœuds de texte était parce que vous avez passé le paramètre data comme '$ nodes/following-sibling :: node()' au lieu de '$ data [1]/following-sibling :: *'. Le '*' correspond seulement aux éléments, alors que 'node()' correspond aux nœuds de texte et d'autres aussi. Mieux serait '$ data [position()! = 1]', si $ data ne contient que les éléments enfants de l'élément args. – LarsH

+0

Juste en passant de vieilles questions que j'ai posées et j'ai vu votre commentaire. Je suis désolé @DimitreNovatchev que je n'ai pas accepté votre réponse.La raison en était qu'elle ne correspondait pas à ma structure xslt et nécessitait plus de travail que ce que j'ai montré ci-dessus. Je voulais simplement prendre une variable contenant un ensemble de nœuds (à partir de la fonction document), et le convertir en une chaîne comme indiqué, ce que le vôtre n'a pas fait .. Il a utilisé le document de support du xslt. Votre solution pour l'utiliser avec mon code était plus de travail que ce que je l'ai résolu. –

+0

xsl: apply-templates est correct dans certains cas, mais quand vous voulez faire une logique procédurale, ce qui dans la plupart des langages de programmation signifie appeler une fonction, vous cassez la lisibilité .. Si j'ai utilisé apply-templates partout je dois faire des recherches inverses pour comprendre ce que l'enfer est fait à mon xml .. IMO il fait un énorme clusterf * ck de code. –

Questions connexes