使用 XSLT 检查两个日期之间的差异

Check difference between two dates using XSLT

1]我有以下输入 xml1:

<TimeLimit Start="2022-02-24" End="2022-03-04"/>
<Tasks>
  <TaskRate RateCode="Test">
    <Rates>
       <Rate BeginDate="2022-02-24" EndDate="2022-02-25" >
        <Base Amount="100.00" CurrencyCode="EUR"/>
       </Rate>
      <Rate BeginDate="2022-02-26" EndDate="2022-03-01" >
       <Base Amount="200.00" CurrencyCode="EUR"/>
      </Rate>
      <Rate BeginDate="2022-03-02" EndDate="2022-03-03" >
       <Base Amount="200.00" CurrencyCode="EUR"/>
      </Rate>
   </Rates>
  </TaskRate>
</Tasks>

我想要如下输出:

<TimeLimit Start="2022-02-24" End="2022-03-04"/>
<Tasks>
  <TaskRate RateCode="Test">
    <Rates>
       <Rate BeginDate="2022-02-24" EndDate="2022-02-25" >
        <Base Amount="100.00" CurrencyCode="EUR"/>
       </Rate>
      <Rate BeginDate="2022-02-25" EndDate="2022-03-02" >
       <Base Amount="200.00" CurrencyCode="EUR"/>
      </Rate>
      <Rate BeginDate="2022-03-02" EndDate="2022-03-04" >
       <Base Amount="200.00" CurrencyCode="EUR"/>
      </Rate>
   </Rates>
  </TaskRate>
</Tasks>

2]当我输入以下内容时 xml2:

<TimeLimit Start="2022-02-24" End="2022-03-04"/>
<Tasks>
  <TaskRate RateCode="Test">
    <Rates>
       <Rate BeginDate="2022-02-24" EndDate="2022-02-26" >
        <Base Amount="100.00" CurrencyCode="EUR"/>
       </Rate>
      <Rate BeginDate="2022-02-26" EndDate="2022-03-02" >
       <Base Amount="200.00" CurrencyCode="EUR"/>
      </Rate>
      <Rate BeginDate="2022-03-02" EndDate="2022-03-04" >
       <Base Amount="200.00" CurrencyCode="EUR"/>
      </Rate>
   </Rates>
  </TaskRate>
</Tasks>

然后我想要输出如下:

<TimeLimit Start="2022-02-24" End="2022-03-04"/>
<Tasks>
  <TaskRate RateCode="Test">
    <Rates>
       <Rate BeginDate="2022-02-24" EndDate="2022-02-26" >
        <Base Amount="100.00" CurrencyCode="EUR"/>
       </Rate>
      <Rate BeginDate="2022-02-26" EndDate="2022-03-02" >
       <Base Amount="200.00" CurrencyCode="EUR"/>
      </Rate>
      <Rate BeginDate="2022-03-02" EndDate="2022-03-04" >
       <Base Amount="200.00" CurrencyCode="EUR"/>
      </Rate>
   </Rates>
  </TaskRate>
</Tasks>

这意味着对于连续或非连续日期范围作为输入,我总是希望输出 xml 具有连续日期范围。 我正在使用以下 XSLT 代码,但它不起作用:

<Rates>
<xsl:for-each select="Rates/Rate">
<Rate>
<xsl:if test="@BeginDate and not(@BeginDate='')">
<xsl:attribute name="BeginDate">
<xsl:value-of select="@BeginDate" />
</xsl:attribute>
</xsl:if>
<xsl:choose>
<xsl:when test="(xs:date(following-sibling::Rate[1]/@BeginDate) - xs:date(@EndDate)) = 1">
<xsl:attribute name="EndDate">
<xsl:value-of select="xs:date(@EndDate)+xs:dayTimeDuration('P1D')" />
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:if test="@EndDate and not(@EndDate='')">
<xsl:attribute name="EndDate">
<xsl:value-of select="@EndDate" />
</xsl:attribute>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="xs:date(/TimeLimit/@End) - @EndDate = 1">
<xsl:attribute name="EndDate">
<xsl:value-of select="xs:date(@EndDate)+xs:dayTimeDuration('P1D')" />
</xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:if test="@EndDate and not(@EndDate='')">
<xsl:attribute name="EndDate">
<xsl:value-of select="@EndDate" />
</xsl:attribute>
</xsl:if>
</xsl:otherwise>
</xsl:choose>

</Rate>
</xsl:for-each>
</Rates>

有人可以帮忙吗?

在下面的 xslt 中我做了 2 个假设:

日期可以相差不止一天,并且还应遵守 TimeLimit/@start。那么就不需要 date-calculation 了。请告诉我这是否正确?

因为你的 xml 没有 root-element,这是 xml 我用过:

<TasksGroup>
  <TimeLimit Start="2022-02-24" End="2022-03-04"/>
  <Tasks>
    <TaskRate RateCode="Test">
      <Rates>
        <Rate BeginDate="2022-02-24" EndDate="2022-02-25" >
          <Base Amount="100.00" CurrencyCode="EUR"/>
        </Rate>
        <Rate BeginDate="2022-02-26" EndDate="2022-03-01" >
          <Base Amount="200.00" CurrencyCode="EUR"/>
        </Rate>
        <Rate BeginDate="2022-03-02" EndDate="2022-03-03" >
          <Base Amount="200.00" CurrencyCode="EUR"/>
        </Rate>
      </Rates>
    </TaskRate>
  </Tasks>  
</TasksGroup>

这是 xslt

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  exclude-result-prefixes="#all">
  
  <xsl:output method="xml"  encoding="UTF-8" indent="yes"/>
  
  <xsl:strip-space elements="*"/>
  
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:variable name="timeLimt" as="element()" select="/*/TimeLimit[1]"/>

  <xsl:template match="Rate">
    <xsl:copy>
      <xsl:choose>
        <xsl:when test="position()=1">
          <xsl:attribute name="BeginDate">
            <xsl:value-of select="$timeLimt/@Start" />
          </xsl:attribute>
        </xsl:when>
        <xsl:when test="@BeginDate[not(.='')]">
          <xsl:copy-of select="@BeginDate"/>
        </xsl:when>
      </xsl:choose>
      <xsl:choose>
        <xsl:when test="position()=last()">
          <xsl:attribute name="EndDate">
            <xsl:value-of select="$timeLimt/@End" />
          </xsl:attribute>
        </xsl:when>
        <xsl:when test="following-sibling::*[1][@BeginDate[not(.='')]]">
          <xsl:attribute name="EndDate">
            <xsl:value-of select="following-sibling::*[1]/@BeginDate" />
          </xsl:attribute>
        </xsl:when>
        <xsl:when test="@EndDate[not(.='')]">
          <xsl:copy-of select="@EndDate"/>
        </xsl:when>
      </xsl:choose>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>

结果:

<TasksGroup>
   <TimeLimit Start="2022-02-24" End="2022-03-04"/>
   <Tasks>
      <TaskRate RateCode="Test">
         <Rates>
            <Rate BeginDate="2022-02-24" EndDate="2022-02-26">
               <Base Amount="100.00" CurrencyCode="EUR"/>
            </Rate>
            <Rate BeginDate="2022-02-26" EndDate="2022-03-02">
               <Base Amount="200.00" CurrencyCode="EUR"/>
            </Rate>
            <Rate BeginDate="2022-03-02" EndDate="2022-03-04">
               <Base Amount="200.00" CurrencyCode="EUR"/>
            </Rate>
         </Rates>
      </TaskRate>
   </Tasks>
</TasksGroup>