xsl template example xslt parameters stylesheet apply-templates

xslt - example - XSL nombró el parámetro ''with-param'' usando ''apply-templates''



xsl:param (2)

Mis preguntas están al final de esta publicación, si desea leerlas antes de la explicación completa.

Estoy convirtiendo un documento XML en una página web bonita con XSL, y tengo problemas para pasar una variable correctamente. Tengo muchos xsl:template s definidos y necesito pasar un parámetro específico a uno solo de ellos. Tenía la esperanza de poder pasar un parámetro con nombre que presumiblemente se enviaría a todos los xsl:template s, pero solo sería utilizado por uno solo e ignorado por los demás. Sin embargo, al intentar probar esto por mí mismo (y mi comprensión limitada de XSL), no pude pasar el parámetro en absoluto, y mucho menos probar si estaba perturbando accidentalmente cualquier otra xsl:template s.

El siguiente es un código de ejemplo simplificado ( escrito para esta pregunta, puede contener un error tipográfico o dos ). Tengo muchas diferentes xsl:template definidas para tratar con nodos en el XML, y todo ha funcionado bien hasta ahora. Al agregar un parámetro a estas plantillas, parece que tengo problemas.

Archivo XML:

<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="main.xsl"?> <wrapperNode> <testNode> <subNode/> </testNode> </wrapperNode>

main.xsl:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:import href="test.xsl"/> <xsl:output method="html" indent="yes"/> <xsl:template match="/"> <html> <body> <xsl:apply-templates> <xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param> </xsl:apply-templates> </body> </html> </xsl:template> </xsl:stylesheet>

test.xsl:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="testNode"> <xsl:param name="testParam" /> TEST1 <xsl:value-of select="$testParam" /> TEST2 </xsl:template> </xsl:stylesheet>

Salida (real):

TEST1 TEST2

Salida (esperado / deseado):

TEST1 TEST_PARAMETER TEST2

Mis preguntas con respecto a esto:

  1. ¿Es posible enviar un parámetro con nombre a todas mis xsl:template s utilizando un xsl:apply-templates con xsl:with-param , pero seleccione este valor específicamente por name= dentro de la plantilla real para que se pueda usar explícitamente en ¿Una plantilla única e ignorada por todas las demás (incluso si quisiera agregar otros parámetros con nombres diferentes para otras plantillas más adelante)?

  2. ¿Qué estoy haciendo mal con mi código de ejemplo actual que parece que no recibe el parámetro en absoluto?

  3. ¿Hay una mejor manera de lograr esto?

Edición: quiero dejar en claro que debido a otra salida dentro de la plantilla test.xsl : testNode , estoy seguro de que se está llamando correctamente. SOLO es la parte del parámetro que no está funcionando. No me refiero a perder el tiempo de la gente para averiguar por qué no se llama a esa plantilla. Es.

Actualización: En respuesta a las respuestas que recibí inicialmente, lo que señalaba que el ejemplo que inventé no era completamente correcto (mi error) y no mostraba claramente el problema (es decir, que se está llamando a la plantilla correcta, pero que solo el parámetro parece no estar funcionando), he reemplazado los ejemplos con otros mucho mejores. Este ejemplo muestra más claramente que la plantilla testNode se está llamando con éxito, pero que el parámetro no parece haberse pasado. He probado esto varias veces, antes y después de considerar las respuestas anteriores a esta pregunta. Estoy absolutamente perplejo, ya que todo parece estar correcto de lo que he leído en otros lugares y lo que la gente ha sugerido hasta ahora.


Mis preguntas con respecto a esto:

  1. ¿Es posible enviar un parámetro con nombre a todas mis plantillas xsl: utilizando una plantilla xsl: apply con xsl: with-param, pero seleccione este valor específicamente por nombre = dentro de la plantilla real para que pueda usarse explícitamente en una ¿Plantilla única e ignorada por todas las demás (incluso si quisiera agregar otros parámetros con nombres diferentes para otras plantillas más adelante)?

Si En XSLT 2.0, uno puede usar los llamados "parámetros de túnel", pero en XSLT 1.0 esta es la forma de que algunos parámetros lleguen a alguna plantilla remota en la cadena.

Otra forma es tener parámetros globales , para que no tengan que pasar a través de cada plantilla en la cadena.

.2. ¿Qué estoy haciendo mal con mi código de ejemplo actual que parece que no recibe el parámetro en absoluto?

La razón está en el código que no nos has mostrado . O quizás el documento XML de origen que tiene en su caso real no es el mismo que el que se proporciona aquí. Ejecuté el código provisto y no pude reprochar el problema en absoluto: se produce la salida deseada.

Mi conjetura es que alguna otra plantilla se selecciona antes de la plantilla que coincide con testNode . Esta plantilla no sabe nada sobre el parámetro pasado y no lo pasa a las plantillas que, a su vez, aplica. Por lo tanto, el parámetro no se pasa en absoluto a la plantilla que coincide con testNode .

Mi conjetura es que si reemplaza:

<xsl:apply-templates> <xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param> </xsl:apply-templates>

con

<xsl:apply-templates select="testNode"> <xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param> </xsl:apply-templates>

Usted podría obtener la salida deseada.

Además, podría rastrear con un depurador XSLT (como el de Visual Studio) y ver exactamente qué plantilla está seleccionada.

.3. ¿Hay una mejor manera de lograr esto?

Como dije anteriormente, los parámetros globales pueden usarse como alternativa, aunque no estoy seguro de que esto sea mejor.

Finalmente , aquí está el código que ejecuté que no puede volver a solucionar su problema:

Hoja de estilo XSLT :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" indent="yes"/> <xsl:template match="/"> This is text1 <xsl:apply-templates> <xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param> </xsl:apply-templates> This is text2 </xsl:template> <xsl:template match="testNode"> <xsl:param name="testParam" /> <xsl:value-of select="$testParam" /> </xsl:template> </xsl:stylesheet>

Documento XML :

<?xml-stylesheet type="text/xsl" href="main.xsl"?> <testNode> <subNode/> </testNode>

Resultado :

This is text1 TEST_PARAMETER This is text2

ACTUALIZAR:

El OP ha proporcionado información más precisa que demuestra mi conjetura.

Ahora es obvio que el problema se debe al permitir que la plantilla incorporada de XSLT para el nodo del elemento se seleccione para wrapperNode . Esta plantilla, naturalmente, no conoce ningún parámetro y no utiliza el parámetro testParam ni pasa este parámetro. Por lo tanto, <xsl:apply-templates/> en la plantilla incorporada hace que la plantilla que coincida con testNode se seleccione sin pasarle ningún parámetro. Esto explica el comportamiento / resultado reportado.

Solución : la solución es especificar una plantilla que coincida con wrapperNode que acepte un parámetro llamado testParam y lo pase cuando aplique las plantillas:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" indent="yes"/> <xsl:template match="/"> <html> <body> <xsl:apply-templates> <xsl:with-param name="testParam" select="''TEST_PARAMETER''"/> </xsl:apply-templates> </body> </html> </xsl:template> <xsl:template match="testNode"> <xsl:param name="testParam" /> TEST1 <xsl:value-of select="$testParam" /> TEST2 </xsl:template> <xsl:template match="wrapperNode"> <xsl:param name="testParam" /> <xsl:apply-templates> <xsl:with-param name="testParam" select="$testParam"/> </xsl:apply-templates> </xsl:template> </xsl:stylesheet>

Ahora, cuando esta transformación se aplica en el documento XML proporcionado, se produce el resultado esperado :

<html> <body> TEST1 TEST_PARAMETER TEST2 </body> </html>


Sus etiquetas <html> y <body> no pueden aparecer donde están en una hoja de estilo XSL. Cuando los elimino, junto con las etiquetas de cierre y ejecuto esto en Oxygen / XML, obtengo la salida "deseada". Creo que quieres poner esas etiquetas DENTRO de la plantilla de nivel superior, en cuyo caso generaría la salida dentro de body etiquetas html y body .

¿Qué motor XSLT usaste que no se quejó de la hoja de estilo no válida?