Respuestas:
<xsl:call-template>
es un equivalente cercano a llamar a una función en un lenguaje de programación tradicional.
Puede definir funciones en XSLT, como esta sencilla que genera una cadena.
<xsl:template name="dosomething">
<xsl:text>A function that does something</xsl:text>
</xsl:template>
Esta función se puede llamar a través de <xsl:call-template name="dosomething">
.
<xsl:apply-templates>
es un poco diferente y en él está el poder real de XSLT: toma cualquier número de nodos XML (lo que sea que defina en el select
atributo), los itera ( esto es importante: ¡las plantillas de aplicación funcionan como un bucle! ) y encuentra plantillas coincidentes para ellos:
<!-- sample XML snippet -->
<xml>
<foo /><bar /><baz />
</xml>
<!-- sample XSLT snippet -->
<xsl:template match="xml">
<xsl:apply-templates select="*" /> <!-- three nodes selected here -->
</xsl:template>
<xsl:template match="foo"> <!-- will be called once -->
<xsl:text>foo element encountered</xsl:text>
</xsl:template>
<xsl:template match="*"> <!-- will be called twice -->
<xsl:text>other element countered</xsl:text>
</xsl:template>
De esta manera, cede un poco de control al procesador XSLT; no es usted quien decide a dónde va el flujo del programa, sino que el procesador lo hace al encontrar la coincidencia más adecuada para el nodo que está procesando actualmente.
Si varias plantillas pueden coincidir con un nodo, gana la que tenga la expresión de coincidencia más específica. Si existe más de una plantilla coincidente con la misma especificidad, la última declarada gana.
Puede concentrarse más en desarrollar plantillas y necesitar menos tiempo para hacer "plomería". Sus programas se volverán más potentes y modularizados, menos anidados y más rápidos (ya que los procesadores XSLT están optimizados para la coincidencia de plantillas).
Un concepto para entender con XSLT es el de "nodo actual". Con <xsl:apply-templates>
el nodo actual avanza con cada iteración, mientras <xsl:call-template>
que no cambia el nodo actual. Es decir, .
dentro de una plantilla llamada se refiere al mismo nodo que .
en la plantilla de llamada. Este no es el caso de las plantillas de aplicación.
Ésta es la diferencia básica. Hay algunos otros aspectos de las plantillas que afectan su comportamiento: sus mode
y priority
, el hecho de que las plantillas pueden tener una name
y una match
. También influye si la plantilla se ha importado ( <xsl:import>
) o no. Estos son usos avanzados y puedes lidiar con ellos cuando llegues allí.
<xsl:apply-templates>
comporta como un bucle. Las diferencias de implementación en el extremo del procesador XSLT no me afectarán como programador XSLT, el resultado es absolutamente el mismo para implementaciones paralelas e iterativas por igual. Pero para un novato de XSLT con un trasfondo imperativo, es útil visualizarlo <xsl:apply-templates>
como una especie de bucle para cada ciclo, incluso si, técnicamente, no lo es.
Para agregar a la buena respuesta de @Tomalak:
Aquí hay algunas diferencias importantes no mencionadas :
xsl:apply-templates
es mucho más rico y profundo que xsl:call-templates
e incluso de xsl:for-each
, simplemente porque no sabemos qué código se aplicará en los nodos de la selección; en el caso general, este código será diferente para los diferentes nodos de la lista de nodos.
El código que se aplicará puede ser escrito mucho después de que se haya escrito la xsl:apply template
s y por personas que no conozcan al autor original.
La implementación de funciones de orden superior (HOF) de la biblioteca FXSL en XSLT no sería posible si XSLT no tuviera la <xsl:apply-templates>
instrucción.
Resumen : Las plantillas y la <xsl:apply-templates>
instrucción muestran cómo XSLT implementa y trata el polimorfismo.
Referencia : Vea todo este hilo: http://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/200411/msg00546.html
xsl:apply-templates
se utiliza normalmente (pero no necesariamente) para procesar todos o un subconjunto de los hijos del nodo actual con todas las plantillas aplicables. Esto admite la recursividad de la aplicación XSLT que coincide con la (posible) recursividad del XML procesado.
xsl:call-template
por otro lado, se parece mucho más a una llamada de función normal. Ejecuta exactamente una plantilla (con nombre), generalmente con uno o más parámetros.
Entonces lo uso xsl:apply-templates
si quiero interceptar el procesamiento de un nodo interesante y (generalmente) inyectar algo en el flujo de salida. Un ejemplo típico (simplificado) sería
<xsl:template match="foo">
<bar>
<xsl:apply-templates/>
</bar>
</xsl:template>
mientras que con xsl:call-template
normalmente resuelvo problemas como agregar el texto de algunos subnodos juntos, transformar conjuntos de nodos seleccionados en texto u otros conjuntos de nodos y cosas por el estilo, cualquier cosa para la que escribiría una función especializada y reutilizable.
Como comentario adicional al texto específico de su pregunta:
<xsl:call-template name="nodes"/>
Esto llama a una plantilla que se llama 'nodos':
<xsl:template name="nodes">...</xsl:template>
Esta es una semántica diferente a:
<xsl:apply-templates select="nodes"/>
... que aplica todas las plantillas a todos los hijos de su nodo XML actual cuyo nombre es 'nodos'.
De hecho, la funcionalidad es similar (aparte de la semántica de llamada, donde se call-template
requiere un name
atributo y una plantilla de nombres correspondiente).
Sin embargo, el analizador no se ejecutará de la misma forma.
Desde MSDN :
A diferencia
<xsl:apply-templates>
,<xsl:call-template>
no cambia el nodo actual ni la lista de nodos actual.
<xsl:apply-templates>
deba implementarse como un bucle; por el contrario, puede implementarse en paralelo, porque las diferentes aplicaciones en los diferentes nodos de la lista de nodos son absolutamente independientes entre sí.