2014-12-26 25 views
1

我使用XSLT 2.0转变为一个新的XML 日期这是我的XML结构:XSL组通过当日期等于从

<?xml version="1.0" encoding="UTF-8"?> 
<bills> 
    <bill id="1"> 
     <rz_from>05.11.2011</rz_from> 
     <rz_to>31.12.2011</rz_to> 
     <rz_price_pro_unit>4</rz_price_pro_unit> 
     <rz_units>7</rz_units> 
    </bill> 
    <bill id="2"> 
     <rz_from>1.1.2012</rz_from> 
     <rz_to>31.3.2012</rz_to> 
     <rz_price_pro_unit>4</rz_price_pro_unit> 
     <rz_units>9</rz_units> 
    </bill> 
    <bill id="3"> 
     <rz_from>1.5.2012</rz_from> 
     <rz_to>31.12.2012</rz_to> 
     <rz_price_pro_unit>4</rz_price_pro_unit> 
     <rz_units>21</rz_units> 
    </bill> 
    <bill id="4"> 
     <rz_from>1.1.2013</rz_from> 
     <rz_to>31.12.2013</rz_to> 
     <rz_price_pro_unit>5</rz_price_pro_unit> 
     <rz_units>45</rz_units> 
    </bill> 
    <bill id="5"> 
     <rz_from>1.1.2014</rz_from> 
     <rz_to>31.12.2014</rz_to> 
     <rz_price_pro_unit>5</rz_price_pro_unit> 
     <rz_units>51</rz_units> 
    </bill> 
</bills> 

我需要按这些规则的议案节点:

  • 单位价格是相同的
  • 日期(rz_from - 1天)等于前一节点的日期(rz_to)
  • 的应单元由分组值

的总和计所以结果应该是:

  • 比尔:16个单位 - 价格4(钞票1 + 2)
  • 比尔:21个单位 - 价格4(纸币3)
  • 比尔:96个单位 - 价格5(票据4 + 5)
+0

到目前为止您尝试过什么?你可以请你发布你的XSLT .. –

回答

1

我想你在这里有足够的两个或三个单独的问题。

首先,这里没有这样的分组,因为没有共同的值可以分组。我相信你需要选择每组中的第一个账单(即那些不会继续“链”的账单),然后将“兄弟递归”应用到组中的成员。

增加的复杂性是您的日期不是ISO-8601日期(YYYY-MM-DD),因此在转换之前不能对它们执行任何计算。我会为此使用自定义函数。

下面的样式表假设票据按时间顺序排序(尽管这个假设是不解决问题的必要):

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" 
xmlns:my="http://www.example.com/my" 
exclude-result-prefixes="xs my"> 
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> 

<xsl:function name="my:get-as-date" as="xs:date"> 
    <xsl:param name="dmy"/> 
    <xsl:variable name="d" select="substring-before($dmy, '.')"/> 
    <xsl:variable name="m" select="substring-before(substring-after($dmy, '.'), '.')"/> 
    <xsl:variable name="y" select="substring-after(substring-after($dmy, '.'), '.')"/> 
    <xsl:value-of select="concat(format-number(xs:integer($y), '0000'), '-', format-number(xs:integer($m), '00'), '-', format-number(xs:integer($d), '00'))"/> 
</xsl:function> 

<xsl:template match="/bills"> 
    <xsl:copy> 
     <xsl:apply-templates select="bill[not(preceding-sibling::bill[1]/my:get-as-date(rz_to) + xs:dayTimeDuration('P1D') = my:get-as-date(rz_from) and preceding-sibling::bill[1]/rz_price_pro_unit = rz_price_pro_unit)]" mode="init"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="bill" mode="init"> 
    <group> 
     <xsl:copy-of select="rz_from"/> 
     <xsl:apply-templates select="." mode="collect"/> 
    </group> 
</xsl:template> 

<xsl:template match="bill" mode="collect"> 
    <xsl:param name="units" select="0"/> 
     <xsl:choose> 
      <xsl:when test="following-sibling::bill[1]/my:get-as-date(rz_from) = my:get-as-date(rz_to) + xs:dayTimeDuration('P1D') and following-sibling::bill[1]/rz_price_pro_unit = rz_price_pro_unit"> 
       <xsl:apply-templates select="following-sibling::bill[1]" mode="collect"> 
        <xsl:with-param name="units" select="$units + rz_units"/> 
       </xsl:apply-templates> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:copy-of select="rz_to"/> 
       <xsl:copy-of select="rz_price_pro_unit"/> 
       <rz_units> 
        <xsl:value-of select="$units + rz_units"/> 
       </rz_units> 
      </xsl:otherwise> 
     </xsl:choose> 
</xsl:template> 

</xsl:stylesheet> 

结果

<?xml version="1.0" encoding="utf-8"?> 
<bills> 
    <group> 
     <rz_from>05.11.2011</rz_from> 
     <rz_to>31.3.2012</rz_to> 
     <rz_price_pro_unit>4</rz_price_pro_unit> 
     <rz_units>16</rz_units> 
    </group> 
    <group> 
     <rz_from>1.5.2012</rz_from> 
     <rz_to>31.12.2012</rz_to> 
     <rz_price_pro_unit>4</rz_price_pro_unit> 
     <rz_units>21</rz_units> 
    </group> 
    <group> 
     <rz_from>1.1.2013</rz_from> 
     <rz_to>31.12.2014</rz_to> 
     <rz_price_pro_unit>5</rz_price_pro_unit> 
     <rz_units>96</rz_units> 
    </group> 
</bills>