2009-12-29 7 views
21

Estoy confundido acerca de la declaración de la plantilla de aplicación XSLT. Por ejemplo, aquí en w3school.XSLT plantilla de aplicación pregunta

http://www.w3schools.com/xsl/xsl_apply_templates.asp

Para las declaraciones,

<xsl:template match="/"> 
    <html> 
    <body> 
    <h2>My CD Collection</h2> 
    <xsl:apply-templates/> 
    </body> 
    </html> 
</xsl:template> 

mis confusiones son,

(1) ¿cuál es la función de la <xsl:apply-templates/>? No contiene ninguna plantilla específica para llamar. Creo que coincidirá (devuelve) con todos los elementos secundarios del elemento actual (no se devolverá el hijo no directo del nodo actual, el nodo actual es el nodo raíz), ¿no estoy seguro de si estoy en lo cierto?

(2) después de que todos los nodos coincidentes se devuelvan en (1), ¿cuál es el siguiente paso que hará el procesador XSLT?

(3) en esta muestra específica, ¿el nodo raíz es catálogo u otro nivel superior de raíz? ¿y por qué?

gracias de antemano, George

Respuesta

47

Algunas cosas que harán que la comprensión de las respuestas que obtenga más fácil:

En primer lugar, nodos y elementos no son la misma cosa. Los elementos son nodos, pero los nodos no son necesariamente elementos. A menudo encuentras personas que usan los términos indistintamente. En realidad, hay cuatro tipos de nodos en XML: elementos, nodos de texto, instrucciones de procesamiento y comentarios. (Los atributos no son realmente nodos, a los que llegaré en un segundo.)

En XSLT, la raíz de un documento XML no es su elemento de nivel superior; la raíz es una abstracción que realmente no existe. El elemento de nivel superior es un elemento secundario de la raíz.Por ejemplo, aquí hay un documento XML bien formado cuya raíz tiene cinco nodos secundarios, incluyendo el elemento de nivel superior:

<?xml-stylesheet href="mystyle.css" type="text/css"?> 
<!-- this is a perfectly legitimate XML document --> 
<top_level_element/> 

Cinco? Parece que solo hay tres. Creo que te dejaré descubrir cuáles son los otros dos tú mismo. Sugerencia: en realidad podría haber siete nodos en ese ejemplo.

La expresión XPath / encuentra la raíz del documento, no el elemento de nivel superior. En el caso anterior, para buscar el elemento de nivel superior, usaría /top_level_element o /*. (Siempre es seguro usar /* para encontrar el elemento de nivel superior, ya que la raíz del documento debe tener un elemento único secundario.)

Armados con ese conocimiento, veamos qué hace apply-templates. Básicamente realiza un proceso de dos pasos: Primero, construye un conjunto de nodos. Luego, y para cada uno, encuentra una plantilla coincidente (de entre las plantillas en el archivo XSLT) y aplica la plantilla a ella. Como observó en uno de sus comentarios, es conceptualmente muy similar a un ciclo.

El atributo select se utiliza en el primer paso. Proporciona una expresión XPath que se usa para construir el conjunto de nodos al que va a aplicar plantillas. Si no se proporciona el atributo select, la lista que crea es todos secundarios del nodo de contexto. (El "nodo de contexto" es el nodo al que se está aplicando la plantilla actual).

El atributo match en los elementos template se usa en el segundo paso. El procesador de hojas de estilo encuentra todas las plantillas cuyo atributo match coincide con el nodo al que intenta aplicar las plantillas. Si encuentra más de uno, selecciona el más específico que pueda, p. dado estas plantillas:

<xsl:template match="*"/> 
<xsl:template match="foo"/> 
<xsl:template match="foo[bar]"/> 

un elemento de foo con un elemento de bar niño será igualada por la tercera, un elemento de foo sin bar será igualado por el segundo, y un elemento de baz será igualada por la primera. (El método actual que utiliza XSLT se define here, en la práctica, he estado usando XSLT durante casi una década y nunca una vez he necesitado saber específicamente cómo funciona, aunque es interesante.)

Si no encuentra una coincidencia, se utilizará la plantilla por defecto incorporado para el tipo de nodo - básicamente, se puede asumir que cualquier transformación XSLT contiene implícitamente estas plantillas:

<xsl:template match="*"> 
    <xsl:apply-templates/> 
</xsl:template> 

<xsl:template match="text()"> 
    <xsl:copy/> 
</xsl:template> 

<xsl:template match="processing-instruction() | comment() | @*"/> 

armado con todo este conocimiento, ahora puede comprender la transformación de identidad:

<xsl:template match="node() | @*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node() | @*"/> 
    </xsl:copy> 
</xsl:template> 

Eso coincide con cualquier nodo o atributo (tenga en cuenta que los atributos no son nodos, por lo que se necesita @*), lo copia y luego aplica plantillas a todos sus nodos y atributos secundarios. (Solo la raíz del documento y los elementos tendrán nodos secundarios, y solo los elementos tendrán atributos). Dado que es la única plantilla en la transformación y coincide con todos los nodos y atributos, se aplica a todos los nodos y atributos secundarios. Por lo tanto, copia todo en el árbol fuente al árbol de salida.

Si se agrega esta plantilla para la identificación transformar:

<xsl:template match="foo"/> 

ahora tiene una transformación que copias cada nodo en el árbol de fuentes exceptofoo elementos - que segundo encaja foo elementos (el primero también lo hace, pero dado que el segundo atributo match es más específico, es el que XSLT elige) y no hace nada con ellos.

Teniendo en cuenta todo esto, las respuestas a sus preguntas específicas:

  1. <xsl:apply-templates> aplica las plantillas a los hijos del nodo de contexto.

  2. Los nodos coincidentes no se "devuelven" en el paso 1; el procesador XSLT encuentra una plantilla para cada uno y la aplica.

  3. En este ejemplo, el nodo de contexto es la raíz del documento, un nodo abstracto que el elemento de nivel superior y cualquier comentario o instrucciones de procesamiento fuera de él son los secundarios de.

+0

La declaración "Los atributos no son realmente nodos" es incorrecta. Los atributos son nodos, pero los atributos no son elementos secundarios del elemento. Para más detalles, mira mi respuesta a continuación. ejecuta solo plantillas para niños (axis child: :) pero no para atributos (axis attribute: :) –

1

xsl: apply-templates dirige el motor XSLT para que coincida con los subnodos actuales documentos de origen contra las plantillas de hojas de estilo para su posterior procesamiento.

+0

"coincide con los subnodos actuales del documento de origen" - en la muestra de w3school, ¿cuáles son los "subnodos de documento fuente actuales"? ¿Y a qué plantillas definidas en el archivo xslt se buscarán para buscar "subnodos de documentos de origen actuales"? – George2

+1

Dado que solo la raíz se ha emparejado hasta ahora, sería todos los nodos de cd. Y todas las plantillas en el ejemplo serían candidatas para emparejar. –

1

1) <xsl:apply-templates/> llama a los cruces por todos los subnodos (secundarios) y llama a la plantilla correspondiente, si la hay.

2) Después de que todos los nodos se hacen coincidir las líneas siguientes son de salida que en este caso son

</body> 
</html> 

3) En el catálogo ejemplo es el nodo raíz.

+0

1.Para 1, ¿puedo entender que se implementa en un bucle de dos capas (bucle externo + bucle interno)? El bucle externo es subnodos foreach, y el bucle interno es para cada plantilla definida en el archivo xslt actual (es decir, para cada subnodos, el motor de procesamiento intentará buscar la plantilla coincidente definida en el archivo xslt actual). 2. Si se encuentra más de una plantilla emparejada, ¿qué sucederá? – George2

+1

¿Puedes dar un ejemplo donde más de una plantilla puede coincidir con un nodo? Por lo que sé, sería un error xslt y tu xslt no compilará en ese caso. –

3
  1. intentará encontrar una plantilla que coincida con el nodo actual y sus hijos.
  2. Después de todos los nodos emparejados son devueltos, el procesador XSL voluntad de salida esas etiquetas de cierre (es decir </body> y </html>)
  3. hay un nodo raíz, justo antes de catálogo, emparejado por "/"

EDIT: Un ejemplo para aclarar 1.; consideran your provided sample:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:template match="/"> 
     Here we're at "root" node, just before "catalog" element.<br /> 
     Let's enumerate this child nodes: 
     <ul> 
     <xsl:for-each select="*"> 
      <li><xsl:value-of select="name()" /></li> 
     </xsl:for-each> 
     </ul> 
     <!-- Now, process "catalog" and ALL his child nodes --> 
     <xsl:apply-templates/> 
    </xsl:template> 

    <xsl:template match="cd"> 
     <p> 
     <!-- Find a template ONLY for title element --> 
     <xsl:apply-templates select="title"/> 
     <xsl:apply-templates select="artist"/> 
     </p> 
    </xsl:template> 
</xsl:stylesheet> 
+0

"intentará encontrar una plantilla que coincida con los nodos actuales": ¿nodo actual o nodos actuales? ¿Y a qué plantillas se buscará para que coincida? Todo en el archivo xslt o? – George2

+0

"etiquetas de cierre": ¿qué es la etiqueta de cierre? ¿Podría describir en otras palabras, por favor? – George2

0
  • elemento XML tiene niños o atributos. Para el XML siguiente, elemento libro tiene niño :: autor (poco autor) y atributo :: primera (poco @first)

    <?xml version="1.0" encoding="UTF-8"?> <book> <author first="tom">Smith</author> </book>

  • XSL: aplicar -templates significa ejecutar plantillas para todos los elementos secundarios del nodo coincidente,, por lo que para la plantilla siguiente, ejecutar plantilla para autor, pero no para @firs t.

<xsl:template match="book"> <xsl:apply-templates/> </xsl:template>

  • texto() nodo Smith es un hijo del elemento autor, por lo xsl: apply-templates llamarán plantilla para el texto () nodo:

<xsl:template match="author"> <xsl:apply-templates/> </xsl:template>

Cuestiones relacionadas