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

时间:2009-02-21 11:47:38

标签: xml xslt sorting

我有一个输入XML文件,我需要将1:1复制到输出中,除了一个包含需要排序的子项的子元素。

<?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 Transformation,它将“contentitem”元素按顺序排列,按其“id”元素排序。 必须逐字复制所有其他标记,包括嵌套标记。我已经尝试过使用xsl:copy,但要么我得到了双重内容,要么结果丢失了。

3 个答案:

答案 0 :(得分:7)

Mark 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>指令来显示以特定顺序应用模板的结果,可能与选择进行处理的节点的文档顺序不同。

答案 1 :(得分:2)

怎么样:

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

答案 2 :(得分:0)

使用xsl:sort与xsl:for-each或xsl:apply-templates

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

多个xsl:sort元素可用于多个排序键。