使用XSLT排序

dsc*_*scl 5 xml sorting xslt xslt-1.0

更新 - 底部的新代码

我试图找出如何使用sort函数从一些XML数据中提取最新记录.我是使用XSLT的新手,遇到了很多问题.这是我的数据的一个例子......

<content date="1/13/2011 1:21:00 PM">
    <collection vo="promotion">
        <data vo="promotion" promotionid="64526" code="101P031" startdate="1/7/2011 12:00:00 AM"/>
        <data vo="promotion" promotionid="64646" code="101P046" startdate="1/9/2011 12:00:00 AM"/>
    </collection>
</content>
Run Code Online (Sandbox Code Playgroud)

我想要做的是按降序顺序按升级ID排序数据,然后只通过HTML输出最大的升级.这是我尝试的方式

更新 - 这是仍然遇到问题的代码的最新版本.

<html><body>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html"  encoding="UTF-8" />
    <xsl:template match="content/collection/data">
        <xsl:apply-templates>
            <xsl:sort select="promotionid" order="descending" data-type="number" />
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="content/collection">
        <xsl:value-of select="data/@promotionid" />
    </xsl:template> 
</xsl:stylesheet>
</body></html>
Run Code Online (Sandbox Code Playgroud)

虽然这确实返回了我得到的结果是'64526'而不是'64646'.

有人可以帮忙吗?我也在网上看过你可以按多个字段排序的例子.现在可能值得注意,而不是后来问,我们可能想要通过startdate而不是promotionid来排序.我已经设法提出了用YYYY,MM和DD打破日期的代码,但是我不知道除了使用那些作为我的选择参数之外我怎么会开始使用它,但我不知道知道这是否真的有效.

Year
<xsl:value-of select="substring(substring-after(substring-after(data/@startdate,'/'),'/'),1,4)" />

Month
<xsl:value-of select="substring-before(data/@startdate,'/')" />

Day
<xsl:value-of select="substring-before(substring-after(data/@startdate,'/'),'/')" />
Run Code Online (Sandbox Code Playgroud)

提前感谢,我向我的新手XSLT技能道歉.

-------------------------------------------------- ----

在此处获得一些帮助后,代码已更改,但仍未按预期工作.这是代码......

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html"  encoding="UTF-8" />
    <xsl:template match="content/collection/">
            <xsl:apply-templates>
                <xsl:sort select="@promotionid" order="descending" data-type="number" />
            </xsl:apply-templates>
        </xsl:template>

 <xsl:template match="content/collection/data">
        <xsl:if test="position()=1">
                   <xsl:value-of select="@promotionid"/>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

我仍然看到较低的价值输出而不是更大的价值.也许还有另一种方法可以通过排序来做到这一点?我也对这种可能性持开放态度.

1/14/11 10:37更新 *---------------------------------------- ---------------------------*好的,现在使用此代码确实对数据进行排序并输出最高的promotionid数.万分感谢!

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="collection">
      <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="data">
         <xsl:sort select="@promotionid" data-type="number" order="descending"/>
        </xsl:apply-templates>
      </xsl:copy>
    </xsl:template>
<xsl:template match="content/collection/data">
        <xsl:if test="position()=1">
                   <xsl:value-of select="@promotionid"/>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

现在忽略promtionid你能告诉我如何按日期排序,降序吗?我尝试删除不幸的是我知道日期应该有一个静态长度,但我们无法控制我们收到的数据:-(

你也可以推荐一本书,以便真正能够更好地理解这一切吗?你得到了很大的帮助!

Dim*_*hev 5

<xsl:sort select="promotionid" order="descending" data-type="number"
Run Code Online (Sandbox Code Playgroud)

/>

这里有一个明显的错误:promotionid是属性,而不是元素.

方案:

select="@promotionid" order="descending" data-type="number" />
Run Code Online (Sandbox Code Playgroud)

另一个错误:

<xsl:template match="content/collection/data">
    <xsl:apply-templates>
        <xsl:sort select="promotionid" order="descending" data-type="number" />
    </xsl:apply-templates>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

<xsl:apply-templates>进行过晚和排序.

你想要:

<xsl:template match="content/collection/">
            <xsl:apply-templates>
                <xsl:sort select="@promotionid" order="descending" data-type="number" />
            </xsl:apply-templates>
        </xsl:template>
Run Code Online (Sandbox Code Playgroud)

    <xsl:template match="content/collection/data">
        <xsl:if test="position()=1">
                   <xsl:value-of select="@promotionid"/>
        </xsl:if>
    </xsl:template>
Run Code Online (Sandbox Code Playgroud)

至于你扩展的问题:

这种转变:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:template match="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="collection">
      <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="data">
         <xsl:sort select="@promotionid" data-type="number" order="descending"/>
         <xsl:sort select=
          "concat(
             substring-after(substring-after(substring-before(@startdate,' ')
                                             ,'/'
                                             ),
                               '/'
                               ),
             substring-before(substring-after(substring-before(@startdate,' ')
                                             ,'/'
                                             ),
                              '/'
                            ),
             substring-before(substring-after(substring-before(@startdate,' ')
                                             ,'/'
                                             ),
                               '/'
                               )
                )"/>
        </xsl:apply-templates>
      </xsl:copy>
    </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

当应用于提供的XML文档时:

<content date="1/13/2011 1:21:00 PM">
    <collection vo="promotion">
        <data vo="promotion" promotionid="64526" code="101P031" startdate="1/7/2011 12:00:00 AM"/>
        <data vo="promotion" promotionid="64646" code="101P046" startdate="1/9/2011 12:00:00 AM"/>
    </collection>
</content>
Run Code Online (Sandbox Code Playgroud)

产生想要的结果:

<content date="1/13/2011 1:21:00 PM">

   <collection vo="promotion">
      <data vo="promotion" promotionid="64646" code="101P046" startdate="1/9/2011 12:00:00 AM"/>
      <data vo="promotion" promotionid="64526" code="101P031" startdate="1/7/2011 12:00:00 AM"/>
   </collection>

</content>
Run Code Online (Sandbox Code Playgroud)

但请注意,这不能处理日期组件的可变长度.最好使用固定长度格式:mm/dd/yyyy