[XSLT] Grouper les elements identique
la première de mes etapes étant le nettoyage du fichier xml, la second sera le tri par categories. \o/ ca à l'air super marrant à faire en xslt. j'ai tout fait en dotnet en une heure pour vérifier que c'etait faisable mais il me faut maintenant le reussir en xslt.
J'ai donc des produits comme ceci
Code:
1 2 3 4 5 6
|
<products>
<product><name>balai</name><class>menager</class></product>
<product><name>aspi</name><class>menager</class></product>
<product><name>balayette</name><class>menager petit</class></product>
</products> |
et j'aimerais créer des classes en rangeant les produits dedans pour obtenir ceci
Code:
1 2 3 4 5 6 7 8 9 10 11
|
<products>
<class cls="menager">
<product><name>balai</name><product>
<product><name>aspi</name><product>
</class>
<class cls="menager petit">
<product><name>balayette</name><product>
</class>
</products> |
j'ai donc pensé à ceci.
-1- je tri les produits par class par ordre alphabétique.
-2- je boucle sur les produits en faisant ceci
soit $tmp une variable qui stocke la classe courante et que j'initialise à '' au debut
Code:
1 2 3 4 5 6 7 8
| for each product
if( $tmp=class)
jajoute le produit
else
je met la valeur de la nouvelle class dans $tmp
je cree la balise class
j'ajoute le produit
fin du foreach |
ce qui avec mon niveau (on rigole pas) donne ceci
Code:
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
|
<xsl:template match="products" >
<xsl:copy>
<xsl:call-template name="tprod" >
<xsl:with-param name="tmp" select="''" />
</xsl:call-template>
</xsl:copy>
</xsl:template>
<xsl:template name="tprod">
<xsl:param name="tmp" />
<xsl:for-each select="product">
<xsl:choose>
<xsl:when test="$tmp=class"><!-- ce test est-il bon?class est un noeud enfant de product -->
<!-- add the product -->
</xsl:when>
<xsl:otherwise>
<!-- set $tmp with the new class -->
<xsl:variable name="tmp">
<xsl:value-of select="class" />
</xsl:variable>
<!-- create prod node -->
<prod>
<xsl:value-of select="$tmp" />
<!-- add the product -->
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template> |
bien entendu, ca ne marche pas :roll:
1- je ne sais pas comment attribuer une variable globale puis changer sa valeur en cours. p-e que je m'y prend mal et que je devrais appeler un template avec un param mais meme avec ca, j'ai des problemes
2- combien meme ca marcherait l'attribution de la variable, je ne sais pas quand fermer la balise class. je peux bidouiller, en mettant un </class> apres le foreach, et avec un if($tmp!='') <class> dans le else (otherwise) mais est-ce propre?
edit apres recherche
parce qu'on ne peut pas redefinir une variable, je crois que mon salut est dans l'appel de template recursif et pourtant mes essais son infructueux. soit ca me dis des erreurs comme quoi je fais nimporte quoi, soit ca me sort rien.
j'ai peur de partir dans n'importe quoi. je suis trop habitué à coder objet et j'ai l'impression de n'avoir pas l'abstraction necessaire pour utiliser proprement xslt. P-e pourriez-vous au moins me donner l'algo general de la chose
indice:
quand j'arriverai a obtenir les produits dans chaque class, j'aurais une derniere etape: ajouter a chaque class deux attributs:
taillemax: qui represente la taille des produits: (petit, moyen,grand) si ca possede pleins de petits colis et un grand, alors taillemax = grand
poids: qui represente le poids total des colis, on va dire que quand c'est un produit petit, j'ajoute 1kg au total, 2kg pour le moyen 3kg pour le grand
pour jespere que c'est possible, obtenir
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
<products>
<class cls="menager" taillemax="grand" poids="6">
<product><name>balai</name><size>petit</size><product>
<product><name>aspi</name><size>grand</size><product>
<product><name>aspi2</name><size>petit</size><product>
<product><name>marteau</name><size>petit</size><product>
</class>
<class cls="menager petit" taillemax="moyen" poids="6">
<product><name>balayette</name><size>moyen</size><product>
</class>
</products> |
je peux p-e faire les deux avec un seul xslt mais à vrai dire, ca m'importe peu d'en utiliser un ou 50 du moment que le resultat final est là
je ne suis pas un adepte du faites moi mon truc donc un algo qui me guiderait suffisemment me plairait amplement. merci d'avance