如何在XSL中排序日期?

时间:2016-04-16 08:50:16

标签: xml xslt xslt-1.0

我有一个以下的XML结构,我想对日期进行排序,并将一个日期节点更新为最新日期。日期为YYYY / mm / dd格式。以下是XML结构。

更具体地说,我在下面举一个例子。 假设2015/01/01,2015 / 01 / 02,2015 / 01/03有3个覆盖有效日期,那么customerEffectiveDate应更新到2015/01/03。

关于XML结构的注意事项: 1.产品数量可以从1到10。 2.覆盖节点可以是1到多个。

<Map>
    <customer>
        <customerDetails>
            <!-- The customerEffectiveDate below should be updated to the latest among all the effectiveDate fron coverage.-->
            <customerEffectiveDate>2014/06/02</customerEffectiveDate>
        </customerDetails>
    </customer>
    <products>
        <product1>
            <!-- Coverage Nodes can occur multiple times. There is no limit.-->
            <coverage>
                <effectiveDate>2015/12/01</effectiveDate>
            </coverage>
            <coverage>
                <effectiveDate>2015/11/01</effectiveDate>
            </coverage>
        </product1>
        <product2>
            <coverage>
                <effectiveDate>2014/12/01</effectiveDate>
            </coverage>
            <coverage>
                <effectiveDate>2015/09/01</effectiveDate>
            </coverage>
        </product2>
        .
        .
        .
        .
        .
        .
        .
        .

        <product10></product10>
    </products>
</Map>

需要注意的另一点是我正在使用XSL 1.0。有人可以帮忙。

我已查看thisthisthis

感谢。

2 个答案:

答案 0 :(得分:1)

鉴于这种格式,您可以轻松对其进行排序,编写模板

<xsl:template match="customer/customerDetails/customerEffectiveDate">
  <xsl:copy>
    <xsl:for-each select="//coverage/effectiveDate">
      <xsl:sort select="." data-type="text" order="descending"/>
      <xsl:if test="position() = 1">
        <xsl:value-of select="."/>
      </xsl:if>
   </xsl:for-each>
 </xsl:copy>
</xsl:template>

加上身份转换模板

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

将其余部分复制不变。

答案 1 :(得分:1)

这可能不是最简单的方法,但这种方法会对<coverage>标记下的所有<product1-10>标记进行排序,从所有<effectiveDate>值中提取最新值并复制其余值。 / p>

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

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

<!-- Process <products> tag with higher priority, so that the follwing template does not match -->
<xsl:template match="products" priority="1">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="*[starts-with(local-name(),'product')]">
  <xsl:element name="{name()}">
    <xsl:for-each select="coverage">
      <xsl:sort select="effectiveDate/text()" order="descending" />
      <xsl:copy-of select="." />
    </xsl:for-each>
  </xsl:element>
</xsl:template>

<!-- extract the first 'effectiveDate' after sorting all values -->
<xsl:template match="customerEffectiveDate">
  <xsl:variable name="latest">
    <xsl:for-each select="../../../products//effectiveDate">
      <xsl:sort select="text()" order="descending" />
      <xsl:if test="position() = 1">
        <xsl:value-of select="." />
      </xsl:if>
    </xsl:for-each>
  </xsl:variable>
  <customerEffectiveDate><xsl:copy-of select="$latest" /></customerEffectiveDate>
</xsl:template>

</xsl:stylesheet>