按xml字母顺序对数据进行排序 [英] Sort data in the xml alphabetical order

查看:44
本文介绍了按xml字母顺序对数据进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

输入 XML :

<?xml version="1.0" encoding="utf-8" ?>
<infoset>
  <info>
    <title>Bill</title>
    <group>
      <code>state</code>
    </group>
  </info>
  <info>
    <title>Auto</title>
    <group>
      <code>state</code>
    </group>
  </info>
  <info>
    <title>Auto2</title>
  </info>
  <info>
    <title>Auto3</title>
  </info>
  <info>
    <title>Auto5</title>
  </info>
  <info>
    <title>Certificate</title>
    <group>
      <code>Auto4</code>
    </group>
  </info>
  </infoset>

预期输出:

A

Auto2
Auto3
Auto4
   Certificate
Auto5

S
state
   Auto
   Bill

我需要按字母顺序排列标题和代码.如果信息包含组,则磁贴应位于组下.我使用的是visual studio2010、xslt1.0处理器和xml编辑器.

I need to arrange the title and code in alphabetical order.If the info has group the tile should come under the group. I am using visual studio2010 , xslt1.0 Processor and xml editor.

推荐答案

在 XSLT 中排序非常简单.您实际上真正需要知道的是如何分组"项目.正如 Michael Kay 评论的那样,这在 XSLT 2.0 中比在 XSLT 1.0 中容易得多.在 XSLT 1.0 中,您倾向于使用 Muenchian Grouping 方法,这在您第一次看到时会让人感到困惑,但通常是最有效的方法.

Sorting in XSLT is straight-forward. What you are actually really needing to know is how to 'group' items. As Michael Kay commented, this is much easier in XSLT 2.0 than in XSLT 1.0. In XSLT 1.0 you tend to use the Muenchian Grouping method, which appears confusing when you first see it, but is generally the most efficient way of doing it.

从输出的外观来看,您正在进行两组分组.首先,按第一个字母,然后按组/代码(如果存在)或标题.

From the looks of your output, you are doing two lots of grouping. Firstly, by the first letter, then by either group/code (if it exists), or title.

Muenchian Grouping 通过定义一个键来实现快速查找组"中的所有项目.对于 group/codetitle 的第一个字母,您可以这样定义

Muenchian Grouping works by defining a key, to enable quick look up of all items in a 'group'. For the first letter of eithe group/code or title, you would define it like so

<xsl:key name="letter" match="info" use="substring(concat(group/code, title), 1, 1)"/>

(注意:这是区分大小写的,因此如果您可以混合使用小写和大写的起始字母,则可能需要使用翻译"功能).

(Note: This is case sensitive, so you may need to use the 'translate' function if you can have a mix of lower and upper case start letters).

如果group/code存在,则取其首字母,否则取标题的首字母.

If group/code exists, it will use the first letter of that, otherwise it will pick up the first letter of the title.

对于组/代码标题本身,关键如下

<xsl:key name="info" match="info" use="title[not(../group)]|group/code"/>

因此,它只使用没有group"元素的title"元素.

So, it only uses "title" elements where there is no "group" element present.

要获得第一个分组的不同首字母,请选择所有 info 元素并检查它们是否是给定字母的键中的第一个元素.这样做是这样的

To get the distinct first letters for your first grouping, you select all the info elements and check whether they are the first element in the key for their given letter. This is done like so

<xsl:apply-templates 
     select="info
             [generate-id() 
              = generate-id(key('letter', substring(concat(group/code, title), 1, 1))[1])]" 
     mode="letter">
  <xsl:sort select="substring(concat(group/code, title), 1, 1)" />
</xsl:apply-templates>

此处使用模式"是因为最终的 XSLT 将必须匹配 info 的模板.

The 'mode' is used here because the final XSLT will have to templates matching info.

在匹配的模板中,要按代码/组标题进行分组,您可以执行此操作

Within the matching template, to group by either code/group or title you can then do this

<xsl:apply-templates 
     select="key('letter', $letter)
            [generate-id() = generate-id(key('info', title[not(../group)]|group/code)[1])]">
  <xsl:sort select="title[not(../group)]|group/code" />
</xsl:apply-templates>

最后,要输出最后一组中的所有元素,您只需再次使用该键

And finally, to output all the elements within the final group, you would just use the key again

<xsl:apply-templates select="key('info', $value)[group/code=$value]/title">

这是完整的 XSLT.

Here is the full XSLT.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" indent="yes"/>

  <xsl:key name="letter" match="info" use="substring(concat(group/code, title), 1, 1)"/>
  <xsl:key name="info" match="info" use="title[not(../group)]|group/code"/>

  <xsl:template match="/*">
    <xsl:apply-templates select="info[generate-id() = generate-id(key('letter', substring(concat(group/code, title), 1, 1))[1])]" mode="letter">
      <xsl:sort select="substring(concat(group/code, title), 1, 1)" />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="info" mode="letter">
    <xsl:variable name="letter" select="substring(concat(group/code, title), 1, 1)" />
    <xsl:value-of select="concat($letter, '&#10;')" />
    <xsl:apply-templates select="key('letter', $letter)[generate-id() = generate-id(key('info', title[not(../group)]|group/code)[1])]">
      <xsl:sort select="title[not(../group)]|group/code" />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="info">
    <xsl:variable name="value" select="title[not(../group)]|group/code" />
    <xsl:value-of select="concat($value, '&#10;')" />
    <xsl:apply-templates select="key('info', $value)[group/code=$value]/title">
      <xsl:sort select="." />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="title">
    <xsl:value-of select="concat('   ', ., '&#10;')" />
  </xsl:template>
</xsl:stylesheet>

应用于您的 XML 时,输出如下

When applied to your XML, the following is output

A
Auto2
Auto3
Auto4
   Certificate
Auto5
s
state
   Auto
   Bill

这篇关于按xml字母顺序对数据进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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