我遇到了一个我无法弄清楚的问题。作为一个警告,我必须非常努力地擦除数据,所以请原谅任何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>	</xsl:text>
<xsl:value-of select="$reportEndMonth"/>
<xsl:text>
</xsl:text>
<xsl:for-each select="contracts/Contract/ContractDetails[Rights/Window/startDateFormula/fixedDate/DATE/@date >= $reportStartMonth and Rights/Window/startDateFormula/fixedDate/DATE/@date <= $reportEndMonth]/RightGroup/cost/costGroup/COSTGROUP[generate-id() = generate-id(key('costGroup', @name)[1])]">
<xsl:value-of select="@name"/>
<xsl:text>	</xsl:text>
<xsl:value-of select="../../../../../@contractNumber"/>
<xsl:text>	</xsl:text>
<xsl:value-of select="../../../../Rights/Window/startDateFormula/fixedDate/DATE/@date"/>
<xsl:text>
</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中是否有一些我没有正确考虑的操作?
答案 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(.) >= $reportStartMonth and xs:date(.) <= $reportEndMonth]]
/RightGroup/cost/costGroup/COSTGROUP[generate-id() = generate-id(key('costGroup', @name)[1])]">
注意,看起来你也试图做Muenchian Groupin。当您使用XSLT 2.0时,请考虑使用xsl:for-each-group
,这将删除使用generate-id()的表达式的可怕部分。