XSLT对多个属性的值进行排序 [英] XSLT to sort on value of multiple attributes

查看:87
本文介绍了XSLT对多个属性的值进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个巨大的XML格式的配置文件.该系统并不关心标签的顺序,但是我们人类却愿意! (主要用于版本比较.)我已经收到下面的XSLT效果很好,但是我发现这还不够.

I have a huge XML-formatted configuration file. The system doesn't care about the order of tags, but we humans do! (Primarily for the purpose of version comparisons.) I already received the XSLT below which works well, but I've discovered that it's not quite enough.

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

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

I want to sort all tags recursively by the value of their name attribute (this works!) but because the attribute is not always present, it must also sort by further attributes, any of which may or may not be present in any given element.

我对XSLT的了解基本上为零,所以我正在尝试.我已经将上面的内容破解了,但是并不能按需工作.结果似乎与上述相同.

I have basically zero understanding of XSLT so I'm experimenting. I've hacked the above into this, but it doesn't work as desired. The result of this seems to be identical to the above.

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

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

My data looks similar to this, and the problem is that the cell elements are not sorted at all (within their grid group) because they have no name attribute. This is why I'd like to extend the sorting logic to use name attribute when present, else the sort should be done using additional attributes like tabindex. Within any given group, the same attributes can be assumed to be present.

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

更新:
在Vincent的非常出色的帮助下,我创建了一种足以满足我们目的的分类方法. 在这里.

Update:
With Vincent's very good help, I've created a sorting that works well enough for our purposes. Here it is.

推荐答案

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

It is a response that assumes that you don't have any mixed content in your data. It only takes into account the two first steps (@name and @col), you can adapt for further steps. Maybe it can be rewritten with a recursive named template that takes the list of your sorting param as input. Could you provide an XML sample if my XSLT don't work for you.

XSLT 2.0示例:

XSLT 2.0 sample :

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

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

Note that the code iterates on a group with same values, so that if an attribute is not present on elements, the elements are grouped together.

我将以下XML作为输入:

I take as Input the following 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>

我得到以下结果:

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

这篇关于XSLT对多个属性的值进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆