Reputation: 13
The validation rule: The EndDate should be greater than the StartDate when EndDate is not null/empty. I'm getting an error on the last entry of employer while I'm expecting none. Am I doing something wrong?
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>
Upvotes: 1
Views: 85
Reputation: 163282
My preference when defining an element that can be either a date or empty is to use a list type with minLength=0, maxLength=1, rather than using a union of xs:date and zero-length string. I think this better reflects the semantics that the "empty" case represents "no date" rather than being something that exists and has a type other than date. The typed value is then always xs:date?
, which plays better into the semantics of XPath comparison operators: the empty case is now an empty sequence, not a string. If you make EndDate
a list type in this way, then the comparison becomes
empty(EndDate) or EndDate gt StartDate
or if you prefer,
not(EndDate le StartDate)
Upvotes: 1
Reputation: 29022
Make one minor correction:
Because your EndDate
type is a union of xs:string
and xs:date
the type could be one or the other and it would fail if the type of the comparison does not match - yielding the error. This error can be fixed by casting it to a common type - here I chose xs:string
. Now it checks the xs:string
version of your date against the empty string and not the xs:date
itself.
So change your assertion to
<xs:assert test="if (xs:string(EndDate) eq '') then true() else EndDate gt StartDate" xmlns:saxon="http://saxon.sf.net/" saxon:message="Error: errors" />
Now it should work as desired.
Upvotes: 1