2010-07-14 19 views
4

Lorsque j'utilise "apply-templates" et sélectionne une séquence variable, le modèle agit-il sur le contexte de l'élément dans la séquence ou agit-il sur le contexte de l'élément dans le document?Application de modèles à des éléments d'une variable/séquence

Dans l'exemple ci-dessous, il semble faire l'un ou l'autre, mais je ne comprends pas pourquoi.

<root> 
<a/> 
<b/> 
<c><a/></c> 
<a/> 
</root> 

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:template match="root"> 
    <!--this variable give me a sequence of "a" elements--> 
    <xsl:variable name="someElementA1" select="//a"/> 
    <xsl:variable name="someElementA2"> 
     <xsl:copy-of select="//a"/> 
    </xsl:variable> 
    <xsl:for-each select="$someElementA1/a"> 
     <xsl:element name="test"> 
      <xsl:text>This is scenario 1: </xsl:text> 
      <xsl:apply-templates select="."/> 
     </xsl:element> 
    </xsl:for-each> 
    <xsl:for-each select="$someElementA2/a"> 
     <xsl:element name="test"> 
      <xsl:text>This is scenario 2: </xsl:text> 
      <xsl:apply-templates select="."/> 
     </xsl:element> 
    </xsl:for-each> 
    <xsl:element name="test"> 
     <xsl:text>This is scenario 3: </xsl:text> 
     <xsl:apply-templates select="$someElementA1"/> 
    </xsl:element> 
    <xsl:element name="test"> 
     <xsl:text>This is scenario 4: </xsl:text> 
     <xsl:apply-templates select="$someElementA2/a"/> 
    </xsl:element> 
</xsl:template> 
<!--these are the templates to apply--> 
<xsl:template match="a[parent::c]"> 
    <xsl:text>This element has a parent</xsl:text> 
</xsl:template> 
<xsl:template match="a[parent::root]"> 
    <xsl:text>This element is in the root element</xsl:text> 
</xsl:template> 
<xsl:template match="a"> 
    <xsl:text>This element is in the sequence</xsl:text> 
</xsl:template> 
</xsl:stylesheet> 

SORTIE:

<test>This is scenario 2: This element is in the sequence</test> 
<test>This is scenario 2: This element is in the sequence</test> 
<test>This is scenario 2: This element is in the sequence</test> 
<test>This is scenario 3: This element is in the root elementThis element has a parentThis element is in the root element</test> 
<test>This is scenario 4: This element is in the sequenceThis element is in the sequenceThis element is in the sequence</test> 
+0

Bonne question (+1). Voir ma réponse pour une explication détaillée. –

Répondre

2

Les résultats que vous obtenez sont en raison des faits suivants:

  1. Une séquence de nœuds contient les noeuds car ils sont dans leur document respectif - pas de copies des noeuds.

  2. <xsl:copy-of> crée une copie de chaque noeud sélectionné par l'expression dans l'attribut select.

crée un nouveau fragment XML (arbre temporaire), ce qui est la valeur de la variable $someElementA2

$someElementA1/a 

ne sélectionne pas un nœud, car aucun des éléments en $someElementA1 ont des enfants nommés a.

$someElementA2/a 

sélectionne tous les éléments a qui sont des enfants du nœud de document (/).

+0

J'ai recherché un peu plus loin ... au lieu d'utiliser la copie-d'utilisation xsl: sequence. Mais cela ne semble pas fonctionner, sauf si vous mettez aussi un as = "element() *" dans la variable. Le moment aha est qu'il y a une différence entre une collection d'éléments et je suppose que ce que vous appelleriez une séquence d'éléments, qui est plus comme naviguer dans un chemin d'éléments et agir sur eux dans leur contexte de document. –

+0

@ Darin-Walsh: Oui, s'il y a des éléments générés dans le corps d'une variable, il a un type par défaut 'document-node()'. Mais pourquoi devriez-vous faire cela? Mieux vaut utiliser une définition directe: '' Rappelez-vous simplement - n'essayez jamais de placer quelque chose dans le corps d'un '. Essayez toujours de spécifier la valeur d'une variable dans son attribut 'select'. –

+0

La raison pour laquelle je l'ai mis dans le corps de la variable est parce que j'utilise soit des conditions complexes, soit l'addition d'éléments dans une séquence. Je verrai si la variable peut gérer ce contenu "mixte" de nœuds de documents réels et d'éléments générés, et ce qui arrive à la séquence lorsqu'elle est passée à travers un param. Il pourrait y avoir un moyen de faire ce qui précède avec une instruction select en utilisant "for ..."? –