如何使用XSLT对XML的子元素进行排序

问题描述:

我有一个输入XML文件,我需要将1:1复制到输出,除了包含需要排序的子项目的一个子元素。如何使用XSLT对XML的子元素进行排序

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

我想XSL转换,它将在“contentitem”的元素,以便通过他们的“ID”元素进行排序。 所有其他标签,包括嵌套标签,都必须逐字复制。我已经尝试过使用xsl:copy,但是我得到了双重内容,或者什么都没有找到。

马克Gravell的解决方案几乎是正确 - 与创建两个嵌套<contents>要素中有轻微的问题。 所有提供答案的人请注意:请测试您的解决方案

这是一个正确的解决方案。这种转变

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

当在最初提供的XML文档应用:

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

产生想要的,正确的结果

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

请注意以下

  1. 使用该identity rule的复制所有节点没有改变。

  2. 身份模板如何重写与特定的模板contents元件

  3. 使用该<xsl:sort>指令来呈现特定的顺序应用模板的结果匹配,可能来自不同选择处理的节点的文档顺序。

使用xsl:排序与任何的xsl:for-每个或XSL:申请模板

喜欢的东西

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

多的xsl:排序元素可以被用于多个排序键。

+0

注意你没有写元素,也没有对任何属性... – 2009-02-21 12:01:31

如何:

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