online - xslt sap
Diferencia entre: child:: node() y child::* (2)
Acabo de escribir un XSLT que no funcionó al principio.
Tuve que cambiar el nombre de todos los hijos de <Recordset>
a <C>
:
<?xml version="1.0" encoding="utf-8"?>
<Record>
<Recordset>
<company>102</company>
<store>1801</store>
....
</Recordset>
<Recordset>
....
</Recordset>
</Record>
Usé el siguiente XSLT:
<xsl:template match="Record/Recordset/child::*">
<xsl:element name="C">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
Funciona y cambia el nombre de todos los elementos secundarios de <Recordset>
a <C>
. Pero primero mi coincidencia en la plantilla se veía así:
<xsl:template match="Record/Recordset/child::node()">
Mi idea era que cada elemento secundario de <Recordset>
es un nodo, por lo que node()
sería apropiado. Funcionó también pero insertó una <C/>
extra para cada niño.
¿Cuál es la diferencia entre child::node()
y child::*
?
Para ampliar la respuesta de lwburk, si su XML se ve así:
<A>
<B/>
<C/>
<D/>
</A>
Entonces, el elemento A tiene 7 nodos secundarios; tres de ellos son elementos, cuatro son nodos de texto. La expresión child::node()
coincide con los 7, mientras que child::*
solo coincide con los elementos.
child::node()
coincide con cualquier nodo que no sea un nodo de atributo, nodo de espacio de nombres o nodo de documento. Eso significa que no coincide con las instrucciones de procesamiento, los comentarios y los nodos de texto.
child::*
coincide solo con elementos.
Ver la sección 5.5.3 de la especificación:
El patrón node () coincide con todos los nodos seleccionados por la expresión raíz (.) // (child-or-top :: node ()), es decir, todos los elementos, texto, comentario y nodos de instrucción de procesamiento, independientemente de que tener un padre No coincide con los nodos de atributo o de espacio de nombres porque la expresión no selecciona los nodos que utilizan el atributo o los ejes del espacio de nombres. No coincide con los nodos de documento porque, por razones de compatibilidad con versiones anteriores, el eje secundario o superior no coincide con un nodo de documento.
Actualización: la respuesta de Michael inspiró la siguiente hoja de estilo. Úselo para probar los tipos de nodos a medida que se procesan:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/|node()">
<xsl:call-template name="type" />
<xsl:text> [ </xsl:text>
<xsl:value-of select="." />
<xsl:text> </xsl:text>
<xsl:apply-templates select="node()" />
<xsl:text> ] </xsl:text>
</xsl:template>
<xsl:template name="type">
<xsl:choose>
<xsl:when test="count(.|/)=1">
<xsl:text>Root</xsl:text>
</xsl:when>
<xsl:when test="self::*">
<xsl:text>Element </xsl:text>
<xsl:value-of select="name()" />
</xsl:when>
<xsl:when test="self::text()">
<xsl:text>Text</xsl:text>
</xsl:when>
<xsl:when test="self::comment()">
<xsl:text>Comment</xsl:text>
</xsl:when>
<xsl:when test="self::processing-instruction()">
<xsl:text>PI</xsl:text>
</xsl:when>
<xsl:when test="count(.|../@*)=count(../@*)">
<xsl:text>Attribute</xsl:text>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Modifique lo que coincide / seleccionado para probar otros patrones. Por ejemplo, la siguiente entrada:
<A attr="test" other="val">
<B/>
<C>some value</C>
<!-- a comment -->
<D/>
</A>
Produce el siguiente resultado:
Root [
some value
Element A [
some value
Text [
] Element B [
] Text [
] Element C [ some value
Text [ some value
] ] Text [
] Comment [ a comment
] Text [
] Element D [
] Text [
] ] ]
Un agradecimiento especial a esta página por iniciarme en las pruebas de tipo de nodo. (Es especialmente apropiado que una de las respuestas de Michael de hace más de seis años aparezca allí también).