2010-11-05 5 views
1

Pour un noeud XML donné, il faut que j'obtienne les paires valeur/clé. Pour un exemple:Impression de l'ensemble de paires valeur/clé à l'intérieur d'un élément XML à l'aide de XSLT

XML:

<root> 
    <detail1> 
     <test1> Text1 </test1> 
     <test2> Text2 </test2> 
     <test3> Text3 </test3> 
    </detail1> 
    <detail2> description 1 </detail2> 
    <detail3> description 2 </detail3> 
</root> 

je besoin d'un tableau comme suit (Ignorer le plus haut sommet élément):

 

detail1 | test1 : Text1 
     | test2 : Text2 
     | test2 : Text3 
     | 
detail2 | description 1 
     | 
detail3 | description 2 

Est-ce possible avec XSLT? Si quelqu'un peut me montrer un exemple ou une ressource, ce serait très utile.

+0

Quel est le format de la table voulez-vous, HTML? – LarsH

+0

oui j'ai besoin d'un tableau HTML. – sanjayav

+0

Bonne question, +1. Voir ma réponse pour une solution complète et courte qui est entièrement dans l'esprit de XSLT (utilise le style push). C'est la seule réponse jusqu'à présent qui produit exactement la sortie désirée. –

Répondre

2

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:variable name="vBlanks" select="'       '"/> 

<xsl:template match="/*/*"> 
    <xsl:value-of select="concat('&#xA;', name(), ' | ')"/> 
    <xsl:apply-templates/> 
</xsl:template> 

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

<xsl:template match="/*/*/*[not(position()=1)]"> 
    <xsl:text>&#xA;</xsl:text> 
    <xsl:value-of select="substring($vBlanks,1,string-length(name(..))+1)"/> 
    <xsl:value-of select="concat('| ', name(), ' : ')"/> 
    <xsl:apply-templates/> 
</xsl:template> 
</xsl:stylesheet> 

lorsqu'il est appliqué sur le document XML fourni:

<root> 
    <detail1> 
     <test1> Text1 </test1> 
     <test2> Text2 </test2> 
     <test3> Text3 </test3> 
    </detail1> 
    <detail2> description 1 </detail2> 
    <detail3> description 2 </detail3> 
</root> 

produit le résultat souhaité, correct:

detail1 | test1 : Text1 
     | test2 : Text2 
     | test3 : Text3 
detail2 | description 1 
detail3 | description 2 
+0

merci beaucoup pour cette solution. – sanjayav

1

J'aime utiliser xsl: apply-templates mieux que d'utiliser xsl: for-each.

Edit: changé clause de correspondance de*[text()]à*[count(text()) = 1]

Si vous appliquez cette transformation

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:template match="/"> 
    <html> 
     <table> 
     <xsl:apply-templates select="root/*"/> 
     </table> 
    </html> 
    </xsl:template> 

    <xsl:template match="*[count(text()) = 1]"> 
    <tr> 
     <td> 
     <xsl:value-of select="name()"/> 
     </td> 
     <td> 
     <xsl:value-of select="."/> 
     </td> 
    </tr> 
    </xsl:template> 

    <xsl:template match="*"> 
    <xsl:apply-templates select="*" mode="keyvalue"/> 
    </xsl:template> 

    <xsl:template match="*" mode="keyvalue"> 
    <tr> 
     <xsl:choose> 
     <xsl:when test="position() = 1"> 
      <td> 
      <xsl:value-of select="name(..)"/> 
      </td> 
      <td> 
      <xsl:call-template name="formatkeyvalue"/> 
      </td> 
     </xsl:when> 
     <xsl:otherwise> 
      <td></td> 
      <td> 
      <xsl:call-template name="formatkeyvalue"/> 
      </td> 
     </xsl:otherwise> 
     </xsl:choose> 
    </tr> 
    </xsl:template> 

    <xsl:template name="formatkeyvalue"> 
    <xsl:value-of select="concat(name(), ' : ', text())"/> 
    </xsl:template> 

</xsl:stylesheet> 

à votre entrée, vous obtenez

<html> 
    <table> 
    <tr> 
     <td>detail1</td> 
     <td>test1 : Text1 </td> 
    </tr> 
    <tr> 
     <td></td> 
     <td>test2 : Text2 </td> 
    </tr> 
    <tr> 
     <td></td> 
     <td>test3 : Text3 </td> 
    </tr> 
    <tr> 
     <td>detail2</td> 
     <td> description 1 </td> 
    </tr> 
    <tr> 
     <td>detail3</td> 
     <td> description 2 </td> 
    </tr> 
    </table> 
</html> 
+0

C'est exactement ce que je voulais. Mais quand j'exécute ceci, la table générée manque des valeurs de test1, de test2, de test3. Je suis très nouveau à xslt. Pouvez-vous me donner un indice sur ce qui pourrait être le problème? Merci d'avance. – sanjayav

+0

@sunnyj: bizarre. J'ai développé la solution avec Xselerator et cela a fonctionné (excellent outil, au fait). Après avoir lu votre commentaire, j'ai re-testé la transformation en studio visuel et il a échoué comme vous l'avez décrit. Intéressant, mais ennuyeux. Je pense que j'ai trouvé ce qui l'a causé et mis à jour ma réponse.Est-ce que ça marche? – cfern

1

Cette feuille de style:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/*"> 
     <table border="1px"> 
      <xsl:apply-templates/> 
     </table> 
    </xsl:template> 
    <xsl:template match="/*/*"> 
     <tr> 
      <td> 
       <xsl:value-of select="name()"/> 
      </td> 
      <td> 
       <xsl:apply-templates/> 
      </td> 
     </tr> 
    </xsl:template> 
    <xsl:template match="/*/*/*"> 
     <xsl:value-of select="concat(name(),' : ')"/> 
     <xsl:apply-templates/> 
     <xsl:if test="following-sibling::*"> 
      <br/> 
     </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

Sortie:

<table border="1px"> 
    <tr> 
     <td>detail1</td> 
     <td>test1 : Text1 
      <br />test2 : Text2 
      <br />test3 : Text3 
     </td> 
    </tr> 
    <tr> 
     <td>detail2</td> 
     <td> description 1 </td> 
    </tr> 
    <tr> 
     <td>detail3</td> 
     <td> description 2 </td> 
    </tr> 
</table> 
+0

je vous remercie beaucoup pour cette solution. – sanjayav

+0

@sunnyj: Vous êtes bienvenu. –

Questions connexes