IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

XSL/XSLT/XPATH XML Discussion :

[XSLT 2.0] Trier selon un ordre spécifique (non alphabétique, non numérique)


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Octobre 2010
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 3
    Par défaut [XSLT 2.0] Trier selon un ordre spécifique (non alphabétique, non numérique)
    Bonjour,

    J'ai écrit une feuille de style XSLT 2.0 pour trier un fichier XML d'annonces dont la structure est la suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <annonces>
      <annonce>
        <id>1</id>
        <ville>Paris</ville>
        <prix>200</prix>
      </annonce>
      <annonce>
        <id>2</id>
        <ville>Nantes</ville>
        <prix>150</prix>
      </annonce>
      <annonce>
        <id>3</id>
        <ville>Paris</ville>
        <prix>120</prix>
      </annonce>
    </annonces>
    En utilisant dans un template une suite de balises <xsl:sort>, j'arrive à trier ces annonces par ville puis par prix.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      <xsl:sort data-type="text" select="ville" order="ascending"/>
      <xsl:sort data-type="number" select="prix" order="descending"/>
    Voici la feuille de style complète, pour ceux que ça intéresse. Au passage, j'ai défini une variable "grouper" qui permet de commuter entre un tri par ville et un tri global selon sa valeur (c'est une astuce pour désactiver facilement le premier <xsl:sort>).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="">
      <xsl:output method="xml" encoding="utf-8" omit-xml-declaration="yes" indent="no"/>
      <xsl:strip-space elements="*"/>
      <xsl:variable name="grouper" select="'par-ville'"/>
      <xsl:template match="/annonces">
        <xsl:apply-templates select="annonce">
          <xsl:sort data-type="text" select="ville[$grouper = 'par-ville']" order="ascending"/>
          <xsl:sort data-type="number" select="prix" order="descending"/>
        </xsl:apply-templates>
      </xsl:template>
      <xsl:template match="*|@*|text()">
        <xsl:copy>
          <xsl:apply-templates select="*|@*|text()"/>
        </xsl:copy>
      </xsl:template>
    </xsl:stylesheet>
    Problématique actuelle : je voudrais pouvoir trier ce fichier suivant un ordre spécifique pour les villes, et non plus seulement par ordre alphabétique croissant ou décroissant. Par exemple, j'aimerais pouvoir dire "fais un tri par ville dans l'ordre Paris / Caen / Lyon / Amiens, et pour chaque ville, fais un tri par prix".

    Voici une tentative (non fonctionnelle) d'utiliser un <xsl:for-each> pour parcourir les valeurs présentes dans une nouvelle variable "villes".

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="">
      <xsl:output method="xml" encoding="utf-8" omit-xml-declaration="yes" indent="no"/>
      <xsl:strip-space elements="*"/>
      <xsl:variable name="grouper" select="'par-ville'"/>
      <xsl:variable name="villes" select="'Paris','Caen','Lyon','Amiens'"/>
     
      <xsl:template name="trier-une-ville">
        <xsl:param name="ville" />
        <xsl:apply-templates select="annonce">
          <xsl:sort data-type="text" select="ville[$grouper = 'par-ville'][. = $ville]" order="ascending"/>
          <xsl:sort data-type="number" select="prix" order="descending"/>
        </xsl:apply-templates>
      </xsl:template>
     
      <xsl:template match="/annonces">
        <xsl:if test="$grouper = 'par-ville'">
          <xsl:for-each select="$villes">
            <xsl:call-template name="trier-une-ville">
              <xsl:with-param name="ville" select="."/>
            </xsl:call-template>
          </xsl:for-each>
        </xsl:if>
        <xsl:if test="$grouper = 'liste-globale'">
          <xsl:call-template name="trier-une-ville"/>
        </xsl:if>
      </xsl:template>
     
      <xsl:template match="*|@*|text()">
        <xsl:copy>
          <xsl:apply-templates select="*|@*|text()"/>
        </xsl:copy>
      </xsl:template>
    </xsl:stylesheet>
    Questions :
    1. Est-il possible d'utiliser un <xsl:for-each> pour parcourir ma variable "villes"?
    2. Dans la négative, comment peut-on trier suivant un ordre spécifique?


    Merci de vos lumières!

    Grégoire

  2. #2
    Rédacteur

    Avatar de Erwy
    Homme Profil pro
    Développeur Web
    Inscrit en
    Novembre 2003
    Messages
    4 967
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2003
    Messages : 4 967
    Par défaut
    Il te faudra encore modifier ton code mais voici un debut.

    On peut coder du XML dans une variable en xslt 2.0

    d'ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    	<xsl:variable name="villes">
    		<a>
    			<ville>Paris</ville>
    			<ville>Caen</ville>
    			<ville>Lyon</ville>
    			<ville>Amiens</ville>
    		</a>
    	</xsl:variable>
    Pour parcourir cette variable :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    			<xsl:for-each select="$villes/*">
    				<xsl:call-template name="trier-une-ville">
    					<xsl:with-param name="ville" select="."/>
    				</xsl:call-template>
    			</xsl:for-each>

  3. #3
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Octobre 2010
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2010
    Messages : 3
    Par défaut EXSLT node-set
    Merci pour cette réponse.

    Il semblerait que l'on puisse aussi utiliser l'extension à XSLT*1.0 nommée EXSLT, qui apporte une fonction "node-set" permettant de parcourir un bloc de XML présent dans la feuille. Quelque chose comme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    <xsl:stylesheet version="1.0"
                          xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                          xmlns:my="whatever"
                          xmlns:exsl="http://exslt.org/common"
                          extension-element-prefixes="exsl"
                          exclude-result-prefixes="my exsl">
      <xsl:output method="xml" encoding="utf-8" omit-xml-declaration="yes" indent="yes"/>
      <xsl:strip-space elements="*"/>
      <xsl:variable name="grouper" select="'par-commune'"/>
      <my:villes>
              <ville>Paris</ville>
              <ville>Caen</ville>
              <ville>Lyon</ville>
      </my:villes>
    Puis dans le template:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <xsl:for-each select="exsl:node-set(//*)/ville">
      <xsl:call-template name="trier-une-ville">
        <xsl:with-param name="ville" select="."/>
      </xsl:call-template>
    </xsl:for-each>
    Bon, ceci dit, je n'ai réussi à faire fonctionner dans Chome et Firefox aucune des deux solutions (bloc de XML préfixé avec EXSLT, ou <xsl:variable> contenant du XML en XSLT 2.0) et j'ai fini par faire le tri en JavaScript (c'est moins beau techniquement mais ça a eu le mérite de marcher en 1 heure).

    Grégoire

  4. #4
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 579
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 579
    Par défaut
    exsl:node-set() n'est pas censé marcher comme ça.

    Il est censé faire ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <xsl:variable name="villes">
      <ville>Paris</ville>
      <ville>Caen</ville>
      <ville>Lyon</ville>
      <ville>Amiens</ville>
    </xsl:variable>
    Puis dans le template :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <xsl:for-each select="exsl:node-set($villes)/ville">
      <xsl:call-template name="trier-une-ville">
        <xsl:with-param name="ville" select="."/>
      </xsl:call-template>
    </xsl:for-each>
    Bref, exactement ce que permet XSLT2, sans s'embêter à appeler exsl:node-set()
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 8
    Dernier message: 12/12/2010, 17h42
  2. [AC-2007] Trier un état selon l'ordre obtenu dans sa requête source
    Par Nephyline dans le forum IHM
    Réponses: 9
    Dernier message: 22/10/2009, 09h24
  3. Réponses: 6
    Dernier message: 17/01/2006, 09h12
  4. [debutant][JTable] Trier selon une colonne
    Par yupa dans le forum Composants
    Réponses: 3
    Dernier message: 08/08/2005, 11h05
  5. Réponses: 4
    Dernier message: 25/11/2004, 11h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo