谓词不按预期排除数据

时间:2018-01-19 02:18:11

标签: xslt xslt-2.0

我遇到了一个我无法弄清楚的问题。作为一个警告,我必须非常努力地擦除数据,所以请原谅任何XML格式的不规则性。

看来我的谓词并没有像我期望的那样排除数据。我想只写一些数据,如果有合约在某个月开始,但是,当我构建我的for-each(或apply-template,或if,或...)语句,试图排除在月份xsl似乎无论年份如何都会返回数据。它确实排除了在给定月份之外的开始,但这可能是巧合。

带有for-each示例的XSLT。我将需要这个(或应用模板)所以这是我认为的问题的核心。再次,原谅违规行为。这不是我要离开它的方式,但它适用于快速测试。

    

<xsl:variable name="reportStartMonth" select="xs:date(contracts/exportinformation/timestamp/TIMESTAMP/@date) - xs:dayTimeDuration(concat('P', day-from-date(contracts/exportinformation/timestamp/TIMESTAMP/@date), 'D')) + xs:dayTimeDuration('P1D')"/>
<xsl:variable name="reportEndMonth" select="xs:date(contracts/exportinformation/timestamp/TIMESTAMP/@date) - xs:dayTimeDuration(concat('P', day-from-date(contracts/exportinformation/timestamp/TIMESTAMP/@date) - 1, 'D')) + xs:yearMonthDuration('P1M') - xs:dayTimeDuration('P1D')"/>
<xsl:key name="costGroup" match="contracts/Contract/ContractDetails/RightGroup/cost/costGroup/COSTGROUP" use="@name"/>

<xsl:template match="/">
    <xsl:value-of select="$reportStartMonth"/>
    <xsl:text>&#x9;</xsl:text>
    <xsl:value-of select="$reportEndMonth"/>
    <xsl:text>&#xA;</xsl:text>
    <xsl:for-each select="contracts/Contract/ContractDetails[Rights/Window/startDateFormula/fixedDate/DATE/@date &gt;= $reportStartMonth and Rights/Window/startDateFormula/fixedDate/DATE/@date &lt;= $reportEndMonth]/RightGroup/cost/costGroup/COSTGROUP[generate-id() = generate-id(key('costGroup', @name)[1])]">
        <xsl:value-of select="@name"/>
        <xsl:text>&#x9;</xsl:text>
        <xsl:value-of select="../../../../../@contractNumber"/>
        <xsl:text>&#x9;</xsl:text>
        <xsl:value-of select="../../../../Rights/Window/startDateFormula/fixedDate/DATE/@date"/>
        <xsl:text>&#xA;</xsl:text>
    </xsl:for-each>
</xsl:template>

针对以下XML运行时:

<contracts>
    <exportinformation>
        <timestamp>
            <TIMESTAMP time="14:08:22.889" date="2018-01-17"/>
        </timestamp>
    </exportinformation>
    <Contract contractName="C1" contractNumber="00000001">
        <ContractDetails>
            <RightGroup>
                <cost>
                    <costGroup>
                        <COSTGROUP name="A1"/>
                    </costGroup>
                </cost>
            </RightGroup>
            <Rights>
                <Window>
                    <startDateFormula>
                        <fixedDate>
                            <DATE date="2018-01-01"/>
                        </fixedDate>
                    </startDateFormula>
                </Window>
            </Rights>
        </ContractDetails>
    </Contract>
    <Contract contractName="C2" contractNumber="00000002">
        <ContractDetails>
            <RightGroup>
                <cost>
                    <costGroup>
                        <COSTGROUP name="A1"/>
                    </costGroup>
                </cost>
            </RightGroup>
            <Rights>
                <Window>
                    <startDateFormula>
                        <fixedDate>
                            <DATE date="2013-01-01"/>
                        </fixedDate>
                    </startDateFormula>
                </Window>
            </Rights>
        </ContractDetails>
    </Contract>
    <Contract contractName="C3" contractNumber="0000003">
        <ContractDetails>
            <RightGroup>
                <cost>
                    <costGroup>
                        <COSTGROUP name="A2"/>
                    </costGroup>
                </cost>
                <cost>
                    <costGroup>
                        <COSTGROUP name="A2"/>
                    </costGroup>
                </cost>
            </RightGroup>
            <Rights>
                <Window>
                    <startDateFormula>
                        <fixedDate>
                            <DATE date="2017-01-01"/>
                        </fixedDate>
                    </startDateFormula>
                </Window>
                <Window>
                    <startDateFormula>
                        <fixedDate>
                            <DATE date="2019-01-01"/>
                        </fixedDate>
                    </startDateFormula>
                </Window>
            </Rights>
        </ContractDetails>
        <ContractDetails>
            <RightGroup>
                <cost>
                    <costGroup>
                        <COSTGROUP name="A2"/>
                    </costGroup>
                </cost>
            </RightGroup>
            <Rights>
                <Window>
                    <startDateFormula>
                        <fixedDate>
                            <DATE date="2017-11-01"/>
                        </fixedDate>
                    </startDateFormula>
                </Window>
            </Rights>
        </ContractDetails>
    </Contract>
</contracts>

我希望这会返回1月份的第一个和最后一个日期,它确实很好,然后就行:

A1  00000001    2018-01-01

然而,它实际上会返回

A1  00000001    2018-01-01
A2  0000003 2017-01-01 2019-01-01

日期比较谓词是我在几个样式表中使用而没有问题的东西。但是,就我记忆而言,它始终是一个值的一部分或选择| when语句。虽然我在过去的一年里已经写了数百个样式表,所以我可能会在for-each或apply-template中使用它。在for-each和key中是否有一些我没有正确考虑的操作?

1 个答案:

答案 0 :(得分:1)

我认为问题在于,您的Rights个元素之一有两个DATE元素作为后代,而您当前的逻辑同时考虑了这两个元素。因此,一个日期2017-01-01小于报告结束日期,另一个日期是2019-01-01,它位于报告开始日期之后。当前表达式中的逻辑导致表达式为true。

你想要的是检查其中一个日期是否满足这两个条件,所以应该是这个......

<xsl:for-each select="contracts/Contract/ContractDetails
                      [Rights/Window/startDateFormula/fixedDate/DATE/@date
                          [xs:date(.) &gt;= $reportStartMonth and xs:date(.) &lt;= $reportEndMonth]]
                      /RightGroup/cost/costGroup/COSTGROUP[generate-id() = generate-id(key('costGroup', @name)[1])]">

注意,看起来你也试图做Muenchian Groupin。当您使用XSLT 2.0时,请考虑使用xsl:for-each-group,这将删除使用generate-id()的表达式的可怕部分。