Bonjour, je voudrais savoir comment tester si le noeud courant est un attribut dont nom est name...
j ai testé...mais rien en fonctionne ...:oops: :oops:Code:
1
2
3 <xsl:if text="self::@name"/> <xsl:if text="self::attribute('name')"/>
Version imprimable
Bonjour, je voudrais savoir comment tester si le noeud courant est un attribut dont nom est name...
j ai testé...mais rien en fonctionne ...:oops: :oops:Code:
1
2
3 <xsl:if text="self::@name"/> <xsl:if text="self::attribute('name')"/>
C'est parce qu'aucun de ces chemins XPath n'est valide ;)
en plus c'est test pas text ;)
essaie ceci :Code:<xsl:if test=".=../@name"/>
pas bête ton idée,
j'écrirai ceci donc
Merci!!:mouarf:Code:<xsl:if test=".= parent::*/@name">
Bonjour,
l'axe self ne te permettra pas de sélectionner un attribut, seul l'axe attribute le peut, mais il ne te sera d'aucune utilité ici. Pour détecter si le noeud contextuel est un attribut, il faut se rappeler une caractéristique fondamentale d'un noeud attribut : son parent est un élément mais il ne fait pas partie des fils de cet élément (voir spécification XPath § 5.3). C'est cette caractérisque qu'il faut tester :
Code:<xsl:if test="count(../*) != count(.|../*) and name() = 'name'">
Attention, là tu testes si le contenu du noeud courant est le même que celui d'un attribut name du parent du noeud courant ; c'est un test d'égalité que tu fais, pas un test d'identité. ;)Citation:
Envoyé par Swoög
Merci GrandFather effectivement avec la syntaxe précédente j ai un souci car j ai un autre attribut avec la même valeur ce qui pose finalement problème...
maintenant si j essaie de décoder ce que tu as écris
je n arrive pas à comprendreCode:<xsl:if test="count(../*) != count(.|../*) and name() = 'name'">
qu est ce que cela signifie..?Code:count(.|../*)
comme un attribut n'est pas le fils de son père (c'est super logique jusque là XD)
tu vas compter tous les fils + l'attribut doncalors que si c'était un fils, ça serait égale (puisque chaque noeud n'est compté qu'une fois)Code:count(../*) = count(.|../*) + 1
Merci,
cette petite phrase m a bcp aidé
"puisque chaque noeud n'est compté qu'une fois"
car sinon effectivement...tout est attribute...
Merci bcp à vous deux :)
.|../* fait une union entre le noeud courant (qui peut être un attribut ou un élément) et les noeuds fils de son parent (qui ne peuvent être que des éléments).
De deux choses l'une :
- le noeud courant est un élément ; cet élément faisant forcément partie des fils de son père, et une union ne pouvant pas renvoyer un nodeset avec des doublons, le test count(../*) != count(.|../*) est faux, les deux parties de l'expression renvoyant le même résultat
- le noeud courant est un attribut ; ne faisant pas partie des fils de son père, count(.|../*) renverra un résultat différent de count(../*), la différence sera de 1 exactement
Pour être totalement fiable, il y a encore deux cas qui restent à traiter, le premier est celui où le noeud courant est une instruction de traitement qui porte le même nom que l'attribut dont on veut tester l'identité et qui a le même parent que lui. Il faut donc ajouter une condition au test pour filtrer ce genre de noeud. Le deuxième est celui où le noeud courant est l'élément racine (document element) du document XML, le chemin parent::* renverra un ensemble de noeuds vide, puisque la racine ne peut être atteinte par ce chemin. Si cet élément porte le même nom que l'attribut recherché, il sera considéré à tort comme étant cet attribut. Il faut donc éviter parent::* par et le remplacer par parent::node().
Cela donne (en remplaçant l'écriture abrégée par l'écriture normale, pour plus de clarté j'espère) :
Code:
1
2 <xsl:if test="count(parent::node()/child::*) != count(self::node()|parent::node()/child::*) and name() = 'name' and not(self::processing-instruction())">
C'est l'inverse :Citation:
Envoyé par Swoög
;)Code:count(../*) + 1 = count(.|../*)
Oui, désolé... :oops:...Citation:
Envoyé par GrandFather
Bon, je vais me recoucher moi là, on va arretter le massacre :mouarf:
Merci encore pour ces précisions,
vu que ceci n est pas dans la FAQ je pense que ça vaudrait le coup de l ajouter.
Faut il poster ta réponse dans le thread correspondant ou pas?
En tout cas tu devrais le faire car ça manque
en tout cas merci encore
C'est vrai que ça pourrait être très utile quand même... En même temps, (en théorie) on devrait toujours savoir où on est dans un document quand on effectue une transformation XSLT... [mais bon, y'a toujours des cas où ^^]
Enfin, c'est sûr que ça serait intéressant quand même... en plus la solution est (au bout du compte) assez simple...
Il existe certains traitements génériques pour lesquels le développeur ignore a priori sur quel type de noeud le traitement va s'appliquer, et dont le traitement diffère selon le type.Citation:
Envoyé par Swoög
Un exemple simple, auquel j'ai été confronté : écrire une fonction XSLT qui prend en paramètre n'importe quel type de noeud, et qui renvoie une chaîne contenant une expression XPath valide qui permettrait d'accéder à ce noeud. Là, tu es obligé de tester le type du noeud.
Tiens, si vous vous sentez d'attaque, essayez de développer ce type de fonction, c'est extrêmement formateur. La mienne fait une quarantaine de lignes, pourrez-vous faire mieux ? ;)
Tu teste avec ou sans key ?Citation:
Envoyé par GrandFather
Allez, je vous mets le pied à l'étrier avec un petit énoncé...
Soit le document XML suivant :
Ecrire la feuille de style XSL qui transforme ce document en ce résultat :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 <?xml version="1.0" encoding="UTF-8"?> <r> <a> <b>1<x/>2</b> <c>2</c> </a> <?truc aaa ?> <d> <e h="toto">1</e> <f>2</f> </d> <?truc bbb ?> <a> <b>1<x/>2</b> <c>2</c> </a> </r>
Pour vous alléger la tâche, je vous donne une partie du code :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 / /r /r/a[1] /r/a[1]/b /r/a[1]/b/text()[1] /r/a[1]/b/x /r/a[1]/b/text()[2] /r/a[1]/c /r/a[1]/c/text() /r/processing-instruction()[1] /r/d /r/d/e /r/d/e/@h /r/d/e/text() /r/d/f /r/d/f/text() /r/processing-instruction()[2] /r/a[2] /r/a[2]/b /r/a[2]/b/text()[1] /r/a[2]/b/x /r/a[2]/b/text()[2] /r/a[2]/c /r/a[2]/c/text()
Il n'y a plus qu'à compléter la fonction... ;)Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:template match="/"> <xsl:for-each select="descendant-or-self::node()[not(self::text()) or normalize-space() != '']|descendant-or-self::node()/@*"> <xsl:call-template name="display-xpath"> <xsl:with-param name="node" select="."/> </xsl:call-template> <xsl:text> </xsl:text> </xsl:for-each> </xsl:template> <xsl:template name="display-xpath"> <xsl:param name="node"/> ... </xsl:template> </xsl:stylesheet>
Sans... ;)Citation:
Envoyé par Erwy