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 :

[xml + xsl] détection d'élément vide


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut [xml + xsl] détection d'élément vide
    Bonjour,
    je génère un fichier texte à partir d'un fichier XML et XSL en utilisant Xalan.
    Dans mon fichier xml, certains champs sont délcarés mais non renseignés. J'aimerai ne pas en tenir compte dans mon fichier xsl, mais je ne sais pas quelle fonction utiliser dans mon text :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <xsl:for-each select="Param">
       <xsl:if test="ElementVide?">
       </xsl:if>
    </xsl:for-each>

  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 : 47
    Localisation : France

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 4 967
    Points : 10 927
    Points
    10 927
    Par défaut Re: [xml + xsl] détection d'élément vide
    essaye
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <xsl:for-each select="Param">
       <xsl:if test="not(.=text() or .=node())">
       </xsl:if>
    </xsl:for-each>
    Si tu n'est pas sur un noeud texte cela devrait marcher

  3. #3
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut
    ça marche pas, mais je crois que j'ai mal expliqué mon problème.
    Voila mon xsl :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    	<!-- Attributes -->
    	<xsl:text>(</xsl:text>
    	<xsl:for-each select="FunctionClass/Property/PNumber/PNParam">
    		<xsl:value-of select="ParamName">		
    		</xsl:value-of>
    		<xsl:if test="position()!=last()">
    			<xsl:text>, </xsl:text>
    		</xsl:if>
     
    	</xsl:for-each>
    	<xsl:text>)</xsl:text>
    	<xsl:value-of select="$NewLine"/>
    En fait, j'aimerai ne pas prendre en compte les ParamName vides...

  4. #4
    Expert éminent
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Points : 7 103
    Points
    7 103
    Par défaut
    Bonjour,

    Vide comment ? Si ca veut dire sans texte, essaie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:for-each select="FunctionClass/Property/PNumber/PNParam[text()]">
    FAQ XML
    ------------
    « Le moyen le plus sûr de cacher aux autres les limites de son savoir est de ne jamais les dépasser »
    Giacomo Leopardi

  5. #5
    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 : 47
    Localisation : France

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 4 967
    Points : 10 927
    Points
    10 927
    Par défaut
    Citation Envoyé par tut

    En fait, j'aimerai ne pas prendre en compte les ParamName vides...
    Oui on s'est mal compris dans ce cas la en effet il faut que tu definisse le "vide"
    si c'est un noeud text comme la
    prend la solution de grandfather
    Si tu veux un noeud qui en contient d'autre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <a>
      <autre>....</autre>
    </a>
    remplace le text() par node()

    si c'est les deux alors text() or node()

  6. #6
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut
    bonjour,
    Merci Grand Father, ça marche
    Cependant, ce n'est pas parfait... Je m'explique, j'ai un fichier xml qui contient la définition de fonctions, à partir duquel je dois générer du code.
    La section sur laquelle je travaille contient les définitions des paramètres.
    Hors certains paramètres ne sont pas encore définis, je ne dois donc pas en tenir compte, et il faut aussi que j'insère des virgules entre chaque élément.
    Le xml ressemble à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    <PNParam>
       <ParamName>ErrorInfo</ParamName>
       <ParamDescription>Description du paramètre</ParamDescription>
    </PNParam>
    <PNParam>
       <ParamName></ParamName>
       <ParamDescription>ne pas tenir compte de ce paramètre</ParamDescription>
    </PNParam>
    <PNParam>
       <ParamName>UnAutre</ParamName>
       <ParamDescription>Description d'un autre paramètre</ParamDescription>
    </PNParam>
    Moi, à partir de ça, il faut que je génère ceci :
    ( ErrorInfo, UnAutre )

    J'ai donc fait le xsl suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    <xsl:text>( </xsl:text>
    <xsl:for-each select="......../PNParam">
       <xsl:value-of select="ParamName[text()]"/>
       <xsl:if test="position()!=last()">
          <xsl:text>, </xsl:text>
       </xsl:if>
    </xsl:for-each>
    <xsl:text> )</xsl:text>
    Le problème est qu'il insère une virgule pour les paramètres non décrits....


    si vous avez des idées...
    Je cherche aussi de la doc sur le XSL, j'ai lu et relu le tuto en PDF de 39 pages, mais il n'aborde que des cas relativement simples. Est-ce que vous connaissez d'autres ressources de doc sur le XSL ?

  7. #7
    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 : 47
    Localisation : France

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 4 967
    Points : 10 927
    Points
    10 927
    Par défaut
    essaye


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    <xsl:text>( </xsl:text> 
    <xsl:for-each select="......../PNParam"> 
       <xsl:value-of select="ParamName"/> 
       <xsl:if test="position()!=last() and .=text()"> 
          <xsl:text>, </xsl:text> 
       </xsl:if> 
    </xsl:for-each> 
    <xsl:text> )</xsl:text>

  8. #8
    Expert éminent
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Points : 7 103
    Points
    7 103
    Par défaut
    Plutôt que de prendre tous les PNParam dans le for-each, puis de tester si le ParamName est vide, il est plus direct de sélectionner dans le for-each les ParamName non vides :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    xsl:text>( </xsl:text> 
    <xsl:for-each select="......../PNParam/ParamName[text()]"> 
       <xsl:value-of select="."/> 
       <xsl:if test="position()!=last()"> 
          <xsl:text>, </xsl:text> 
       </xsl:if> 
    </xsl:for-each> 
    <xsl:text> )</xsl:text>
    XSLT en soi n'est pas très compliqué. En l'occurence, tes difficultés présentes viennent plus de la compréhension de XPath. Et maîtriser XSLT sans maîtriser XPath n'est pas difficile, c'est impossible...
    Pour XPath, je te conseille l'excellent site de Zvon http://www.zvon.org/xxl/XPathTutoria.../examples.html
    FAQ XML
    ------------
    « Le moyen le plus sûr de cacher aux autres les limites de son savoir est de ne jamais les dépasser »
    Giacomo Leopardi

  9. #9
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut
    Merci Grand Father pour le lien, effectivement, il y a plein de trucs que je ne sais pas... Je suis nettement plus à l'aise en C++...

    Si je sélectionne tous les PNParam c'est que je en fais pas que lire la valeur de la balise ParamName. Je me sers aussi de PNParam pour lire les types des attributs :
    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
     
    	<!-- Parameters -->
    	<xsl:text>(</xsl:text>
    	<xsl:for-each select="FunctionClass/Property/PNumber/PNParam">
     
    		<!-- Type -->
    		<xsl:choose>
    			<xsl:when test="PNParamType/TNumber/BasicDataType[name()='TUWord']">
    				<xsl:text>UWord8 </xsl:text>
    			</xsl:when>
    			<xsl:when test="PNParamType/TNumber/BasicDataType[name()='TULong']">
    				<xsl:text>UWord16 </xsl:text>
    			</xsl:when>			
    		</xsl:choose>
     
    		<!-- Name -->
    		<xsl:value-of select="ParamName[text()]"/>
    		<xsl:if test="position()!=last()">
    				<xsl:text>, </xsl:text>
    		</xsl:if>
     
    	</xsl:for-each>
    	<xsl:text>)</xsl:text>
    	<xsl:value-of select="$NewLine"/>
    La solution que tu m'as donné Erwy ne fonctionne pas : quand je la mets je n'ai plus de virgule entre mes attributs.
    Ma balise <xsl:choose> ne fonctionne pas non plus : j'essaye de lire le nom de la balise située en-dessous de (balise fille de ) BasicDataType, et suivant le nom de la balise afficher UWord8 ou UWord16; mais ça ne doit pas être la bonne syntaxe.
    Un peu déconcertant cette syntaxe quand même...

  10. #10
    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 : 47
    Localisation : France

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 4 967
    Points : 10 927
    Points
    10 927
    Par défaut
    mal lu ,fatigue de fin de semaine
    Je m'étais trompe d'element,je faisais le test sur l'element courant au lieu de ParamName

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <xsl:text>( </xsl:text> 
    <xsl:for-each select="......../PNParam"> 
       <xsl:value-of select="ParamName"/> 
       <xsl:if test="position()!=last() and ParamName[text()]"> 
          <xsl:text>, </xsl:text> 
       </xsl:if> 
    </xsl:for-each> 
    <xsl:text> )</xsl:text>

  11. #11
    Expert éminent
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Points : 7 103
    Points
    7 103
    Par défaut
    C'est normal que ca ne fonctionne pas, la fonction XPath name() dans le prédicat renvoie le nom du noeud courant, le noeud courant étant le noeud qui précéde juste le prédicat soit 'BasicDataType. Il faut que tu descendes d'un niveau sur le noeud enfant que ca fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:when test="PNParamType/TNumber/BasicDataType/*[name()='TUWord']">
    Maintenant, pourquoi ne pas désigner explicitement le noeud enfant ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:when test="PNParamType/TNumber/BasicDataType/TUWord">
    Un exemple plus fourni de ton fichier XML nous permettrait d'être plus précis.
    FAQ XML
    ------------
    « Le moyen le plus sûr de cacher aux autres les limites de son savoir est de ne jamais les dépasser »
    Giacomo Leopardi

  12. #12
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut
    J'avance petit à petit...
    J'ai résolu mon problème de virgule. Merci Erwy !
    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
    34
     
    	<!-- Parameters -->
    	<xsl:text>(</xsl:text>
    	<xsl:for-each select="FunctionClass/Property/PNumber/PNParam">
     
    		<!-- parameter separator -->
    		<xsl:if test="position()!=1 and ParamName[text()]">
    				<xsl:text>, </xsl:text>
    		</xsl:if>
     
    		<!-- Type -->
    		<xsl:choose>
    			<xsl:when test="PNParamType/TNumber">
    				<xsl:choose>
    					<xsl:when test="PNParamType/TNumber/BasisDataType/TVoid"><xsl:value-of select="$Void"/></xsl:when>
    					<xsl:when test="PNParamType/TNumber/BasisDataType/TUByte"><xsl:value-of select="$UWord8"/></xsl:when>
    					<xsl:when test="PNParamType/TNumber/BasisDataType/TSByte"><xsl:text>Word8 </xsl:text></xsl:when>
    					<xsl:when test="PNParamType/TNumber/BasisDataType/TUWord"><xsl:text>UWord16 </xsl:text></xsl:when>
    					<xsl:when test="PNParamType/TNumber/BasisDataType/TSWord"><xsl:text>UWord16 </xsl:text></xsl:when>					
    					<xsl:when test="PNParamType/TNumber/BasisDataType/TULong"><xsl:text>UWord32 </xsl:text></xsl:when>					
    					<xsl:when test="PNParamType/TNumber/BasisDataType/TSLong"><xsl:text>SWord32 </xsl:text></xsl:when>										
    				</xsl:choose>			
    			</xsl:when>			
    			<xsl:when test="PNParamType/TVoid">
    				<xsl:value-of select="$Void"/>
    			</xsl:when>		
    		</xsl:choose>		
     
    		<!-- Name -->
    		<xsl:value-of select="ParamName"/>
     
    	</xsl:for-each>
    	<xsl:text>)</xsl:text>
    	<xsl:value-of select="$NewLine"/>
    Tu as raison GrandFather, l'écriture que tu proposes est meilleure, surtout que je connais les valeurs possibles : elles sont spécifiées dans le dtd.
    Par contre je trouve l'écriture de mon xsl:choose plutôt lourde. Est-ce qu'il éxiste un moyen de ne pas répéter le chemin complet "PNParamType/TNumber/" ?

  13. #13
    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 : 47
    Localisation : France

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 4 967
    Points : 10 927
    Points
    10 927
    Par défaut
    tu peux utiliser une variable apres ton premier choose

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:variable name="param" select="PNParamType/TNumber/BasisDataType"/>
    par exemple
    appel:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     <xsl:when test="$param/TVoid"><xsl:value-of select="$Void"/></xsl:when>
    ou faire un apply-template sur PNParamType/TNumber/ et mettre ton choose dans une template

  14. #14
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut
    Merci beaucoup pour vos réponses !
    Vous m'avez enlevé une fière chandelle du pied !

  15. #15
    Expert éminent
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Points : 7 103
    Points
    7 103
    Par défaut
    Encore mieux, faire une table de look-up :
    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
    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:lookup="Espace de nom perso">
     
      <lookup:table>
         <lookup:item cle="TSByte">Word8</lookup:item>
         <lookup:item cle="TUWord">UWord16</lookup:item>
         <lookup:item cle="UWord16">UWord16</lookup:item> 	
         ...
      </lookup:table>
     
      ...
      <xsl:for-each select="PNParamType/TNumber/BasisDataType/*">
        <xsl:variable name="nom" select="name()"/>
        <xsl:value-of select="document('')//lookup:table/lookup:item[@cle=$nom]"/>
      </xsl:for-each>
      ...
     
    </xsl:stylesheet>
    En utilisant la fonction XPath document() sans paramètre, on récupère la racine de la feuille de style XSLT (et non pas celle du fichier XML !) dans laquelle on aura rajouté la table contenant les noms de variable. Ne pas oublier de créer son propre espace de nom dans la balise xsl:stylesheet
    FAQ XML
    ------------
    « Le moyen le plus sûr de cacher aux autres les limites de son savoir est de ne jamais les dépasser »
    Giacomo Leopardi

  16. #16
    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 : 47
    Localisation : France

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 4 967
    Points : 10 927
    Points
    10 927
    Par défaut
    M'ouais enfin ca revient pas un peu a mettre des donnees dans le xslt

    c'est pas un peu detourner son usage

  17. #17
    Expert éminent
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Points : 7 103
    Points
    7 103
    Par défaut
    Pas du tout ! Ce ne sont pas des données d'entrée, ce sont des littéraux utilisés par les templates et destinés à figurer dans l'arbre de sortie. Ils ne bougent pas de la feuille de style, mais plutôt que de les placer dans des templates, on les place dans leur propre structure XML. Plus lisible et plus facile à maintenir : Y'a qu'à comparer la version avec xsl:choose et celle avec table lookup...
    FAQ XML
    ------------
    « Le moyen le plus sûr de cacher aux autres les limites de son savoir est de ne jamais les dépasser »
    Giacomo Leopardi

  18. #18
    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 : 47
    Localisation : France

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 4 967
    Points : 10 927
    Points
    10 927
    Par défaut
    Ok, c'est juste que j'aurais plutot eu tendance a creer un deuxieme xml a cause des cle="TSByte" et autres.Mais c'est vrai que c'est pas les meme performances

  19. #19
    tut
    tut est déconnecté
    Membre averti
    Avatar de tut
    Inscrit en
    Juillet 2002
    Messages
    373
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 373
    Points : 394
    Points
    394
    Par défaut
    De toute façon, je ne peux pas modifier le XML, alors le problème ne se pose pas.

  20. #20
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    284
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 284
    Points : 349
    Points
    349
    Par défaut
    J'adore le coup de la lookup, c'est très rigolo et bien pensé
    Nicolas

Discussions similaires

  1. [XSL] Comment ne pas réstituer un élément vide ?
    Par Mister Ren dans le forum XML/XSL et SOAP
    Réponses: 20
    Dernier message: 17/02/2012, 15h35
  2. RPG XML-INTO et élément vide
    Par jump400 dans le forum AS/400
    Réponses: 2
    Dernier message: 12/01/2009, 15h23
  3. Problème éléments vides dans du XML sous VB6
    Par matteli dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 21/11/2007, 16h01
  4. [XSL 1.0] Output vide pour XML valide !?
    Par pradator dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 22/05/2007, 11h30
  5. [xsl] Ajouter 1 élément à la page xml
    Par ametisse dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 10/03/2003, 12h15

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