Rechercher : dans
Par :

XSLT - boucle et variable

Dernière réponse le 3 mar 2008 à 15:06:39 stephbibie, le 28 fév 2008 à 11:02:46 
 Signaler ce message aux modérateurs

Bonjour,

Je dois transformer un fichier XML en un autre fichier XML à l'aide de XSLT.
Dans mon fichier XML d'origine, j'ai un élément qui peut-être répété plusieur fois à la suite.
Ce que je veux faire c'est garder uniquement la première occurence non nulle. Et si elles sont toutes nulles, gardé une seule occurence (nulle).

exemple 2 :

<package>
      <package_desc></package_desc>
      <package_desc>Pkg Desc1</package_desc>
      <package_desc>Pkg Desc2</package_desc>
</package> 


donne :
<package>
      <package_desc>Pkg Desc1</package_desc>
</package> 


exemple 1 :
<package>
      <package_desc></package_desc>
      <package_desc></package_desc>
</package> 


donne :
<package>
      <package_desc></package_desc>
</package> 


Je pensais faire ça avec une boucle for-each en utilisant une variable, genre "elementTrouvé" pour savoir si une occurrence a déjà été trouvée.
Mais apparemment, j'ai vu que ce n'est pas possible de modifier une variable en XSLT.
Je ne vois donc pas vraiment comment faire.

Quelqu'un aurait-il une solution ?
Configuration: Windows XP
Firefox 2.0.0.12

Meilleures réponses pour « XSLT boucle et variable » dans :
[Bash] La variable d'environnement PATH VoirLa variable d'environnement PATH I. Préambule II. C'est quoi le shell ? III. Définition IV. Séance de dissection V. Ajouter un répertoire à la variable PATH VI. Et puis... I. Préambule Sous les systèmes GNU/Linux qu'on le veuille ou...
[Shell] Tester une variable numérique VoirTester une variable numérique    Préambule Dans un environnement "shell", les variables sont, par défaut, de type "chaîne de caractères". De ce fait il n'est pas possible de déclarer une variable de type "entier" (enfin, ceci n'est pas tout à...
Comment récupérer le résultat d'une commande dans une variable VoirComment récupérer le résultat d'une commande dans une variable Préambule Syntaxe Exemples Préambule Il est bien souvent nécessaire de récupérer le résultat d'une commande (ou de son code retour) dans une variable afin de pouvoir...
Les variables avec Perl VoirConcept de variable avec Perl Une variable est un objet repéré par son nom, pouvant contenir des données, qui pourront être modifiées lors de l'exécution du programme. Les variables en langage Perl peuvent être de trois...
Javascript - Les variables VoirLe concept de variable Une variable est un objet repéré par son nom, pouvant contenir des données, qui pourront être modifiées lors de l'exécution du programme. En Javascript, les noms de variables peuvent être aussi long que l'on désire,...
Variables d'environnement VoirVariables d'environnement Une variable d'environnement est une valeur dynamique, chargée en mémoire, pouvant être utilisée par plusieurs processus fonctionnant simultanément. Sur la plupart des systèmes d'exploitation, les emplacement de...

1

tomlecabron, le 28 fév 2008 à 16:15:29

Le xsl peut être celui-là :

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

<xsl:template match="package">
<xsl:copy>
<xsl:call-template name="get_premier_non_vide">
<xsl:with-param name="index" select="1"/>
</xsl:call-template>
</xsl:copy>
</xsl:template>

<xsl:template name="get_premier_non_vide">
<xsl:param name="index"/>

<xsl:if test="package_desc[$index]">

<xsl:choose>
<xsl:when test="package_desc[$index]/text() != ''">
<xsl:copy-of select="package_desc[$index]"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="get_premier_non_vide">
<xsl:with-param name="index" select="$index + 1"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>

</xsl:template>

</xsl:stylesheet>

Répondre à tomlecabron

2

stephbibie, le 29 fév 2008 à 10:39:52

Merci tomlecabron,

ça répond tout à fait à mon problème.
J'ai toutefois une autre interrogation. Est-il possible de rendre cette fonction plus générique en l'utilisant pour d'autres ensembles de nœuds. J'ai fait plusieurs tentatives en modifiant ton code mais je n'y arrive pas...je débute en XSLT :(

Par exemple :

<package>
      <package_name></package_name>
      <package_name>Name1</package_name>
      <package_desc></package_desc>
      <package_desc>Pkg Desc1</package_desc>
      <package_desc>Pkg Desc2</package_desc>
</package>


donne :
<package>
      <package_name>Name1</package_name>
      <package_desc>Pkg Desc1</package_desc>
</package>


Et enfin une dernière chose. J'ai d'autres traitements à faire comme supprimer certains éléments ou attributs. j'avais donc procédé d'une autre manière pour faire ces traitements. Du coup, ça ne me semble pas compatible avec cette nouvelle fonction. Et je n'arrive pas à conserver ce que j'avais fait avec cette nouvelle fonction. (J'exprime mal mais c'est pas évident à expliquer)

Enfin bref, voilà un exemple de la feuille XSLT que j'avais commencé. En gros cela recopie tout sauf les éléments et attributs précisés. Mais avec l'appel à la fonction maintenant, je n'ai plus aucun élément recopié sous le nœud package (dans ce cas) à part package_desc et les attributs ne sont pas non plus supprimés.


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

<xsl:template match="package/elementX|
				package/elementY|
				service/elementV|
				service/elementW"/>

<xsl:template match="elementX/@language|
				elementY/@language|
				elementV/@language|
				elementW/@language|"/>

Répondre à stephbibie

3

tomlecabron, le 29 fév 2008 à 16:39:34

Bonjour,

Voilà une version générique, qui s'applique à tous les noeuds fils de "package". C'est plus court que l'autre, et beaucoup plus élégant.
Ce site est pas mal pour commencer : www.laltruiste.com
Après il faut compléter avec d'autres ressources.
Ciao

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

<xsl:template match="package">
<xsl:copy>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>

<xsl:template match="*">
<xsl:if test="not(preceding-sibling::*[text() != '' and name() = name(current())]) and text() != ''">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>

</xsl:stylesheet>

Répondre à tomlecabron

4

stephbibie, le 3 mar 2008 à 11:37:14

Merci beaucoup tomlecabron,

effectivement ça correspond davantage à mes besoins.
Par contre j'ai voulu rajouter la condition qui dit que si aucun élément non null n'a été trouvé, il faut copier le dernier élément null, mais une fois de plus je n'y arrive pas (je crois que XSLT n'ait pas fait pour moi). J'ai fait ça :

<xsl:template match="package_desc">
        <xsl:if test="not(preceding-sibling::*[text() != '' and name() = name(current())]) and (text() != ''" or  current()[position()=last()])>
                 <xsl:copy-of select="."/>
        </xsl:if>
</xsl:template> 


et pour l'exemple suivant :
<package id="idPack1">
	.........
	<package_desc language="default"></package_desc>
	<package_desc language="default">Pkg Desc2</package_desc>
	<package_desc language="default"></package_desc>
        ......
</package>    
<package id="idPack2">
	.........
	<package_desc language="default"></package_desc>
	<package_desc language="default"></package_desc>
        ......
</package>  


cela donne :
<package id="idPack1">
	.........
	<package_desc language="default"></package_desc>
	<package_desc language="default">Pkg Desc2</package_desc>
        ......
</package>    
<package id="idPack2">
	.........
	<package_desc language="default"></package_desc>
	<package_desc language="default"></package_desc>
        ......
</package>         



autre chose, je n'arrive toujours pas à intégrer ma suppression d'attribut:
par exemple dans l'exemple précédent,je veux supprimer l'attribut language.
En ajoutant la ligne
<xsl:template match="package_desc/@language" />
à la feuille de style, cela ne fonctionne pas. j'imagine que c'est parce que la précédente règle
 <xsl:template match="package_desc">
surchage cette règle. Mais du coup je ne vois pas comment faire.

Répondre à stephbibie

5

stephbibie, le 3 mar 2008 à 14:29:32

C'est bon pour la suppression des attributs, j'ai réussi à m'en sortir, j'ai fait comme ça et ça semble fonctionner:

<xsl:template match="package_desc">
	<xsl:if test="not(preceding-sibling::*[text() != '' and name() = name(current())]) and text() != ''">
		<xsl:copy >
		<xsl:apply-templates select="attribute::*[name()!='language']|node()"/>
		</xsl:copy>
	</xsl:if>
</xsl:template>


Il ne manque plus qu'à trouver une solution pour mon histoire de dernier élément null et j'en aurais fini avec XSLT...pour cette fois!

Répondre à stephbibie

6

 stephbibie, le 3 mar 2008 à 15:06:39

Bon ça y est,
j'ai finalement trouvé une solution pour mon problème de dernier null. Je sais pas si c'est la meilleure façon de le faire mais en tout cas ça à l'air de fonctionner :

<xsl:if test="not(preceding-sibling::*[text() != '' and name() = name(current())]) 
	              and (text() != '' or not(following-sibling::*[name() = name(current())]))">
		<xsl:copy >
			<xsl:apply-templates select="attribute::*[name()!='language']|node()"/>
		</xsl:copy>
	</xsl:if>



En tout cas, merci encore, je ne pense pas que je m'en serais sorti sans ton aide précieuse!

Répondre à stephbibie