xml - tutorial - xslt editor
Cómo ordenar un subelemento de XML con XSLT (3)
Tengo un archivo XML de entrada que necesito copiar 1: 1 a la salida, a excepción de un subelemento que contiene subelementos que deben ordenarse.
<?xml version="1.0"?>
<top>
<elementA />
<elementB />
<contents>
<contentitem>
<id>3</id>
<moretags1 />
<moretags2 />
</contentitem>
<contentitem>
<id>2</id>
<moretags1 />
<moretags2 />
</contentitem>
<contentitem>
<id>1</id>
<moretags1 />
<moretags2 />
</contentitem>
</contents>
</top>
Me gustaría una Transformación XSL que ponga en orden los elementos "contentitem", ordenados por sus elementos "id". Todas las demás etiquetas, incluidas las anidadas, deben copiarse textualmente. Ya probé con xsl: copy, pero o bien obtengo doble contenido o algo falta.
Qué tal si:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/top/contents">
<contents>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="contentitem">
<xsl:sort data-type="number" select="id"/>
</xsl:apply-templates>
</xsl:copy>
</contents>
</xsl:template>
</xsl:stylesheet>
Use xsl: sort con xsl: for-each o xsl: apply-templates
Algo como
<xsl:template match=''/top/contents''>
<xsl:apply-templates select=''contentitem''>
<xsl:sort select=''id'' data-type=''number''/>
</xsl:apply-templates>
</xsl:template>
Múltiples elementos xsl: sort pueden ser usados para múltiples claves de clasificación.
La solución de Mark Gravell es casi correcta , con un ligero problema que crea dos elementos <contents>
anidados. Nota para todos los que proporcionan respuestas: ¡Pon a prueba tus soluciones !
Aquí hay una solución correcta. Esta transformación :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<!-- -->
<xsl:strip-space elements="*"/>
<!-- -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- -->
<xsl:template match="contents">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="contentitem">
<xsl:sort select="id" data-type="number"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
cuando se aplica en el documento XML proporcionado originalmente :
<top>
<elementA />
<elementB />
<contents>
<contentitem>
<id>3</id>
<moretags1 />
<moretags2 />
</contentitem>
<contentitem>
<id>2</id>
<moretags1 />
<moretags2 />
</contentitem>
<contentitem>
<id>1</id>
<moretags1 />
<moretags2 />
</contentitem>
</contents>
</top>
produce el resultado deseado y correcto :
<top>
<elementA/>
<elementB/>
<contents>
<contentitem>
<id>1</id>
<moretags1/>
<moretags2/>
</contentitem>
<contentitem>
<id>2</id>
<moretags1/>
<moretags2/>
</contentitem>
<contentitem>
<id>3</id>
<moretags1/>
<moretags2/>
</contentitem>
</contents>
</top>
Tenga en cuenta lo siguiente :
El uso de la regla de identidad para copiar todos los nodos sin cambios.
Cómo se invalida la plantilla de identidad con una plantilla específica que coincide con el elemento de
contents
El uso de la instrucción
<xsl:sort>
para presentar los resultados de la aplicación de una plantilla en un orden específico, posiblemente diferente del orden de los nodos de los documentos, seleccionado para su procesamiento.