pas très élégant... à vrai dire je n'en doute pas, je n'ai pas eu de
formation à xsl ni vraiment en informatique pour tout dire...
J'apprend xsl au fur et à mesure des besoins que je rencontre et c'est
sûrement dommage car je dois me compliquer la vie des fois ;)
C'est aussi souvent un problème de temps, il faut développer vite mais c'est
vrai, parfois perdre un peu de temps à court terme en fait gagner beaucoup à
long terme !
C'est ici l'occasion d'apprendre justement...
Je crois n'avoir pas ou mal compris la solution de stéphane. Je ne sais pas
trop où insérer le traitement (="afficher A + son id")
Je travail en output=html, et en faisant tourner cette xsl je récupère tous
les noeuds A.
Comme je l'avais écrit j'ai l'impression que cette solution me permet de
récupérer l'arbre xml des A (non ?). N'est-ce pas le but des <xsl:copy> ?
Ta solution Eric ne va-t-elle pas dans le même sens en récupérant la
hiérarchie des A dans <resultat> ?
d'autre part dans mon cas réél je n'ai pas d'@id comme énoncé dans le 1er
message, je les ai mis juste histoire de mieux comprendre et pouvoir écrire
le résulat A1, A2, A3... plus explicitement.
Si je reprend la solution d'Eric en output=html cela donne-t-il ? :
<xsl:stylesheet xmlns:xsl = "
http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="html"/>
<xsl:template match="root|A">
<xsl:value-of select="@id"/>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="*">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
Je récupère tous les neouds A ici, ce que j'aimerai c'est pour chaque noeud
A, matcher chacun des sous-noeud A (direct ou indirecte mais 1seul niveau de
A).
Disons qu'en sortie HTML j'aimerai pouvoir écrire :
à partir du même fichier xml :
<root>
<A id="context">
<foo>
<A id="1">
<A id="1.1"/>
<bar>
<A id="1.2"/>
</bar>
</A>
</foo>
<A id="2"/>
<fred>
<waldo>
<A id="3">
<A id="3.1"/>
</A>
</waldo>
</fred>
</A>
</root>
SORTIE :
Acontext:
==> A1
==> A2
==> A3
A1 :
==> A1.1
==> A1.2
A2 :
A3 :
==> A3.1
A1.1 :
A1.2 :
A3.1 :
Je n'arrive pas à obtenir ce résultat à partir des solutions proposées,
avec le template reccursif j'y arrive facilement :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="
http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="root">
Résultat : <br/>
<xsl:for-each select="A | //A">
A<xsl:value-of select="@id"/> : <br/>
<xsl:for-each select="*">
<xsl:call-template name="MatchA1erNiveau"/>
</xsl:for-each>
<br/>
</xsl:for-each>
</xsl:template>
<xsl:template name="MatchA1erNiveau">
<xsl:choose>
<xsl:when test="name()='A'">
==> A<xsl:value-of select="@id"/><br/>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="*">
<xsl:call-template
name="MatchA1erNiveau"/>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Ou peut être (un peu) mieux ? :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="
http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="root">
Résultat : <br/>
<xsl:apply-templates select="A | //A"/>
</xsl:template>
<xsl:template match="A">
A<xsl:value-of select="@id"/> : <br/>
<xsl:for-each select="*">
<xsl:call-template name="MatchA1erNiveau"/>
</xsl:for-each>
<br/>
</xsl:template>
<xsl:template name="MatchA1erNiveau">
<xsl:choose>
<xsl:when test="name()='A'">
==> A<xsl:value-of select="@id"/><br/>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="*">
<xsl:call-template
name="MatchA1erNiveau"/>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Je crois qu'il y a quelquechose que je n'ai pas compris dans vos solutions,
ou alors mon problème n'était pas assez clairement posé, je ne sais pas...
sincèrement.
je pense que la sortie proposée ici ne peut que répondre parfaitement à mon
problème réél, aussi je suis preneur d'une xsl plus élégante qui donne la
même sortie.
Encore une fois désolé si j'ai du mal à comprendre, je ne suis pas habitué à
cette utilisation très déclarative d'xsl.
Matthieu.
-----Message d'origine-----
De : xml-tech-bounce@xxxxxxxxx [
mailto:xml-tech-bounce@xxxxxxxxx]De la
part de Eric van der Vlist
Envoyé : vendredi 23 septembre 2005 13:43
À : xml-tech@xxxxxxxxx
Objet : [xml-tech] Re: récupérer tous les enfants(directs ou
"indirects") de premiers niveau ?
Le vendredi 23 septembre 2005 à 13:33 +0200, Matthieu Ricaud a écrit :
>
C'est bon, le template récursif était super simple en fait... :
>
<xsl:template match="root">
>
<xsl:for-each select="A">
>
<xsl:for-each select="*">
>
<xsl:call-template name="MatchA1erNiveau"/>
>
</xsl:for-each>
>
</xsl:for-each>
>
</xsl:template>
>
>
<xsl:template name="MatchA1erNiveau">
>
<xsl:choose>
>
<xsl:when test="name()='A'">
>
A<xsl:value-of select="@id"/>
>
</xsl:when>
>
<xsl:otherwise>
>
<xsl:for-each select="*">
>
<xsl:call-template
>
name="MatchA1erNiveau"/>
>
</xsl:for-each>
>
</xsl:otherwise>
>
</xsl:choose>
>
</xsl:template>
Cela marche, mais vous ne tirez pas partie du caractère déclaratif de
XML avec vos xsl:for-each, xsl:call-template et xsl:choose...
Ce que vous faites est en somme l'équivalent non déclaratif (donc moins
élégant en XSLT) de ce qu'avait proposé Stéphane Bonhomme :
<xsl:stylesheet xmlns:xsl = "
http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="root|A">
<xsl:copy>
<xsl:copy-of select="@id"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
Si vous voulez "isoler" ces traitements, il suffit d'utiliser un mode :
xsl:stylesheet xmlns:xsl = "
http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="root">
<xsl:copy>
<xsl:copy-of select="@id"/>
<xsl:apply-templates mode="filtrage"/>
</xsl:copy>
</xsl:template>
<xsl:template match="A" mode="filtrage">
<xsl:copy>
<xsl:copy-of select="@id"/>
<xsl:apply-templates mode="filtrage"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="filtrage">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>
Quant à la dernière transformation que je vous ai proposée :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="
http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="/">
<resultat>
<xsl:apply-templates select="//A[not(ancestor::A)]"/>
</resultat>
</xsl:template>
<xsl:template match="A">
<xsl:copy>
<!-- insérer votre traitement à la place de l'instruction
suivante -->
<xsl:copy-of select="@*"/>
<!--<xsl:apply-templates select=".//A[ count(ancestor::A) =
count(current()/ancestor-or-self::A) ]"/>-->
<!--<xsl:apply-templates select=".//A[ count(ancestor::A[1] |
current() ) = 1 ]"/>-->
<xsl:apply-templates select=".//A[generate-id(ancestor::A[1]) =
generate-id(current())]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Elle est équivalente si ce n'est que le filtrage des noeuds est fait
dans les "select" au lieu d'être fait dans les "match".
Suivant les cas, l'un ou l'autre peut être préférable... Dans votre cas,
le filtrage au niveau des match est plus simple et il semble convenir
(ceci dit, cela dépend du traitement que vous voulez insérer, si par
exemple vous aviez besoin de compter le nombre des noeuds de niveau
inférieur, l'expression XPath redeviendrait bien utile).
Cordialement,
Eric van der Vlist
--
Have you ever thought about unit testing XSLT templates?
http://xsltunit.org
------------------------------------------------------------------------
Eric van der Vlist
http://xmlfr.org http://dyomedea.com
(ISO) RELAX NG ISBN:0-596-00421-4
http://oreilly.com/catalog/relax
(W3C) XML Schema ISBN:0-596-00252-1
http://oreilly.com/catalog/xmlschema
------------------------------------------------------------------------
--
Devenez redacteur <XML>fr et contribuez au developpement du
xml francophone (
http://xmlfr.org/infos/redacteurs/) !
Liste de diffusion "xml-tech@xxxxxxxxx" (
http://xmlfr.org).
Cette liste est a votre disposition pour discuter en francais de
tout sujet technique lie a XML.
Pour resilier votre abonnement, envoyez un message contenant
la commande "unsubscribe" a xml-tech-request@xxxxxxxxx
(
mailto:xml-tech-request@xxxxxxxxx?Subject=unsubscribe)