XSLT对多个属性的值进行排序

Tor*_*uun 7 sorting xslt

我有一个巨大的XML格式的配置文件.系统不关心标签的顺序,但我们人类做的!(主要是为了版本比较的目的.)我已经收到了下面的XSLT,它运行良好,但我发现它还不够.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="*">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:apply-templates>
      <xsl:sort select="(@name, name())[1]"/>
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

我希望通过其name属性的值递归对所有标签进行排序(这有效!)但是因为该属性并不总是存在,所以它还必须按其他属性排序,其中任何属性可能存在于任何给定元素中,也可能不存在.

我对XSLT基本上没有理解,所以我正在试验.我已将上述内容攻入此内容,但它并没有按预期工作.其结果似乎与上述相同.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="*">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:apply-templates>
      <xsl:sort select="@name"/>
      <xsl:sort select="@row"      data-type="number"/>
      <xsl:sort select="@col"      data-type="number"/>
      <xsl:sort select="@sequence" data-type="number"/>
      <xsl:sort select="@tabindex" data-type="number"/>
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

我的数据看起来与此类似,问题是cell元素根本没有排序(在它们的grid组内),因为它们没有name属性.这就是为什么我想name在存在时扩展排序逻辑以使用属性,否则排序应该使用其他属性来完成tabindex.在任何给定的组中,可以假设存在相同的属性.

<sections>
  <section name="SomeList">
    <caption>
      <![CDATA[Candidates]]>
    </caption>
    ...
    <parameters>
      <parameter name="pageSize">
        <![CDATA[50]]>
      </parameter>
    </parameters>
    ... 
    <grid>
      <cell row="0" col="7" tabindex="9" colspan="10">
        <field name="Entered" />
      </cell>
    </grid>
  </section>
</sections>
Run Code Online (Sandbox Code Playgroud)

更新:
在Vincent的帮助下,我创建了一个适合我们目的的分类.这里是.

Vin*_*net 4

这是一个假设您的数据中没有任何混合内容的响应。它仅考虑前两个步骤(@name 和 @col),您可以适应进一步的步骤。也许可以使用递归命名模板重写它,该模板将排序参数列表作为输入。如果我的 XSLT 不适合您,您能否提供一个 XML 示例?

XSLT 2.0 示例:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
        <xsl:template match="*">
            <xsl:copy>
                <xsl:copy-of select="@*"/>
                <xsl:for-each-group select="*" group-by="if (exists(@name)) then @name else ''">
                    <xsl:sort select="current-grouping-key()" data-type="text"/>
                    <xsl:for-each-group select="current-group()" group-by="if (exists(@row)) then @row else -1">
                        <xsl:sort select="current-grouping-key()" data-type="number"/>
                        <xsl:apply-templates select="current-group()"/>
                    </xsl:for-each-group>
                </xsl:for-each-group>
            </xsl:copy>
        </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

请注意,代码在具有相同值的组上进行迭代,因此,如果元素上不存在属性,则这些元素将被分组在一起。

我将以下 XML 作为输入:

<?xml version="1.0" encoding="UTF-8"?>
<items>
    <item row="5" col="9"></item>
    <item name="d" row="20" col="12" tabindex="" sequence=""></item>
    <item row="1" col="5" ></item>
    <item name="d" row="5" col="6" ></item>
    <item name="a" row="7" col="8" ></item>
    <item name="s" row="1" col="5" ></item>
    <item name="c" row="5" col="9"></item>
    <item row="2" col="5" ></item>
    <item row="20" col="9"></item>
    <item row="0" col="9"></item>
    <item name="s" row="2" col="10" tabindex="" sequence=""></item>
    <item name="z" row="8" col="15" tabindex="" sequence=""></item>    
</items>
Run Code Online (Sandbox Code Playgroud)

我有以下结果:

<?xml version="1.0" encoding="UTF-8"?>
<items>
   <item row="0" col="9"/>
   <item row="1" col="5"/>
   <item row="2" col="5"/>
   <item row="5" col="9"/>
   <item row="20" col="9"/>
   <item name="a" row="7" col="8"/>
   <item name="c" row="5" col="9"/>
           <item name="d" row="5" col="6"/>
   <item name="d" row="20" col="12" tabindex="" sequence=""/>
   <item name="s" row="1" col="5"/>
   <item name="s" row="2" col="10" tabindex="" sequence=""/>
   <item name="z" row="8" col="15" tabindex="" sequence=""/>
</items>
Run Code Online (Sandbox Code Playgroud)