我有一些使用XSLT的经验,但现在我遇到了一个问题: 我需要检查开始和结束之间的时间是否完全涵盖其他时期。
这是xml的一部分:
<Parent ID="1">
<StartDate>20050101</StartDate>
<EndDate>20060131</EndDate>
<Child ID="1">
<StartDate>20050101</StartDate>
<EndDate>20081231</EndDate>
</Child>
</Parent>
<Parent ID="2">
<StartDate>20060201</StartDate>
<EndDate>20071231</EndDate>
<Child ID="1">
<StartDate>20050101</StartDate>
<EndDate>20081231</EndDate>
</Child>
</Parent>
<Parent ID="3">
<StartDate>20080101</StartDate>
<EndDate>20081231<EndDate>
<Child ID="1">
<StartDate>20050101</StartDate>
<EndDate>20081231</EndDate>
</Child>
</Parent>
所以我需要检查在XSLT中Child的开始和结束之间的时间段是否完全覆盖Parent的开始和结束之间的时间段,并将父和子ID写入xml失败。
有人能给我一个先掌如何在XSLT中管理它吗?
我可以完全控制XML的结构,所以当使用其他XML结构(使用相同的数据)更容易时,我可以更改它。
非常感谢!
答案 0 :(得分:3)
这是一个在xslt 2.0中直接执行的示例,它应该适用于大多数日期分隔符:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
exclude-result-prefixes="functx xs"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:functx="http://www.functx.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="/">
<dates>
<dateBetween>
<xsl:choose>
<xsl:when test="functx:dateBetween('02-01-2009','01-01-2009','03-01-2009')=true()">
<xsl:text>date lays between given dates</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>date is not between given dates</xsl:text>
</xsl:otherwise>
</xsl:choose>
</dateBetween>
<currentDateBetween>
<xsl:choose>
<xsl:when test="functx:currentDateBetween('01-01-2000','01-01-2019')=true()">
<xsl:text>current date lays between given dates</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>current date is not between given dates</xsl:text>
</xsl:otherwise>
</xsl:choose>
</currentDateBetween>
</dates>
</xsl:template>
<!--
Function: dateBetween
Description: This function will check if a dates is between given dates
Input: Input date, Input start date, Input end date
Output: Boolean true if beween param 2 and 3
Created: 21-09-2012 by Raymond Meester
-->
<xsl:function name="functx:dateBetween">
<xsl:param name="param1"/>
<xsl:param name="param2"/>
<xsl:param name="param3"/>
<xsl:variable name ="dateToCheck" select="functx:mmddyyyy-to-date($param1)"/>
<xsl:variable name ="startDate" select="functx:mmddyyyy-to-date($param2)"/>
<xsl:variable name ="endDate" select="functx:mmddyyyy-to-date($param3)"/>
<xsl:variable name ="true" as="xs:boolean" select="true()"/>
<xsl:variable name ="false" as="xs:boolean" select="false()"/>
<xsl:choose>
<xsl:when test="$startDate < $dateToCheck and $dateToCheck < $endDate"><xsl:value-of select="$true"/></xsl:when>
<xsl:otherwise><xsl:value-of select="$false"/></xsl:otherwise>
</xsl:choose>
</xsl:function>
<!--
Function: currentDateBetween
Description: This function will check if a dates is between given dates
Input: Input date, Input start date, Input end date
Output: Boolean true if beween param 2 and 3
Created: 21-09-2012 by Raymond Meester
-->
<xsl:function name="functx:currentDateBetween">
<xsl:param name="param1"/>
<xsl:param name="param2"/>
<xsl:variable name ="startDate" select="functx:mmddyyyy-to-date($param1)"/>
<xsl:variable name ="endDate" select="functx:mmddyyyy-to-date($param2)"/>
<xsl:variable name ="true" as="xs:boolean" select="true()"/>
<xsl:variable name ="false" as="xs:boolean" select="false()"/>
<xsl:choose>
<xsl:when test="$startDate < current-date() and current-date() < $endDate"><xsl:value-of select="$true"/></xsl:when>
<xsl:otherwise><xsl:value-of select="$false"/></xsl:otherwise>
</xsl:choose>
</xsl:function>
<!--
Function: mmddyyyy-to-date
Description: The functx:mmddyyyy-to-date function converts $dateString into a valid xs:date value. The order of the digits in $dateString must be MMDDYYYY, but it can contain any (or no) delimiters between the digits.
Input: Input string
Output: Return date
Created: 2007-02-26 http://www.xsltfunctions.com/xsl/functx_mmddyyyy-to-date.html
-->
<xsl:function name="functx:mmddyyyy-to-date" as="xs:date?"
xmlns:functx="http://www.functx.com">
<xsl:param name="dateString" as="xs:string?"/>
<xsl:sequence select="if (empty($dateString)) then () else if (not(matches($dateString,'^\D*(\d{2})\D*(\d{2})\D*(\d{4})\D*$'))) then error(xs:QName('functx:Invalid_Date_Format')) else xs:date(replace($dateString,'^\D*(\d{2})\D*(\d{2})\D*(\d{4})\D*$','$3-$1-$2'))"/>
</xsl:function>
</xsl:stylesheet>
答案 1 :(得分:2)
使用简单的字符串比较很容易,因为您的日期格式是big-endian。这是我编写的快速XSLT文档,用于测试它:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" indent="yes"/>
<xsl:template match="/">
<root>
<xsl:for-each select="//Parent">
<parent>
<xsl:attribute name="id">
<xsl:value-of select="@ID"/>
</xsl:attribute>
<xsl:choose>
<xsl:when test="(Child/StartDate <= StartDate) and
(Child/EndDate >= EndDate)">
<xsl:text>OK</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>Not OK</xsl:text>
</xsl:otherwise>
</xsl:choose>
</parent>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
显然,您需要自己检查以确保StartDate
在EndDate
之前为父母和孩子提供。{/ p>
答案 2 :(得分:0)
number(Child/StartDate) <= number(Parent/StartDate) and number(Child/EndDate) >= number(Parent/EndDate)
出了什么问题?
答案 3 :(得分:0)
这不是一个完整的解决方案,但您可能需要查看日期操作的EXSLT扩展here。
但我会考虑使用XSLT extension functions创建几个Joda time's Interval abstractions。可能比直接从XSLT尝试更轻松,更快捷。