XML 使用 XSD 断言和 Saxon.Api 的日期验证(.NET 版本)

XML date validation using XSD assertion with Saxon.Api (.NET version)

验证规则:当EndDate 不是null/empty 时,EndDate 应大于StartDate。 当我期待 none 时,雇主的最后一次输入出现错误。我做错了什么吗?

XML

<Employers>
    <Employer>
      <StartDate>2020-01-01</StartDate>
      <EndDate></EndDate>
  </Employer>
  <Employer>
      <StartDate>2020-01-01</StartDate>
      <EndDate>2021-01-01</EndDate>
  </Employer>
</Employers>

XSD

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
   <xs:element name="Employers">
      <xs:complexType>
         <xs:sequence>
            <xs:element name="Employer" maxOccurs="unbounded">
               <xs:complexType>
                  <xs:sequence>
                        <xs:element name="StartDate" type="xs:date"></xs:element>
                            <xs:element name="EndDate" minOccurs="0">
                                <xs:simpleType>
                                     <xs:union>
                                    <xs:simpleType>
                                        <xs:restriction base="xs:string">
                                            <xs:minLength value="0" />
                                            <xs:maxLength value="0" />
                                        </xs:restriction>
                                    </xs:simpleType>
                                    <xs:simpleType>
                                        <xs:restriction base="xs:date">
                                        </xs:restriction>
                                    </xs:simpleType>
                                </xs:union>
                                </xs:simpleType>
                            </xs:element>
                        </xs:sequence>
                        <xs:assert test="if (./EndDate eq '') then true() else ./EndDate gt ./StartDate" xmlns:saxon="http://saxon.sf.net/" saxon:message="Error: errors"/>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema> 

稍作更正:
因为您的 EndDate 类型是 xs:stringxs:date 的并集,所以类型可能是其中之一,如果比较类型不匹配,它将失败 - 产生错误。可以通过将其转换为常见类型来修复此错误 - 这里我选择 xs:string。现在它会根据空字符串检查日期的 xs:string 版本,而不是 xs:date 本身。

因此将您的断言更改为

<xs:assert test="if (xs:string(EndDate) eq '') then true() else EndDate gt StartDate" xmlns:saxon="http://saxon.sf.net/" saxon:message="Error: errors" />

现在它应该可以正常工作了。

在定义可以是日期或空的元素时,我的偏好是使用 minLength=0、maxLength=1 的列表类型,而不是使用 xs:date 和零长度字符串的并集.我认为这更好地反映了“空”案例代表“无日期”的语义,而不是存在的东西并且具有日期以外的类型。然后,键入的值始终为 xs:date?,这更符合 XPath 比较运算符的语义:空大小写现在是空序列,而不是字符串。如果这样把EndDate做成列表类型,那么比较就变成了

empty(EndDate) or EndDate gt StartDate

或者如果您愿意,

not(EndDate le StartDate)