2009-02-21 12 views
7

Ich habe eine XML-Eingabedatei, die ich 1: 1 in die Ausgabe kopieren muss, mit Ausnahme eines Unterelements, das Unterelemente enthält, die sortiert werden müssen.So sortieren Sie ein XML-Unterelement mit 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> 

würde ich eine XSL-Transformation wie die die „ContentItem“ Elemente um, sortiert nach ihrer „id“ Elemente setzt. Alle anderen Tags, auch verschachtelte, müssen wörtlich kopiert werden. Ich habe es schon mit xsl: copy versucht, aber entweder bekomme ich doppelte Inhalte oder es fällt etwas aus.

Antwort

7

Mark GRA-Lösung fast richtig ist - mit einem leichten Problem, das zwei verschachtelte <contents> Elemente erzeugt. Hinweis für alle, die Antworten geben: Testen Sie Ihre Lösungen!

Hier ist eine korrekte Lösung. Diese Transformation:

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

wenn auf dem ursprünglich bereitgestellten XML-Dokument angewendet:

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

erzeugt die gewünschte, korrekte Ergebnis:

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

der beachten Sie folgende:

  1. Die Verwendung des identity rule alle Knoten ohne Änderung zu kopieren.

  2. Wie die Identität Vorlage mit einer bestimmten Vorlage außer Kraft gesetzt wird passend zum contents Elemente

  3. Die Verwendung der <xsl:sort> Anweisung die Ergebnisse des Anwendens eine Vorlage in einer bestimmten Reihenfolge zu präsentieren, möglicherweise verschieden von die Dokumentenreihenfolge der Knoten, die für die Verarbeitung ausgewählt wurden.

0

Verwendung xsl: sort entweder mit xsl: for-each oder xsl: apply-templates

So etwas wie

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

mehrere xsl: sort Elemente können für mehrere Sortierschlüssel verwendet werden.

+0

Hinweis Sie haben nicht das Element geschrieben, noch irgendwelche Attribute drauf ... –

+0

Dies ist keine vollständige Lösung, stattdessen darauf konzentriert, wie zu sortieren. – Richard

2

Wie wäre:

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