【问题标题】:Sorting XML in XSLT based on a list of values基于值列表在 XSLT 中对 XML 进行排序
【发布时间】:2011-06-14 18:27:33
【问题描述】:

我想使用 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。请参阅我的答案以获得完整而简短的解决方案,以及详尽的解释。

标签: xml xslt sorting


【解决方案1】:

这种转变

<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. 顶部元素的标识规则被覆盖。顶部元素被部分复制,它的属性被复制,然后模板被应用到所有子元素上,带有 &lt;xsl:sort&gt; 子指令,它指定要使用的确切排序键 - 如何在 pSortingValues 前面值element 孩子的名字是。

更新:正如@Alejandro 所指出的,这:

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

可以简化为:

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

【讨论】:

  • @Dimitre:+1 好答案。作为字符串数据类型,之前的子字符串也以相同的方式工作。
  • @Alejandro:谢谢。我使用substring-before()
  • @Dimitre:Ja!是的,我看到了。我的意思是没有fn:string-length() 也没有@data-type="number"
  • @Alejandro:你能详细解释一下吗?
  • @Dimitre:对不起,是的。就像herexsl:sort select="substring-before($vSortingValues,concat(',',name,','))" 就足够了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-21
  • 1970-01-01
  • 2019-03-31
相关资源
最近更新 更多