XSLT 1.0:通过连接日期字符串的部分进行排序 [英] XSLT 1.0: Sorting by concating portions of date string

查看:192
本文介绍了XSLT 1.0:通过连接日期字符串的部分进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用XML数据并按照其数据属性排序元素。不幸的是,日期以mm / dd / yyyy格式出现,不是静态长度。 (Jan = 1而不是01)所以我相信这个字符串必须被分解成三个组件,并填写一个月。最新的结合值(yyyymmdd)然后按降序排列。



问题是我不知道如何做到这一点。以下是数据的示例

 < content date =1/13/2011 1:21:00 PM> ; 
< collection vo =promotion>
< data vo =promotionpromotionid =64526code =101P031startdate =1/7/2011 12:00:00 AMtype =base/>
< data vo =promotionpromotionid =64646code =101P026startdate =2/19/2011 12:00:00 AMtype =/>
< data vo =promotionpromotionid =64636code =101P046startdate =1/9/2011 12:00:00 AMtype =base/>
< / collection>
< / content>

还有谁可以推荐一本关于学习XSLT的好书?



谢谢!



更新1



我真的很希望我更了解这个LOL,无论如何,我使用您提供的代码,并添加了在另一个问题中提供的相关代码中工作的值代码,并且没有看到任何结果。理想情况下,一旦排序完成,我将需要从最新的数据元素中引用多个其他属性。

 < xsl: stylesheet version =1.0xmlns:xsl =http://www.w3.org/1999/XSL/Transformxmlns:ext =http://exslt.org/common> 
< xsl:output omit-xml-declaration =yesindent =yes/>
< xsl:strip-space elements =*/>

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

< xsl:template match =/>
< xsl:variable name =vrtfPass1>
< xsl:apply-templates />
< / xsl:variable>
< xsl:apply-templates mode =pass2select =
ext:node-set($ vrtfPass1)/ */>
< / xsl:template>

< xsl:template match =@ startdate>
< xsl:variable name =vDateselect =substring-before(。,'')/>

< xsl:variable name =vYearselect =
substring($ vDate,string-length($ vDate)-3)/>
< xsl:variable name =vDayMonthselect =
substring-before($ vDate,concat('/',$ vYear))/>

< xsl:variable name =vMonth
select =format-number(substring-before($ vDayMonth,'/'),'00')/>
< xsl:variable name =vDay
select =format-number(substring-after($ vDayMonth,'/'),'00')/>

< xsl:attribute name =startdate>
< xsl:value-of select =concat($ vYear,$ vMonth,$ vDay)/>
< / xsl:attribute>
< / xsl:template>

< xsl:template match =node()| @ *mode =pass2>
< xsl:copy>
< xsl:apply-templates mode =pass2select =node()| @ */>
< / xsl:copy>
< / xsl:template>

< xsl:template mode =pass2match =collection>
< xsl:copy>
< xsl:apply-templates mode =pass2select =@ */>
< xsl:apply-templates mode =pass2>
< xsl:sort select =@ startdate/>
< / 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>



更新2



嗯,好的,我试着像你说的那样更新

  ... 
< / xsl:template> ;

< xsl:template mode =pass2match =content / collection / data>
< xsl:value-of select =@ promotionid/>
< / xsl:template>
< / xsl:stylesheet>

我还没有得到任何输出。我google了一下,也试图弄乱这个声明 xmlns:ext =http://exslt.org/common,并根据我看过的文章尝试了不同的值在。我试过




  • http:// exslt .org / common

  • urn:schemas-microsoft-com:xslt

  • http://xml.apache.org/xalan (将
    更改为nodeet设置为nodeset)



    • 没有提供输出。所以我想知道我是否有问题,或者我的xslt处理器不支持它。



      更新3



      好的,我们已经被反复给了不好的信息。我用更改需要完成的另一个属性更新示例XML。



      需要做的是数据按日期排序,就像我们已经完成的那样,然后拉出最近的AND的类型的数据节点的promotionid ='base'。如果没有数据节点的type ='base'比我们仅仅引用最近的数据节点,就像我们已经有工作一样。



      希望是有道理的。再次非常感谢。

      解决方案

      您可以使用多个 xsl:sort 在这个样式表中的说明:

       < xsl:stylesheet version =1.0xmlns: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 =collection>
      < xsl:copy>
      < xsl:apply-templates select =@ */>
      < xsl:apply-templates select =data>
      < xsl:sort select =substring-after(
      substring-after(
      substring-before(
      @startdate,
      ''),
      '/'),
      '/')data-type =number/>
      < xsl:sort select =substring-before(
      @startdate,
      '/')data-type =number/>
      < xsl:sort select =substring-before(
      substring-after(
      @startdate,
      '/'),
      '/') -type =number/>
      < / xsl:apply-templates>
      < / xsl:copy>
      < / xsl:template>
      < / xsl:stylesheet>

      输出:

       code>< content date =1/13/2011 1:21:00 PM> 
      < collection vo =promotion>
      < data vo =promotionpromotionid =64526code =101P031
      startdate =1/7/2011 12:00:00 AM>< / data>
      < data vo =promotionpromotionid =64636code =101P046
      startdate =1/9/2011 12:00:00 AM>< / data>
      < data vo =promotionpromotionid =64646code =101P026
      startdate =2/19/2011 12:00:00 AM>< / data>
      < / collection>
      < / content>

      从评论更新


      我想要做的是在
      样式表中执行排序,因为
      已完成,然后导出
      promotionid在这种情况下,startdate
      ' 2/19/2011 '的项目。我假设
      它将像
      < xsl:value-of
      select =data [last()] / @ promotionid/>

      但是我正在使用错误的
      地方或者错误的语句


      更新3 :现在使用新的选择数据条件



      使用标准最大成语。这个样式表:

       < xsl:stylesheet version =1.0xmlns:xsl =http://www.w3。 org / 1999 / XSL / Transform> 
      < xsl:template match =collection>
      < xsl:variable name =vDataselect =data [@ type ='base']/>
      < xsl:for-each select =data [not($ vData)] | $ vData>
      < xsl:sort select =substring-after(
      substring-after(
      substring-before(
      @startdate,
      ''),
      '/'),
      '/')data-type =number/>
      < xsl:sort select =substring-before(
      @startdate,
      '/')data-type =number/>
      < xsl:sort select =substring-before(
      substring-after(
      @startdate,
      '/'),
      '/') -type =number/>
      < xsl:if test =position()= last()>
      < xsl:value-of select =@ promotionid/>
      < / xsl:if>
      < / xsl:for-each>
      < / xsl:template>
      < / xsl:stylesheet>

      输出:

       code> 64636 


      I'm trying to take XML data and sort elements by their data attribute. Unfortunately the dates come over in mm/dd/yyyy format and are not static lengths. (Jan = 1 instead of 01) So I believe the string will have to be parsed into three components and the month padded. The newly concated value (yyyymmdd) then sorted descending.

      Problem is I have no idea how to do this. Here is an example of the data

      <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" type="base"/>
              <data vo="promotion" promotionid="64646" code="101P026" startdate="2/19/2011 12:00:00 AM" type=""/>
              <data vo="promotion" promotionid="64636" code="101P046" startdate="1/9/2011 12:00:00 AM" type="base"/>
          </collection>
      </content>
      

      Also can anyone please recommend a good book on learning XSLT?

      Thanks!

      Update 1

      I really wish I had a better understanding of this LOL Anyways, I used the code you provided and added the 'value-of' code that worked in the related code you provide in another question and am seeing no results. Ideally once this has been sorted I would then need to reference multiple other attributes from the most recent data element.

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ext="http://exslt.org/common">
       <xsl:output omit-xml-declaration="yes" indent="yes"/>
       <xsl:strip-space elements="*"/>
      
          <xsl:template match="node()|@*">
            <xsl:copy>
               <xsl:apply-templates select="node()|@*"/>
            </xsl:copy>
          </xsl:template>
      
          <xsl:template match="/">
            <xsl:variable name="vrtfPass1">
              <xsl:apply-templates/>
            </xsl:variable>
            <xsl:apply-templates mode="pass2" select=
             "ext:node-set($vrtfPass1)/*"/>
          </xsl:template>
      
          <xsl:template match="@startdate">
           <xsl:variable name="vDate" select="substring-before(.,' ')"/>
      
           <xsl:variable name="vYear" select=
             "substring($vDate, string-length($vDate) -3)"/>
           <xsl:variable name="vDayMonth" select=
            "substring-before($vDate, concat('/',$vYear))"/>
      
            <xsl:variable name="vMonth"
              select="format-number(substring-before($vDayMonth, '/'), '00')"/>
            <xsl:variable name="vDay"
              select="format-number(substring-after($vDayMonth, '/'), '00')"/>
      
          <xsl:attribute name="startdate">
            <xsl:value-of select="concat($vYear,$vMonth,$vDay)"/>
          </xsl:attribute>
          </xsl:template>
      
          <xsl:template match="node()|@*" mode="pass2">
            <xsl:copy>
               <xsl:apply-templates mode="pass2" select="node()|@*"/>
            </xsl:copy>
          </xsl:template>
      
          <xsl:template mode="pass2" match="collection">
            <xsl:copy>
             <xsl:apply-templates mode="pass2" select="@*"/>
             <xsl:apply-templates mode="pass2">
              <xsl:sort select="@startdate"/>
             </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>
      

      Update 2

      Hmm, well I tried updating it like you said

      ...
      </xsl:template>
      
          <xsl:template mode="pass2" match="content/collection/data">
                         <xsl:value-of select="@promotionid"/>
          </xsl:template>
      </xsl:stylesheet>
      

      And I still don't get any output. I googled around a bit and also tried messing with this declaration xmlns:ext="http://exslt.org/common" and tried different values based on an article I looked at. I tried

      And nothing provided output. So I wonder if I have something wrong or if my xslt processor doesn't support it.

      Update 3

      Okay apparently we've been given, repeatedly, bad information. I've update the sample XML with another attribute which changes what needs to be done.

      What needs to happen is the data be sorted by date like we've already done and then pull the promotionid of the data node that is the most recent AND has the type='base'. If no data node has type='base' than we just reference the most recent data node like we've already have working.

      Hope that makes sense. And once again thanks so much.

      解决方案

      You can use multiple xsl:sort instructions like in this stylesheet:

      <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="collection">
              <xsl:copy>
                  <xsl:apply-templates select="@*"/>
                  <xsl:apply-templates select="data">
                  <xsl:sort select="substring-after(
                                       substring-after(
                                          substring-before(
                                             @startdate,
                                             ' '),
                                          '/'),
                                       '/')" data-type="number"/>
                  <xsl:sort select="substring-before(
                                       @startdate,
                                       '/')" data-type="number"/>
                  <xsl:sort select="substring-before(
                                       substring-after(
                                          @startdate,
                                          '/'),
                                       '/')" data-type="number"/>
                  </xsl:apply-templates>
              </xsl:copy>
          </xsl:template>
      </xsl:stylesheet>
      

      Output:

      <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>
              <data vo="promotion" promotionid="64636" code="101P046"
                    startdate="1/9/2011 12:00:00 AM"></data>
              <data vo="promotion" promotionid="64646" code="101P026"
                    startdate="2/19/2011 12:00:00 AM"></data>
          </collection>
      </content>
      

      Update from comments

      What I'm trying to do is in that stylesheet perform the sort as you've done and then export out the promotionid of the item with startdate '2/19/2011' in this case. I assumed it would be something like <xsl:value-of select="data[last()]/@promotionid"/> but I either am using it in the wrong place or have the statement wrong

      Update 3: Now with new selecting data conditions

      Use the "standard" maximum idiom. This stylesheet:

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
          <xsl:template match="collection">
              <xsl:variable name="vData" select="data[@type='base']"/>
              <xsl:for-each select="data[not($vData)]|$vData">
                  <xsl:sort select="substring-after(
                                           substring-after(
                                              substring-before(
                                                 @startdate,
                                                 ' '),
                                              '/'),
                                           '/')" data-type="number"/>
                  <xsl:sort select="substring-before(
                                           @startdate,
                                           '/')" data-type="number"/>
                  <xsl:sort select="substring-before(
                                           substring-after(
                                              @startdate,
                                              '/'),
                                           '/')" data-type="number"/>
                  <xsl:if test="position()=last()">
                      <xsl:value-of select="@promotionid"/>
                  </xsl:if>
              </xsl:for-each>
          </xsl:template>
      </xsl:stylesheet>
      

      Output:

      64636
      

      这篇关于XSLT 1.0:通过连接日期字符串的部分进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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