XSLT:按多个项目排序

8

我有一些XML数据,例如:

<feed>
  <entry>
    <id>4</id>
    <updated>2011-01-18T16:55:54Z</updated>
    <title>title2</title>
  </entry>
  <entry>
    <id>3</id>
    <updated>2011-01-18T16:55:54Z</updated>
    <title>title1</title>
  </entry>
  <entry>
    <id>2</id>
    <updated>2011-01-18T16:55:54Z</updated>
    <title>title1</title>
  </entry>
  <entry>
    <id>1</id>
    <updated>2011-01-18T16:55:54Z</updated>
    <title>title</title>
  </entry>
</feed>

And I need the outcome to result like:

<feed>
  <entry>
    <id>1</id>
    <updated>2011-01-18T16:55:54Z</updated>
    <title>title</title>
  </entry>
  <entry>
    <id>2</id>
    <updated>2011-01-18T16:55:54Z</updated>
    <title>title1</title>
  </entry>
  <entry>
    <id>3</id>
    <updated>2011-01-18T16:55:54Z</updated>
    <title>title1</title>
  </entry>
  <entry>
    <id>4</id>
    <updated>2011-01-18T16:55:54Z</updated>
    <title>title2</title>
  </entry>
</feed>

基本上,我需要XSLT按标题和ID进行排序。我已经制作了一个XSLT,但是较短的时间会最后出现(使用Xerces):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:atom="http://www.w3.org/2005/Atom"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />

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

 <xsl:template match="atom:feed">
  <xsl:copy>
   <xsl:apply-templates select="*" />
   <xsl:for-each select="atom:entry">
    <xsl:sort select="string-length(atom:title)" order="descending" />
    <xsl:sort select="atom:title" data-type="text" order="ascending" />
    <xsl:copy-of select="."/>
   </xsl:for-each>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="atom:feed/atom:entry"/>

</xsl:stylesheet>

1
如果“短条目”指的是具有较小字符串长度的entry/title,那么按此长度排序的要求与按字母顺序排序的entry/title的要求相冲突。例如,您想如何对具有字符串值“Zoo”和“Alphabet”的标题的两个条目进行排序?哪一个应该先出现?请更正您的问题并删除任何相互矛盾的要求。 - Dimitre Novatchev
1个回答

18

对于您的输入样本(实际上不是Atom Feed),此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="feed">
        <xsl:copy>
            <xsl:apply-templates>
                <xsl:sort select="update" order="descending"/>
                <xsl:sort select="title"/>
                <xsl:sort select="id" data-type="number"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

输出:

<feed>
    <entry>
        <id>1</id>
        <updated>2011-01-18T16:55:54Z</updated>
        <title>title</title>
    </entry>
    <entry>
        <id>2</id>
        <updated>2011-01-18T16:55:54Z</updated>
        <title>title1</title>
    </entry>
    <entry>
        <id>3</id>
        <updated>2011-01-18T16:55:54Z</updated>
        <title>title1</title>
    </entry>
    <entry>
        <id>4</id>
        <updated>2011-01-18T16:55:54Z</updated>
        <title>title2</title>
    </entry>
</feed>

注意:只要没有不同的时区,此日期时间格式可以像字符串一样进行排序(默认)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接