utilisez xsl pour afficher du texte brut

J'avais besoin D'utiliser XSL pour générer une sortie de texte simple à partir de XML. Comme je n'ai trouvé aucun bon exemple concis en ligne, j'ai décidé de poster ma solution ici. Tout lien se référant à un meilleur exemple serait bien sûr apprécié:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" >
    <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
    <xsl:template match="/">
        <xsl:for-each select="script/command" xml:space="preserve">at -f <xsl:value-of select="username"/> <xsl:value-of select="startTime/@hours"/>:<xsl:value-of select="startTime/@minutes"/> <xsl:value-of select="startDate"/><xsl:text>
</xsl:text></xsl:for-each> 
    </xsl:template>
</xsl:stylesheet>

Quelques choses qui m'ont aidé ici:

  1. l'utilisation de xsl:output omettre la déclaration au début du document de sortie
  2. l'utilisation de l'attribut xml:space="preserve" pour espace j'ai écrit dans le XSL: pour-chaque balise. Cela m'a également obligé à écrire tout le code dans la balise for-each, y compris cette balise, sur une seule ligne (à l'exception du saut de ligne).
  3. l'utilisation de pour insérer un saut de ligne-encore une fois, j'ai dû omettre l'indentation xml standard ici.

La sortie résultante et souhaitée pour ce xslt était:

At-f alluser 23: 58 17.4.2010
au -f ggroup67 7:58 28.4.2010
au -f ggroup70 15:58 18.4.2010
au -f alluser 23:58 18.4.2010
au -f ggroup61 7:58 22.9.2010
au -f ggroup60 23:58 21.9.2010
au -f alluser 3:58 22.9.2010

Comme je l'ai dit, toute suggestion sur la façon de le faire plus élégamment serait appréciée.


SUIVI 2011-05-08:

Voici le type de xml que je traite:

<script xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="script.xsd">
    <command>
        <username>alluser</username>
        <startTime minutes="58" hours="23"/>
        <startDate>17.4.2010</startDate>
    </command>
</script>
26
demandé sur Chris 2011-05-06 12:17:51

2 réponses

  • Vous pouvez définir un modèle pour correspondre à script/command et éliminer le xsl:for-each
  • concat() peut être utilisé pour raccourcir l'expression et vous éviter d'insérer explicitement autant d'éléments <xsl:text> et <xsl:value-of>.
  • l'utilisation d'une référence d'entité &#xA; pour le retour chariot, plutôt que de s'appuyer sur la préservation du saut de ligne entre votre élément <xsl:text> est un peu plus sûre, car le formatage du code ne gâchera pas vos sauts de ligne. En outre, pour moi, il se lit comme un saut de ligne explicite et est plus facile pour comprendre l'intention.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:fo="http://www.w3.org/1999/XSL/Format" >
    <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>

    <xsl:template match="script/command">
        <xsl:value-of select="concat('at -f '
                    ,username
                    ,' '
                    ,startTime/@hours
                    ,':'
                    ,startTime/@minutes
                    ,' '
                    ,startDate
                    ,'&#xA;')"/>
    </xsl:template>

</xsl:stylesheet>
22
répondu Mads Hansen 2011-05-06 11:26:38

Juste pour le plaisir: cela peut être fait de manière très générale et compacte :

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

    <xsl:template match="*">
        <xsl:apply-templates select="node()|@*"/>
        <xsl:text> </xsl:text>
    </xsl:template>

    <xsl:template match="username">
       at -f <xsl:apply-templates select="*|@*"/>
    </xsl:template>
</xsl:stylesheet>

Lorsqu'il est appliqué sur ce document XML:

<script>
 <command>
  <username>John</username>
  <startTime hours="09:" minutes="33"/>
  <startDate>05/05/2011</startDate>

  <username>Kate</username>
  <startTime hours="09:" minutes="33"/>
  <startDate>05/05/2011</startDate>

  <username>Peter</username>
  <startTime hours="09:" minutes="33"/>
  <startDate>05/05/2011</startDate>
 </command>
</script>

Le résultat voulu et correct est produit:

   at -f 09:33 05/05/2011 
   at -f 09:33 05/05/2011 
   at -f 09:33 05/05/2011  

Note : cette approche générale est mieux applicable si toutes les données à produire sont contenues dans des nœuds de texte - pas dans des attributs.

7
répondu Dimitre Novatchev 2011-05-06 14:35:56