Forum Programmation.autre Grouper le traitement de balises via XSLT

Posté par  (site web personnel) .
Étiquettes : aucune
0
9
oct.
2006
Bonjour,

Je débute un peu en XSLT et je me trouve confronté à un problème que j'ai un peu de mal à formaliser. Un bon exemple valant mieux qu'un long discours...

Voici un fragment XML :

[resource id="r1" name="Titi" /]
[resource id="r2" name="Titi" /]
[task id="t1" resource="r1" /]
[task id="t2" resource="r1" /]
[task id="t3" resource="r2" /]


Je voudrais traiter chaque task en les regroupant par resource.
Soit, je voudrais obtenir un résultat proche de :

[ul]
[li]Ressource Toto :[/li]
[ul]
[li]r1[/li]
[li]r2[/li]
[/ul]
[/ul]
[ul]
[li]Ressource Titi :[/li]
[ul]
[li]r3[/li]
[/ul]
[/ul]


Dans ma première implémentation, j'étais parti pour n'avoir qu'un seul template, correspondant à "task". Dans ce template, si c'est le premier à traiter de la ressource citée j'ajoute l'introduction (ouvrant entre autre le bloc "ul") et si c'est le dernier je ferme le "ul".
Or, le processeur XSLT râle car mes ouvertures et fermeture du "ul" englobant se font à l'intérieur de "xsl:if" rompant la correspondance entre balises ouvrantes et fermantes.

Quelles solutions utilise-t-on classiquement dans ce genre de cas ?
PS : je souhaiterai éviter de modifier le XML.
  • # utiliser <xsl:for-each>

    Posté par  . Évalué à 0.

    Pour ce genre de chose le plus simple est d'utiliser le tag <xsl:for-each>. Dans un template associé à l'élément père des éléments <task>, on peut écrire quelque chose de ce genre:

    <ul>
    <xsl:for-each select="task">
    <li><xsl:value-of select="."/></li>
    </xsl:for-each>
    </ul>
    • [^] # Re: utiliser <xsl:for-each>

      Posté par  (site web personnel) . Évalué à 1.

      En fait, le problème n'est pas le traitement des task, mais plutôt le fait de faire une seule action pour deux tasks.

      En effet, je n'affiche qu'une seule fois la ressource r1 pour les deux tasks t1 et t2.

      Désolé de ne pas avoir été plus précis dès mon premier post.
      • [^] # Re: utiliser <xsl:for-each>

        Posté par  . Évalué à 0.

        Désolé également, j'ai lu un peu vite. Si je comprends bien, le code dont tu as besoin serait plutôt, toujours dans un template associé au père des éléments <task> et <resource>

        <ul>
        <xsl:for-each select="resource">
        <li>Resource <xsl:value-of select="."/></li>
        <ul>
        <xsl:variable name="resourceId" select="@id"/>
        <xsl:for-each select="../task[@resource=$resourceId]">
        <li>Task <xsl:value-of select="."/></li>
        </xsl:for-each>
        </ul>
        </xsl:for-each>
        </ul>
  • # Ma solution

    Posté par  (site web personnel) . Évalué à 1.

    J'ai fini par trouver une solution que je crois relativement élégante.

    Dans mon exemple, j'avais oublié que les "task" sont dans un "tasks".
    Du coup, sur "tasks" je parcours tous les "resource" de façon uunique avec un "for-each" et un select comme suit :
    task[position() = 1 or not(preceding-sibling::node()/@resource = @resource)]

    Voilou, ça marche. Et je n'ai qu'un seul "for-each", ce qui est plus dans l'esprit je pense.

    Merci à tous.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.