IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

XSL/XSLT/XPATH XML Discussion :

[XPath] test self::attribute [FAQ]


Sujet :

XSL/XSLT/XPATH XML

  1. #1
    Membre éclairé Avatar de luta
    Inscrit en
    Novembre 2003
    Messages
    1 038
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 1 038
    Points : 786
    Points
    786
    Par défaut [XPath] test self::attribute
    Bonjour, je voudrais savoir comment tester si le noeud courant est un attribut dont nom est name...
    j ai testé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    <xsl:if text="self::@name"/>
    <xsl:if text="self::attribute('name')"/>
    ...mais rien en fonctionne ...

  2. #2
    Expert éminent
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Points : 8 339
    Points
    8 339
    Par défaut
    C'est parce qu'aucun de ces chemins XPath n'est valide

    en plus c'est test pas text

    essaie ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:if test=".=../@name"/>

  3. #3
    Membre éclairé Avatar de luta
    Inscrit en
    Novembre 2003
    Messages
    1 038
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 1 038
    Points : 786
    Points
    786
    Par défaut
    pas bête ton idée,
    j'écrirai ceci donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:if test=".= parent::*/@name">
    Merci!!

  4. #4
    Expert éminent
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Points : 7 103
    Points
    7 103
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:if test="count(../*) != count(.|../*) and name() = 'name'">

  5. #5
    Expert éminent
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Points : 7 103
    Points
    7 103
    Par défaut
    Citation Envoyé par Swoög
    C'est parce qu'aucun de ces chemins XPath n'est valide

    en plus c'est test pas text

    essaie ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:if test=".=../@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é.

  6. #6
    Membre éclairé Avatar de luta
    Inscrit en
    Novembre 2003
    Messages
    1 038
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 1 038
    Points : 786
    Points
    786
    Par défaut
    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <xsl:if test="count(../*) != count(.|../*) and name() = 'name'">
    je n arrive pas à comprendre qu est ce que cela signifie..?

  7. #7
    Expert éminent
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Points : 8 339
    Points
    8 339
    Par défaut
    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 donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    count(../*) = count(.|../*) + 1
    alors que si c'était un fils, ça serait égale (puisque chaque noeud n'est compté qu'une fois)

  8. #8
    Membre éclairé Avatar de luta
    Inscrit en
    Novembre 2003
    Messages
    1 038
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 1 038
    Points : 786
    Points
    786
    Par défaut
    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

  9. #9
    Expert éminent
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Points : 7 103
    Points
    7 103
    Par défaut
    .|../* 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 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    <xsl:if test="count(parent::node()/child::*) != count(self::node()|parent::node()/child::*) 
    and name() = 'name' and not(self::processing-instruction())">

  10. #10
    Expert éminent
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Points : 7 103
    Points
    7 103
    Par défaut
    Citation Envoyé par Swoög
    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 donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    count(../*) = count(.|../*) + 1
    C'est l'inverse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    count(../*) + 1 = count(.|../*)

  11. #11
    Expert éminent
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Points : 8 339
    Points
    8 339
    Par défaut
    Citation Envoyé par GrandFather
    C'est l'inverse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    count(../*) + 1 = count(.|../*)
    Oui, désolé... ...

    Bon, je vais me recoucher moi là, on va arretter le massacre

  12. #12
    Membre éclairé Avatar de luta
    Inscrit en
    Novembre 2003
    Messages
    1 038
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 1 038
    Points : 786
    Points
    786
    Par défaut
    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

  13. #13
    Expert éminent
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Points : 8 339
    Points
    8 339
    Par défaut
    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...

  14. #14
    Expert éminent
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Points : 7 103
    Points
    7 103
    Par défaut
    Citation Envoyé par Swoög
    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ù ^^]
    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.

    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 ?

  15. #15
    Rédacteur

    Avatar de Erwy
    Homme Profil pro
    Développeur Web
    Inscrit en
    Novembre 2003
    Messages
    4 967
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2003
    Messages : 4 967
    Points : 10 927
    Points
    10 927
    Par défaut
    Citation Envoyé par GrandFather
    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.
    Tu teste avec ou sans key ?

  16. #16
    Expert éminent
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Points : 7 103
    Points
    7 103
    Par défaut
    Allez, je vous mets le pied à l'étrier avec un petit énoncé...

    Soit le document XML suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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>
    Ecrire la feuille de style XSL qui transforme ce document en ce résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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()
    Pour vous alléger la tâche, je vous donne une partie du code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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>
    Il n'y a plus qu'à compléter la fonction...

  17. #17
    Expert éminent
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 54

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Points : 7 103
    Points
    7 103
    Par défaut
    Citation Envoyé par Erwy
    Tu teste avec ou sans key ?
    Sans...

Discussions similaires

  1. Réponses: 3
    Dernier message: 02/07/2010, 15h50
  2. [XPATH] Test sur 2 attributs
    Par robbiano78 dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 09/03/2009, 10h10
  3. [XPATH]Test d'une attribut à ""
    Par tatemilio2 dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 15/11/2007, 09h17
  4. [XSL][XPATH] recopier les attributs d un élément mais pas le
    Par Triangle dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 26/08/2005, 16h07
  5. xpath-->test sur les commentaires
    Par yos dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 11/07/2005, 12h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo