web-dev-qa-db-fra.com

Que signifie «@ * | node ()» dans une sélection de modèle d'application XSLT?

J'ai lu quelques exemples XSLT et j'ai trouvé ce code:

<xsl:apply-template select="@*|node()"/>

Qu'est-ce que ça veut dire?

37
maximus

L'expression XPath @* | node() sélectionne l'union des nœuds d'attribut (@*) Et tous les autres types de nœuds XML ( node()).

C'est un raccourci pour attribute::* | child::node().

Dans XSLT, XPath est relatif au nœud de contexte et à l'axe par défaut sélection est l'axe child, donc l'expression

  • sélectionne tous les attributs et enfants immédiats du nœud de contexte (lorsqu'il est utilisé comme expression select="...", par exemple dans <xsl:apply-templates> )
  • correspond à tous les nœuds d'attribut et autres quel que soit le contexte (lorsqu'il est utilisé comme expression match="" dans <xsl:template>) - note qu'il existe une différence entre la sélection de nœuds et leur correspondance: le nœud de contexte n'a d'importance que pour la sélection.

Imaginez que le nœud suivant est le nœud de contexte:

<xml attr="value">[
  ]<child />[
  ]<!-- comment -->[
  ]<child>
    <descendant />
  </child>[
]</xml>

l'expression node() sélectionnera non seulement les deux nœuds <child>, mais aussi quatre nœuds de texte uniquement en espace blanc (signifiés par [ et ] pour le plaisir de visibilité) et le commentaire. Le <descendant> N'est pas sélectionné.

Une caractéristique particulière de XML est que les nœuds d'attribut ne sont pas les enfants des éléments auxquels ils appartiennent (bien que le parent d'un attribut soit l'élément auquel il appartient) .

Cette relation asymétrique oblige à les sélectionner séparément, d'où le @*.

Il correspond à n'importe quel nœud d'attribut appartenant au nœud de contexte, donc le attr="value" Sera également sélectionné.

Le | Est l'opérateur d'union XPath. Il crée un seul ensemble de nœuds à partir de deux ensembles de nœuds distincts.

<xsl:apply-templates> Trouve ensuite le <xsl:template> Approprié pour chaque nœud sélectionné et l'exécute pour ce nœud. Ceci est la partie correspondant au modèle que j'ai mentionnée ci-dessus.

42
Tomalak

Pour ajouter à l'excellente réponse de Tomalak:

La plupart du temps, on verrait <xsl:apply-template select="@*|node()"/> utilisé dans un modèle comme celui-ci :

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

Il s'agit de la règle d'identité ou " modèle d'identité".

L'un des modèles de conception XSLT les plus fondamentaux et les plus puissants est l'utilisation et la substitution de la règle d'identité .

Si une transformation se compose uniquement de la règle d'identité, le résultat de la transformation est le document XML source lui-même - c'est pourquoi le modèle est appelé "la règle d'identité".

Pourquoi ce résultat est-il produit?

La réponse courte est : à cause du modèle de traitement XSLT.

Une explication plus détaillée doit commencer par le haut :

node()

correspond à tout élément, nœud de texte, commentaire ou instruction de traitement. Le noeud document (racine) est également associé à node().

Nous pouvons imaginer les nœuds "feuilles" de n'importe quelle arborescence de documents - ce sont tous les nœuds qui n'ont pas eux-mêmes d'enfants tels qu'un nœud de texte, un commentaire et une instruction de traitement. Un élément vide doit également être considéré comme un nœud feuille.

La règle d'identité est initialement sélectionnée pour être exécutée (appliquée) sur tous les nœuds enfants des nœuds de document (il s'agit des éléments supérieurs uniques et des éventuels commentaires ou frères et sœurs d'instructions de traitement qu'elle pourrait avoir). Le nœud mis en correspondance est copié de manière superficielle et s'il s'agit d'un nœud feuille non élémentaire, l'instruction <xsl:apply-templates select="node()|@*"/> ne sélectionne aucun nœud ni attribut.

Si le nœud correspondant est un élément, il est copié de façon superficielle, puis l'instruction <xsl:apply-templates select="node()|@*"/> entraîne l'application du même modèle (car il n'y a aucun autre modèle dans le code de transformation) contre chacun de ses attributs et chacun de ses nœuds enfants.

Il s'agit de la récursivité qui entraîne le traitement de chaque nœud du document XML jusqu'à ce que les nœuds feuilles ou les attributs soient atteints et à quel endroit la <xsl:apply-templates select="node()|@*"/> ne sélectionne aucun enfant ou nœud d'attribut.

16
Dimitre Novatchev

Félicitations à @Tomalak pour la première bonne réponse. La tique devrait continuer sa réponse. Je vais simplement ajouter quelques éclaircissements à sa réponse.

Note One

... @ * | node () sélectionne l'union de ...

Le | L'opérateur renvoie non seulement l'union des deux opérandes, mais trie dans l'ordre du document et supprime les doublons. La partie de déduplication n'est pas pertinente ici car il n'y a pas de doublons à supprimer, mais la partie de tri mérite d'être notée. Une version plus correcte serait de dire ...

... @ * | node () sélectionne l'union, triée dans l'ordre du document, de ...

Remarque deux

... et tous les autres types de nœuds enfants XML (node ​​())

C'est globalement vrai, mais trompeur. Lorsque la plupart des gens lisent "nœuds enfants XML", ils pensent que les nœuds enfants au sens DOM. Mais ce n'est pas ce qui est sélectionné. Seuls les nœuds XDM sont sélectionnés. Pour une illustration, consultez le document suivant.

<?xml version="1.0" encoding="ISO-8859-1"?>
<root-element my-attrib="myattrib-vaue" xmlns:hi="www.abc.com"><child-element />
abc&apos;def
</root-element>

Supposons maintenant que l'élément de contexte soit "l'élément racine". Un lecteur de la réponse de Tomalak se pose la question: qu'est-ce qui est sélectionné par "@ * | node ()"? L'implication de la réponse de Tomalak pour ceux qui pensent au modèle DOM serait qu'il y a 6 choses sélectionnées:

  • L'attribut my-attrib
  • L'attribut node-space (qui est un vrai attribut dans DOM)
  • Le nœud d'élément enfant
  • Le bit 'abc'
  • La référence d'entité
  • Le bit "def".

Mais ce n'est pas vrai en XSLT. Ce qui est réellement sélectionné est ...

  • L'attribut my-attrib
  • Le nœud d'élément enfant
  • Le nœud de texte XDM, étant la concatination de 3 nœuds de texte DOM comme: "abc'def"

Donc, une déclaration plus précise serait ...

L'expression XPath @ * | node () sélectionne l'union, triée dans l'ordre du document, de (nœuds d'attribut de l'élément de contexte et nœuds enfants XML de l'élément de contexte au sens du XDM). Le modèle XD ignore certains types de nœuds, tels que les définitions d'entité, qui se trouvent dans le DOM, et les nœuds DOM de texte contigus sont concaténés en un nœud de texte XDM.

7
Sean B. Durkin