2011-06-13 11 views
7

He visto muchas publicaciones que hacen algo como esto y eso me hace sentir que esto es posible y solo estoy haciendo algo mal. He simplificado tanto como sea posible para tratar de averiguar por qué ocurre esto:Uso de la variable xsl para capturar la salida de la plantilla de llamada volviendo en blanco para mí

Heres mi xml (nada muy emocionante):

<?xml version="1.0" encoding="UTF-8"?> 
<REPORT> 

</REPORT> 

Aquí está mi XSL:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
    <xsl:template match="REPORT"> 
     <xsl:variable name="tryThisTemplate"> 
     <xsl:call-template name="TRY_THIS"/> 
     </xsl:variable> 
     <TEST1> 
     <xsl:call-template name="TRY_THIS"/> 
     </TEST1> 
     <TEST2> 
     <xsl:value-of disable-output-escaping="yes" select="$tryThisTemplate" /> 
     </TEST2> 
     <TEST3> 
     <xsl:value-of select="$tryThisTemplate" /> 
     </TEST3> 
    </xsl:template> 

    <xsl:template name="TRY_THIS"> 
     <MY_NODE desc="my description" /> 
    </xsl:template> 
</xsl:stylesheet> 

aquí es mi resultado:

<?xml version="1.0" encoding="utf-8"?> 
<TEST1> 
    <MY_NODE desc="my description"/> 
</TEST1> 
<TEST2></TEST2> 
<TEST3></TEST3> 

aquí está mi pregunta: ¿Cómo es que TEST2 y T EST3 no funciona. La variable $ tryThisTemplate parece estar en blanco. Estoy malentendiendo algo aquí. ¿Debo hacer esto de otra manera?

+0

Buena pregunta, +1. Vea mi respuesta para una explicación y solución completa. –

Respuesta

15

Aquí es la forma correcta de hacer esto (nota que el DOE no es necesario y debe evitarse):

<xsl:stylesheet 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="REPORT"> 
    <xsl:variable name="tryThisTemplate"> 
     <xsl:call-template name="TRY_THIS"/> 
    </xsl:variable> 
    <TEST1> 
     <xsl:call-template name="TRY_THIS"/> 
    </TEST1> 
    <TEST2> 
     <xsl:copy-of select="$tryThisTemplate" /> 
    </TEST2> 
    <TEST3> 
     <xsl:copy-of select="$tryThisTemplate" /> 
    </TEST3> 
</xsl:template> 

<xsl:template name="TRY_THIS"> 
    <MY_NODE desc="my description" /> 
</xsl:template> 
</xsl:stylesheet> 

cuando se aplica esta transformación en el documento XML proporcionado:

<REPORT> 

</REPORT> 

el resultado deseado se produce:

<TEST1> 
    <MY_NODE desc="my description"/> 
</TEST1> 
<TEST2> 
    <MY_NODE desc="my description"/> 
</TEST2> 
<TEST3> 
    <MY_NODE desc="my description"/> 
</TEST3> 

Explicación:<xsl:copy-of> copia (como su nombre lo indica) nodos. <xsl:value-of> muestra el valor de cadena de lo que sea que esté en su atributo select. El valor de cadena de un elemento es la concatenación (en orden de documento) de todos sus descendientes de nodo de texto. En su caso, el elemento no tiene descendientes de texto-nodo y, por lo tanto, <xsl:value-of> no genera nada.

+0

+1 buena explicación, y para recordar decir que desactivar-salida-escapar generalmente NO es la respuesta. – LarsH

+0

Muy buena explicación. Gracias por tomarse el tiempo para ayudarme a entender. – testing123

+0

@ testing123: De nada. –

2

variable $ tryThisTemplate parece estar en blanco

La variable que no es blanco, pero con xsl:value-of que están pidiendo los nodos de texto dentro de eso. Eso es "en blanco".

Por ejemplo, tratar con:

<TEST3> 
    <xsl:copy-of select="$tryThisTemplate" /> 
    </TEST3> 

Y verá aparecer mágicamente MY_NODE entre TEST3 :))

3

Sí, hay un malentendido. Si está intentando copiar la estructura de $tryThisTemplate a la salida, necesita usar <xsl:copy-of> en lugar de <xsl:value-of>. <xsl:value-of> muestra el valor de cadena de su argumento de selección, es decir, su contenido de texto, que en este caso es una cadena vacía.

0

la salida mi solución

aquí es mi plantilla (se conformó veriable)

<xsl:template name="author-name" match="string-name"> 
    <xsl:if test="fn[string-length(normalize-space()) > 0] or given-names[string-length(normalize-space()) > 0]"> 
     <xsl:apply-templates select="fn | given-names" mode="ascii"/> 
    </xsl:if> 
    <xsl:if test="sn[string-length(normalize-space()) > 0] or surname[string-length(normalize-space()) > 0]"> 
     <xsl:text> </xsl:text><xsl:apply-templates select="sn | surname" mode="ascii"/> 
    </xsl:if> 
    <xsl:if test="sn[string-length(normalize-space()) > 0] or suffix[string-length(normalize-space()) > 0]"> 
     <xsl:text> </xsl:text><xsl:apply-templates select="sn | suffix" mode="ascii"/> 
    </xsl:if> 
</xsl:template> 

y cuando lo uso en cualquier otra plantilla simplemente acabo de llamarlo como esto

<xsl:template match="string-name"> 
    <xsl:variable name="author"> 
     <xsl:call-template name="author-name"/> <!--here is the tricky part--> 
    </xsl:variable> 
    <span class="NLM_{name()}"> 
     <xsl:copy-of select="@id" /> 
     <xsl:value-of select="normalize-space($author)" /> 
    </span> 
</xsl:template> 

espero que esto te ayude

Cuestiones relacionadas