Xml xsl group by随时间从日期到等于日期从

Xml xsl group by随时间从日期到等于日期从,xml,xslt,group-by,Xml,Xslt,Group By,我正在使用XSLT2.0转换为新的XML 这是我的xml结构: <?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</

我正在使用XSLT2.0转换为新的XML 这是我的xml结构:

<?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>

05.11.2011
31.12.2011
4.
7.
1.1.2012
31.3.2012
4.
9
1.5.2012
31.12.2012
4.
21
1.1.2013
31.12.2013
5.
45
1.1.2014
31.12.2014
5.
51
我需要按照以下规则对账单节点进行分组:

  • 每件的价格是一样的
  • 日期(rz_from-1天)等于上一个节点的日期(rz_to)
  • 单位计数应为分组值之和
因此,结果应该是:

  • 工程量清单:16个单位-价格4(工程量清单1+2)
  • 工程量清单:21件-价格4(工程量清单3)
  • 工程量清单:96个单位-价格5(工程量清单4+5)

我想你有足够的时间回答两三个问题

首先,这里没有这样的分组,因为没有可以分组的公共值。我认为您需要选择每个组中的第一个账单(即不延续“链”的账单),然后对组中的成员应用“兄弟递归”

更复杂的是,您的日期不是ISO-8601日期(YYYY-MM-DD),因此在转换日期之前,无法对其执行任何计算。我将为此使用自定义函数

下面的样式表假设账单是按时间顺序排序的(尽管这个假设对于解决问题不是必需的):

XSLT2.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>

05.11.2011
31.3.2012
4.
16
1.5.2012
31.12.2012
4.
21
1.1.2013
31.12.2014
5.
96

到目前为止,您尝试了什么?你能发布你的XSLT吗。。