2010-09-19 10 views
7

¿Está bien pasar XML a una plantilla XSL a través de un parámetro? Por ejemplo, a continuación tengo la plantilla body llamada plantilla test1 que pasa algo de XML a través del parámetro var1. entonces trato de caminar hasta el nodo a usando XPathXSL, utilizando XML como parámetro para la plantilla

<xsl:template name="test1"> 
    <xsl:param name="var1" /> 
    <fo:block> 
     <xsl:value-of select="$var1/a" /> 
    </fo:block> 
</xsl:template> 

<xsl:template name="body"> 
    <xsl:call-template name="test1"> 
     <xsl:with-param name="var1" > 
      <a>foo</a> 
     </xsl:with-param> 
    </xsl:call-template> 
</xsl:template> 

El problema es que esto hace que mi intérprete XSL para fallar con un mensaje de error inútil. Me veo obligado a utilizar un sistema de proveedor de código cerrado para generar documentos, por lo que no puedo depurarlo. Pero antes de investigarlo más, estoy buscando la confirmación de que este es un uso válido de XSL.

+1

Buena pregunta (+1). Vea mi respuesta para una explicación y solución detallada. –

Respuesta

14
<xsl:template name="body"> 
    <xsl:call-template name="test1"> 
     <xsl:with-param name="var1" > 
      <a>foo</a> 
     </xsl:with-param> 
    </xsl:call-template> 
</xsl:template> 

El parámetro $var1 pasado a la plantilla es difícilmente utilizable en XSLT 1.0/XPath 1.0 debido a la RTF infame (resultado-Tree Fragmento) tipo.

Desde el W3C XSLT 1.0 spec:.

11,1 Resultados Fragmentos árbol

variables introducen un tipo de datos adicional en el lenguaje de expresión. Este tipo de datos adicional se llama resultado fragmento de árbol. Una variable puede vincularse a un fragmento de árbol de resultados en lugar de uno de los cuatro tipos de datos XPath básicos (cadena, número, booleano, conjunto de nodos). Un fragmento de árbol de resultado representa un fragmento del árbol de resultados. Un resultado fragmento de árbol se trata de manera equivalente a un conjunto de nodos que contiene solo un nodo raíz único . Sin embargo, las operaciones permitidas en un árbol de resultados son un subconjunto de aquellas permitidas en un conjunto de nodos. Se permite Una operación en un fragmento de árbol resultado sólo si esa operación sería permitida en una cadena (la operación en la cadena puede implicar primero la conversión de la cadena en un número o boolean). En particular, no está permitido utilizar los operadores /, //, y [] en los fragmentos del árbol de resultados . Cuando se lleva a cabo una operación permitida en un fragmento del árbol de resultados , se realiza exactamente como en el conjunto de nodos equivalente.

Cuando un fragmento de árbol resultado se copia en el árbol de resultado (ver [11.3 Utilizando valores de variables y parámetros con xsl: copy-de]), entonces todos los nodos que son hijos del nodo raíz en el conjunto de nodos equivalente se agrega en la secuencia al árbol de resultados.

expresiones sólo pueden valores del fragmento de árbol de resultados tipo de retorno por referencia a variables de tipo de resultado árbol fragmento o llamando a la extensión funciones que devuelven un árbol de resultados fragmento o conseguir una propiedad del sistema cuyo valor es un fragmento de árbol de resultados .

Para eludir esta decisión de diseño agobiante, casi cada procesador XSLT tiene su propia función de extensión, por lo general llamado xxx:node-set() donde el prefijo xxx debe estar enlazado a un espacio de nombres definido por el proveedor.

Solución:

encontrar exactamente lo que es el nombre de esta función de extensión ofrecido por el proveedor de procesador XSLT.

O, si su procesador XSLT apoya EXSLT, utilice la función de extensión exsl:node-set() como se define por EXSLT.

Éstos son algunos espacios de nombres específicos del proveedor:

MSXML y .NET XslCompiledTransform, XslCompiledTransform:

xmlns:vendor="urn:schemas-microsoft-com:xslt" 

Xalan (nota, el nombre de la función es: xxx:nodeset()):

xmlns:vendor="http://xml.apache.org/xalan" 

Saxofón en (6.x):

xmlns:vendor="http://icl.com/saxon" 

Altova:

xmlns:vendor="http://www.altova.com/xslt-extensions" 

Todos los procesadores XSLT que implementan EXSLT:

xmlns:vendor="http://exslt.org/common" 

En caso de que el cuerpo de el <xsl:param> no es dinámico aliado construidos, se puede evitar la función

xxx:node-set() de la siguiente manera:

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

<xsl:variable name="vrtfparamXML"> 
    <a> 
    <b>foo</b> 
    </a> 
</xsl:variable> 

<xsl:variable name="vparamXML" select= 
"document('')/*/xsl:variable 
       [@name='vrtfparamXML']/*"/> 

<xsl:template match="/"> 
    <xsl:copy-of select="$vparamXML/b"/> 
</xsl:template> 
</xsl:stylesheet> 

cuando se aplica esta transformación en cualquier documento XML (no se utiliza), el resultado es el hijo deseado de la RTF :

<b xmlns:xsl="http://www.w3.org/1999/XSL/Transform">foo</b> 

Nota: XSLT 2.0/2.0 XPath se deshizo del "tipo" RTF y hay uno no tendrá ningún problema para acceder a los árboles y temporales navegándolos utilizando toda la potencia de XPath 2.0

+2

Agradezco su minuciosa respuesta Dimitre. Me comunicaré con mi proveedor y veré si tal extensión es posible. – Mike

+0

@Mike: De nada. Para su conveniencia, edité mi respuesta para proporcionar los espacios de nombres que utilizan algunos de los procesadores XSLT. –

+1

Encontré que mi procesador incluye soporte para exsl. Gracias de nuevo por su ayuda, esto me permitirá mejorar en gran medida mi diseño – Mike

Cuestiones relacionadas