使用嵌套if

时间:2018-03-16 19:49:17

标签: xslt xslt-2.0

我已经解决了这个问题,但我想实现更好的代码。我试图确定发生非零金融事件的最后日期。请注意,为简洁起见,这是一个剥离和更改的XML,因此可以解释任何格式化的怪异。我使用的实际XML具有从1/1/2018到12/31/2029的更改金额,从4/1/2018到12/31/2029的所有内容总计为0.

<Products>
  <Cost>
    <Company name="A"/>
    <Financials>
       <Change amount="-10000">
          <Date date="1/1/2018" dateindays="42734">
          <Type name="open">
       <Change>
       <Change amount="4500">
          <Date date="2/1/2018" dateindays="42765">
          <Type name="debit">
       </Change>
       <Change amount="4500">
          <Date date="3/1/2018" dateindays="42793">
          <Type name="debit">
       </Change>
       <Change amount="4500">
          <Date date="4/1/2018" dateindays="42824">
          <Type name="debit">
       </Change>
       <Change amount="-2000">
          <Date date="4/1/2018" dateindays="42824">
          <Type name="debit">
       <Change>
       <Change amount="-2500">
          <Date date="4/1/2018" dateindays="42824">
          <Type name="debit">
    </Financials>
  </Cost>
</Products>

在上面的代码段中我想要3/1/2018的日期,因为4月1日的日期总计为0借记。

使用XSLT 2.0,我使用以下代码排除了4/1/2018的日期,但我还没有找到只返回3/1/2018日期的方法。我尝试过的每件事都已经将4/1/2018作为系列中的最后一个日期。

<xsl:for-each-group select="Products/Cost[Company/@name = 
    $Company]/Financials/Change[Type/@name = 'Debit']/Date" group-
    by="@dateindays">
  <xsl:sort select="@dateindays" data-type="number" order="descending"/>
  <xsl:variable name="actDate" select="@dateindays"/>
  <xsl:if test="sum(/Products/Cost[Company/@name = 
    $Company]/Financials/Change[Type/@name = 'Debit' and Date/@dateindays = 
    $actDate]/@amount) != 0">
      <xsl:value-of select="@date"/>
  </xsl:if>
</xsl:for-each-group>

正如我所说的,我做了一些黑客攻击(Excel中的隐藏单元格),但我真的想在代码中处理它,因为看起来这个日期可能会成为代码中后续过滤的一部分。

3 个答案:

答案 0 :(得分:3)

我认为您可以使用当前组的总和进行检查,然后您需要在变量中输出这些元素,然后获取该变量值中的第一项:

  <xsl:variable name="non-zero" as="element(Date)*">
      <xsl:for-each-group select="Products/Cost[Company/@name = 'A']/Financials/Change[Type/@name = 'debit']" group-by="Date/@dateindays">
          <xsl:sort select="current-grouping-key()" data-type="number" order="descending"/>
          <xsl:variable name="actDate" select="@dateindays"/>
          <xsl:if test="sum(current-group()/@amount) != 0">
              <Date>{Date/@date}</Date>
          </xsl:if>
      </xsl:for-each-group>
  </xsl:variable>
  <xsl:value-of select="$non-zero[1]"/>

https://xsltfiddle.liberty-development.net/pPgCcoC

<Date>{Date/@date}</Date>是XSLT 3,在XSLT 2中你需要<Date><xsl:value-of select="Date/@date"/></Date>

答案 1 :(得分:0)

这是与马丁相似的另一种选择。我喜欢马丁的更好(+1),但是因为我已经写好了,所以我会继续添加它。

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:param name="company" select="'A'"/>

  <xsl:key name="changes" match="Change" use="Date/@dateindays"/>

  <xsl:template match="/">
    <xsl:apply-templates select="Products/Cost[Company/@name = $company]/Financials"/>
  </xsl:template>

  <xsl:template match="Financials">
    <xsl:variable name="non-zero-days" as="xs:float*">
      <xsl:for-each-group select="Change" group-by="Date/@dateindays">
        <xsl:if test="sum(current-group()/@amount) != 0">          
          <xsl:sequence select="data(Date/@dateindays)"/>
        </xsl:if>
      </xsl:for-each-group>      
    </xsl:variable>
    <results>
      <xsl:value-of select="key('changes',string(max($non-zero-days)))[1]/Date/@date"/>
    </results>
  </xsl:template>

</xsl:stylesheet>

<强>输出

<results>3/1/2018</results>

工作小提琴:https://xsltfiddle.liberty-development.net/3Nqn5Yn/1

答案 2 :(得分:0)

我会采用两阶段方法:首先对数据进行分组,然后对组进行操作。

在第一阶段,你转换

   <Change amount="4500">
      <Date date="4/1/2018" dateindays="42824">
      <Type name="debit">
   </Change>
   <Change amount="-2000">
      <Date date="4/1/2018" dateindays="42824">
      <Type name="debit">
   </Change>
   <Change amount="-2500">
      <Date date="4/1/2018" dateindays="42824">
      <Type name="debit">
   </Change>

<Date date="4/1/2018" dateindays="42824">
  <Change amount="4500">
          <Type name="debit">
  </Change>
  <Change amount="-2000">
          <Type name="debit">
  </Change>
  <Change amount="-2500">
          <Type name="debit">
  </Change>
</Date>

(这是xsl:for-each-group的一个简单使用)

在第二阶段,您应用过滤,例如Date[sum(Change/@amount)!=0)][last()]