我可以使用schematron验证日期范围在xml文件中不重叠吗?

时间:2011-11-23 14:04:11

标签: xml xsd schematron

想象一下,我有一个简单的xml文件:

<intervals>
  <range from="2001-12-17T09:30:47Z" to="2001-12-19T11:35:16Z" />
  <range from="2002-12-17T09:30:47Z" to="2002-12-19T11:35:16Z" />
<intervals>

我想确保给定的日期范围不重叠。显然,我可以在代码中执行此操作,但理想情况下,我希望提供一个验证包以与我的xml架构一起验证某些业务规则。

我可以使用schematron验证范围是否重叠?

1 个答案:

答案 0 :(得分:1)

ISO Schematron是您解决问题的工具。只需使用允许数据输入的XPath 2.0实现。然后你只需要测试一个断言。像<assert test="@from &lt; @to"/>

这样的东西

请参阅:http://www.schematron.com/implementation.html

关于重叠:您可以编写一个XSLT函数,该函数在schematron模式中返回一个布尔值,并从您的测试属性中调用它。

嵌入了XSLT功能的Schematron:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://purl.oclc.org/dsdl/schematron" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:fct="localFunctions" queryBinding="xslt2"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" >
    <ns prefix="fct" uri="localFunctions"/>
    <pattern>
        <rule context="intervals">
            <assert test="fct:checkOverlaping((),range)" >OVERLAPING</assert>
        </rule>
    </pattern>
    <xsl:function name="fct:checkOverlaping" as="xs:boolean">
        <xsl:param name="currentEndDate" as="xs:dateTime?"/>
        <xsl:param name="ranges" as="node()*"/>
        <xsl:choose>
            <xsl:when test="not(exists($currentEndDate))">
                <xsl:variable name="orderedRanges" as="node()*">
                    <xsl:for-each select="$ranges">
                        <xsl:sort select="@from"/>
                        <xsl:copy-of select="."/>
                    </xsl:for-each>
                </xsl:variable>
                <xsl:value-of select="fct:checkOverlaping(xs:dateTime($orderedRanges[position()=1]/@to),$orderedRanges[position()>1])"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="
                    if (not(exists($ranges))) then true() else 
                    if ($currentEndDate > $ranges[position()=1]/@from) then false() else 
                    fct:checkOverlaping($ranges[position()=1]/@to,$ranges[position()>1])
                    "/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:function>
</schema>

使用以下实现:http://www.schematron.com/tmp/iso-schematron-xslt2.zip实现allow-foreign并使用XPath 2.0。当此参数allow-foreign设置为true时,实现将嵌入上述函数。

函数如何工作:第一个循环(currentEndDate未设置)range元素按from个日期排序。其他递归循环(排序后):测试第一个范围的to日期是否在第二个日期的起始日期之前,如果是真,则继续下一个日期(否则为假和停止)。