2010-01-30 17 views
10

¿Es posible pasar una variable de una plantilla primaria a su elemento hijo?XSL: pasar variables entre plantillas

<xsl:template match="structure"> 
    <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable> 
    <xsl:apply-templates select="folders"> 
    <xsl:with-param name="var1" select="'{var}'"/> 
    </xsl:apply-templates> 
</xsl:template> 

esta plantilla coincidirá:

<xsl:template match="folder"> 
    <xsl:param name="var1"/> 
    <xsl:value-of select="$var1"/> 
</xsl:template> 

Ves lo que quiero utilización var como var1 en la plantilla emparejado.

Como puedo hacer este trabajo?

edición: la estructura es la siguiente:

<structure path="C:\xampplite\htdocs\xampp"> 
    <folders> 
    <folder name="img"> 
     <date>01/28/10 21:59:00</date> 
     <size>37.4 KB</size> 
    </folder> 
</folders> 
</structure> 

Edit2:

<xsl:template match="folder"> 
<xsl:variable name="var1"><xsl:value-of select="../../@path"/></xsl:variable> 
<xsl:variable name="var2"><xsl:value-of select="@name" /></xsl:variable> 
<xsl:variable name="var3"><xsl:value-of select="$var1"/>\<xsl:copy-of select="$var2"/> </xsl:variable> 
<th colspan="2" align="left" bgcolor="#FF5500"><a onclick="foo('{$var3}')"><xsl:value-of select="$var3"/></a></th> 

en la función de JScript la cadena está exenta de barras invertidas. alguien sabe por qué?

C: xampplitehtdocsxamppimg

+0

Eso debería "solo funcionar" - la pregunta implica que no es así. Sin esperar ... el nombre de la plantilla y el select = no coinciden en el código mostrado, tienes select = "folders" y match = "folder" sin 's'. ¿Ese es el problema o es solo un ejemplo? – Murph

+0

echa un vistazo a mi respuesta aquí http://stackoverflow.com/a/41530702/4251431 –

Respuesta

26

Puede pasar parámetros a las plantillas con nombre que <xsl:call-template> llamada a través de, por ejemplo .:

<xsl:call-template name="name"> 
    <xsl:with-param name="param" select="xpathexpr"/> 
</xsl:call-template> 

<xsl:template name="name"> 
    <xsl:param name="param"/> 
    ... 
</xsl:template> 

Cuando se llama a una plantilla llamada, el nodo de contexto es el contexto actual. Así que para llamar a una plantilla llamada de nodos secundarios, es necesario cambiar el contexto actual utilizando <xsl:for-each>:

<xsl:for-each select="child"> 
    <xsl:call-template name="name"> 
     <xsl:with-param name="param" select="xpathexpr"/> 
    </xsl:call-template> 
</xsl:for-each> 

En su caso, sin embargo, no hay necesidad de pasar parámetros, ya que la variable que se está tratando el uso es algo que es navegable desde el nodo de contexto.Y que no es necesario utilizar todas esas variables (ni debe nunca dar una variable un nombre tan inútil como var1):

<xsl:template match="folder"> 
    <xsl:variable name="linkarg" value="concat(../../@path, '\\', @name)"/> 
    <xsl:variable name="linktext" value="concat(../../@path, '\', @name)"/> 
    <th colspan="2" align="left" bgcolor="#FF5500"> 
     <a onclick="foo('{$linkarg}')"> 
     <xsl:value-of select="$linktext"/> 
     </a> 
    </th> 
</xsl:template> 

Además, me gustaría tener la tentación de utilizar en lugar de ancestor::structure[1]/@path../../@path, porque hace que la intención sea mucho más explícita; su versión significa "obtener el atributo path del elemento primario", mientras que mi versión significa "atravesar la cadena de elementos antecesores hasta que encuentre el primero llamado structure, y obtenga su atributo path".

+2

+1 para asesorar sobre la forma idiomática de hacerlo (por ejemplo, usar contexto en lugar de variables). (Por cierto: las barras invertidas en su respuesta deben ser reparadas.) – Tomalak

+0

Oh, claro. JavaScript. Fijo. –

+0

No, aún no está completamente corregido. No se permiten barras diagonales inversas en XPath (consulte el último párrafo). – Tomalak

5

Dos problemas con la plantilla structure:

  1. Usted está solicitando plantillas de selección de folders, pero tienen una coincidencia de plantilla en folder. Cambie a folder, o si tiene una plantilla folders, asegúrese de que pase el valor del parámetro var1 a la plantilla folder.
  2. Su with-param @select usa '{var}', que selecciona esa cadena literal {var}. Si desea seleccionar la variable var, elimine las comillas circundantes y las llaves y simplemente seleccione $var.

cambios aplicados a la plantilla structure:

<xsl:template match="structure"> 
    <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable> 
    <xsl:apply-templates select="folder"> 
    <xsl:with-param name="var1" select="$var"/> 
    </xsl:apply-templates> 
</xsl:template> 
4

El código exacto para la llamada sería:

<xsl:template match="structure"> 
    <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable> 
    <xsl:apply-templates select="folders/folder"> 
    <xsl:with-param name="var1" select="$var"/> 
    </xsl:apply-templates> 
</xsl:template> 

Otra forma de acceder al atributo @path del nodo raíz sería modificando su plantilla a:

<xsl:template match="folder"> 
    <xsl:value-of select="../../../@path"/> 
</xsl:template> 
+0

la última propuesta funciona bien para mí. thx – binaryguy

7

Al utilizar XSLT 2.0, es posible pasar parámetros a las plantillas de niño, mediante la adición de tunnel="yes" a la <xsl:with-param .../> en el callsite, y al elemento de </xsl:with-param .../> en la plantilla llamada también. Sólo hacer:

<xsl:template match="folder"> 
    <xsl:param name="var1" tunnel="yes"/> <!-- note the 'tunnel="yes"' attribute here! --> 
    <xsl:value-of select="$var1"/> 
</xsl:template> 

<xsl:template match="structure"> 
    <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable> 
    <xsl:apply-templates select="folders"> 
    <xsl:with-param name="var1" select="$var" tunnel="yes"/> <!-- note the 'tunnel' attribute here, too! --> 
    </xsl:apply-templates> 
</xsl:template> 

Para más información, por favor refiérase a la sección 10.1.2 Tunnel parameters en la especificación XSLT 2.0.


Un ejemplo extendido

Con parámetros del túnel, incluso se podría hacer esto:

<xsl:template match="structure"> 
    <!-- same as before --> 
</xsl:template> 

<xsl:template match="folder"> 
    <!-- Look, ma, no param declaration! --> 
    <!-- ... --> 
    <xsl:apply-templates select="date"/> 
    <!-- ... --> 
</xsl:template> 

<xsl:template match="folder/date"> 
    <xsl:param name="var1" tunnel="yes"/> 
    <xsl:value-of select="$var1"/> 
</xsl:template> 

Debido al atributo túnel, el parámetro var1 se pasa de la plantilla inicial a través de todas las plantillas de intermedios en la plantilla "folder/date".

Sólo recuerde que la declaración tunnel="yes" atributo debe estar presente tanto en la <xsl:param name="var1" tunnel="yes"/>Y el atributo <xsl:with-param name="var1" tunnel="yes" select="..."/> correspondiente.

Cuestiones relacionadas