web-dev-qa-db-fra.com

utiliser xsl pour sortir du texte brut

J'avais besoin d'utiliser XSL pour générer une sortie simple en texte brut à 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 renvoyant à un meilleur exemple serait bien entendu 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 importantes qui m'ont aidé ici:

  1. l'utilisation de xsl: output pour omettre la déclaration standard au début du document de sortie
  2. l'utilisation de l'attribut xml: space = "preserve" pour conserver les espaces que j'ai écrits dans la balise xsl: for-each. Cela m'a également obligé à écrire tout le code dans la balise for-each, y compris cette balise également, 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:

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

Comme je l'ai dit, toute suggestion sur la façon de le faire de manière plus élégante 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>
29
Chris
  • Vous pouvez définir un modèle à faire correspondre sur 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 compter 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 votre sauts de ligne. De plus, pour moi, cela se lit comme un saut de ligne explicite et est plus facile à 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>
25
Mads Hansen

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érique est mieux applicable si toutes les données à produire sont contenues dans des nœuds de texte - pas dans des attributs.

7