基于值列表在XSLT中对XML进行排序

时间:2011-01-24 20:06:42

标签: xml xslt sorting

我想用XSL转换对一个XML文件进行排序。

<root>
   <element>
        <name>A</name>
   </element>
   <element>
        <name>B</name>
   </element>
   <element>
        <name>C</name>
   </element>
</root>

必须按以下名称列表进行排序:C,A,B,以便生成的XML为:

 <root>
       <element>
            <name>C</name>
       </element>
       <element>
            <name>A</name>
       </element>
       <element>
            <name>B</name>
       </element>
    </root>

显然,要排序的值列表应该是非常动态的(XSLT的参数,另一个XML文件......)。 知道如何在XSLT中做到这一点吗?

谢谢, 克里斯托夫

1 个答案:

答案 0 :(得分:9)

此转化

<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:param name="pSortingValues" select="'C,A,B'"/>
 <xsl:variable name="vSortingValues" select=
  "concat(',', $pSortingValues, ',')"/>

    <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="/*">
      <xsl:copy>
       <xsl:apply-templates select="@*"/>
       <xsl:apply-templates select="*">
        <xsl:sort data-type="number" select=
        "string-length(substring-before($vSortingValues,concat(',',name,',')))"/>
       </xsl:apply-templates>
      </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档

<root>
    <element>
        <name>A</name>
    </element>
    <element>
        <name>B</name>
    </element>
    <element>
        <name>C</name>
    </element>
</root>

生成想要的正确结果

<root>
   <element>
      <name>C</name>
   </element>
   <element>
      <name>A</name>
   </element>
   <element>
      <name>B</name>
   </element>
</root>

请注意

  1. 所需的排序值列表是pSortingValues全局参数,可以在转换外部提供。

  2. 标识规则用于“按原样”复制所有节点。

  3. 顶级元素的身份规则被覆盖。 top元素被部分复制,其属性被复制,然后模板应用于所有带有<xsl:sort>子指令的子元素,该指令指定要使用的确切排序键 - 如何在{{1值} pSortingValues孩子的名字是。

  4. 更新:正如@Alejandro所说,这:

    element

    可简化为:

            <xsl:sort data-type="number" select=
            "string-length(substring-before($vSortingValues,concat(',',name,',')))"/>