2012-06-23 8 views

Respuesta

35

El XPath expresión @* | node() selecciona el unión de nodos de atributo (@*) y todos los otros tipos de nodos XML (node()).

Es una abreviatura de attribute::* | child::node().

En XSLT, XPath es relativo al nodo contexto y el valor predeterminado selection axis es el eje child, por lo que la expresión

  • selecciona todos los atributos y los niños inmediatos del nodo de contexto (cuando se utiliza como una expresión select="...", por ejemplo en <xsl:apply-templates>)
  • partidos todos los nodos atributo-y otras independientemente del contexto (cuando se utiliza como match="" expresión en <xsl:template>): tenga en cuenta que existe una diferencia entre seleccionar nodos y hacer coincidirlos: el nodo contextual solo importa para la selección.

imaginar el siguiente nodo es el nodo de contexto:

<xml attr="value">[ 
    ]<child />[ 
    ]<!-- comment -->[ 
    ]<child> 
    <descendant /> 
    </child>[ 
]</xml> 

la expresión node() no sólo seleccionará ambos <child> nodos, pero también cuatro espacios en blanco de sólo los nodos de texto (representado por [ y ] en aras de visibilidad) y el comentario. El <descendant> no está seleccionado.

Una característica especial de XML es que los nodos de atributo son no hijos de los elementos a los que pertenecen (aunque el padre de un atributo es el elemento al que pertenece).

Esta relación asimétrica hace que sea necesario seleccionarlos por separado, de ahí el @*.

Coincide con cualquier nodo de atributo que pertenezca al nodo de contexto, por lo que también se seleccionará attr="value".

El | es el operador de unión XPath. Crea un nodo singe conjunto de dos conjuntos de nodos separados.

<xsl:apply-templates> encuentra el <xsl:template> apropiado para cada nodo seleccionado y lo ejecuta para ese nodo. Esta es la parte de coincidencia de plantilla que mencioné anteriormente.

+3

Excelente respuesta. Vale la pena enfatizar (si estoy en lo cierto) que 'node()' difiere de simplemente '*' en que, como dices, el primero también selecciona texto, comentarios y nodos de espacio en blanco. Esto puede tener implicaciones al usar 'position()'. Más sobre esto [aquí] (http://www.dpawson.co.uk/xsl/sect2/N6099.html). – Utkanos

+0

@Utkanos Sí, dije algo así debajo de mi código XML de muestra, pero no con tan explícitamente. – Tomalak

13

Para añadir a la excelente respuesta de Tomalak:

más ofthen uno vería <xsl:apply-template select="@*|node()"/> utilizado en una plantilla como ésta:

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

Esto se conoce como la plantilla identity rule o "identidad ".

Uno de los patrones más fundamentales y de gran alcance de diseño XSLT es el uso y primordial de la regla de identidad.

Si una transformación consiste únicamente en la regla de identidad, el resultado de la transformación es el documento XML de origen en sí; esta es la razón por la cual la plantilla se conoce como "la regla de identidad".

¿Por qué se produce este resultado?

La respuesta corta es: debido al modelo de procesamiento XSLT.

Una explicación más detallada debe comenzar desde la parte superior:

node() 

coincide con cualquier elemento, texto-nodo, comentario o instrucción de procesamiento. El documento (raíz) -nodo también se corresponde con node().

Podemos imaginar los nodos "hoja" de cualquier árbol de documentos - estos son los nodos que no tienen hijos a sí mismos como un texto-nodo, comentar y instrucción de procesamiento. Un elemento vacío también debe considerarse un nodo hoja.

La regla de identidad se selecciona inicialmente para la ejecución (aplicada) contra todos los nodos secundarios de los nodos del documento (estos son los elementos superiores individuales y cualquier comentario o hermanos de instrucciones de procesamiento que pueda tener). El nodo emparejado es poco profunda copiado y si es un nodo hoja no elemento, la instrucción <xsl:apply-templates select="node()|@*"/> no selecciona ningún nodo o atributos.

Si el nodo coincidente es un elemento, se copia poco a poco, la instrucción <xsl:apply-templates select="node()|@*"/> hace que la misma plantilla (ya que no hay ninguna otra plantilla en el código de transformación) se aplique contra cada uno de sus atributos y cada uno de sus Nodos de niños.

Esta es la recursión que impulsa el procesamiento de cada nodo del documento XML hasta que se alcanzan los nodos de hoja o atributos y en el que el lugar <xsl:apply-templates select="node()|@*"/> selecciona sin niños o atributo nodos.

5

Felicidades a @Tomalak por primera respuesta correcta. El tictac debe seguir su respuesta. Voy a agregar algunas aclaraciones a su respuesta.

Nota Una

... @ * | node() selecciona la unión de ...

The | El operador no solo devuelve la unión de los dos operandos, sino que ordena en orden de documento y elimina los duplicados. La parte de-dup no es relevante aquí porque no hay duplicados para eliminar, pero vale la pena mencionar la parte de clasificación. Una versión más correcta sería decir ...

... @ * | nodo() selecciona la unión, ordenados en orden de documento, de ...

Nota Dos

... y todos los demás tipos de nodos secundarios XML (nodo())

Esto es ampliamente cierto, pero es engañoso. Cuando la mayoría de las personas lee "nodos hijos XML", piensan en nodos secundarios en el sentido DOM. Pero esto no es lo que se está seleccionando. Solo se seleccionan nodos XDM. Para una ilustración, eche un vistazo al siguiente documento.

<?xml version="1.0" encoding="ISO-8859-1"?> 
<root-element my-attrib="myattrib-vaue" xmlns:hi="www.abc.com"><child-element /> 
abc&apos;def 
</root-element> 

Supongamos ahora que el elemento de contexto es el 'elemento raíz'. A un lector de la respuesta de Tomalak se le hace la pregunta: ¿qué se selecciona mediante "@ * | node()"? La implicación de la respuesta de Tomalak para aquellos que estén pensando el modelo DOM, sería que hay 6 cosas seleccionados:

  • El atributo mi-attrib
  • El atributo de nodo en el espacio (que es un verdadero atributo en DOM)
  • El elemento hijo nodo
  • El 'abc' mordió
  • La referencia de entidad
  • El 'def' bits.

Pero esto no es cierto en XSLT. Lo que en realidad es seleccionada ...

  • El atributo mi-attrib
  • El elemento hijo-nodo
  • El nodo de texto XDM, siendo el concatenar de nodos de texto 3 DOM como: "abc'def"

Así que una declaración más exacta sería ...

La expresión XPath @ * | node() selecciona la unión, ordenada en orden de documento, de (nodos de atributo del elemento de contexto y nodos secundarios XML del elemento de contexto en el sentido del XDM). El modelo XD ignora algunos tipos de nodos, como las definiciones de entidades, que están en el DOM, y los nodos DOM de texto contiguo se concatenan en un nodo de texto XDM.

Cuestiones relacionadas