2009-02-21 19 views
7

Tengo un archivo XML de entrada que necesito copiar 1: 1 en la salida, a excepción de un subelemento que contiene subelementos que deben ordenarse.Cómo ordenar un subelemento de XML con XSLT

<?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 pone los elementos "ContentItem" con el fin, 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.

Respuesta

7

Marcos Gravell es casi correcta - con un pequeño problema que crea dos <contents> elementos 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 correcto deseada:

<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> 

hacer la nota del siguiendo:

  1. El uso de la identity rule para copiar todos los nodos sin cambio.

  2. Cómo la plantilla de identidad se overriden con una plantilla específica que coincide con el elemento de contents

  3. 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 de el orden del documento de los nodos, seleccionado para el procesamiento.

0

Uso xsl: sort, ya sea con xsl: for-each o xsl: apply-templates

algo así como

<xsl:template match='/top/contents'> 
    <xsl:apply-templates select='contentitem'> 
    <xsl:sort select='id' data-type='number'/> 
    </xsl:apply-templates> 
</xsl:template> 

XSL múltiples: ordenar los elementos puede ser utilizado para múltiples claves de ordenación.

+0

en cuenta que no he escrito el elemento , ni ningún atributo en él ... –

+0

Esto no es una solución completa, en lugar centrado en cómo ordenar. – Richard

2

¿Qué tal: la solución de

<?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> 
Cuestiones relacionadas