My question is almost exactly the same as this one, but for a xs:dateTime type rather than a user defined element.
An element in my XML (which I do not create) can l
1 You can declare the element nillable (as suggested by Ben).
2 You can declare a simple type which is a union of xs:dateTime and the empty string. This is easiest to follow if we build it up in stages. First, declare a named simple type whose sole value is the empty string:
<xs:simpleType name="empty-string">
<xs:restriction base="xs:string">
<xs:enumeration value=""/>
</xs:restriction>
</xs:simpleType>
Then declare a union type whose members are xs:dateTime and empty-string:
<xs:simpleType name="dateTime-or-nothing">
<xs:union memberTypes="xs:dateTime empty-string"/>
</xs:simpleType>
Then use dateTime-or-nothing as the basis for your extension step:
<xs:complexType name="DateOrRef">
<xs:simpleContent>
<xs:extension base="dateTime-or-nothing">
<xs:attribute type="xs:string"
name="reference"
use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
If the reference attribute should occur if and only if the element has no content, then you'll need an XSD 1.1 assertion to that effect (or an ancillary Schematron schema, or ad-hoc validation code at the application layer). XSD content models make it easy to say you must have either a dateTime or a reference, but only if each of those options is represented by a child element.
I don't think it's possible to validate those elements as xs:dateTime if they are empty. If you had control of the input XML, I would suggest that you could mark up the elements as "nil", and set the element to be nillable in the schema.
Doing so means that this fragment:
<parent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<start reference="a string" xsi:nil="true"/>
<end reference="a string" xsi:nil="true"/>
</parent>
...will validate against this schema:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="DateOrRef">
<xs:simpleContent>
<xs:extension base="xs:dateTime">
<xs:attribute type="xs:string" name="reference" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="parent">
<xs:sequence>
<xs:element minOccurs="0" name="start" type="DateOrRef" nillable="true"/>
<xs:element minOccurs="0" name="end" type="DateOrRef" nillable="true"/>
</xs:sequence>
</xs:complexType>
<xs:element name="parent" type="parent"/>
</xs:schema>
Without being able to change the input XML, the best I could come up with is using one or more xs:assertion
elements to validate that the string matches the dateTime format, i.e. using the XPath "matches" function.
You could also declare an xs:simpleType
with an xs:restriction
and xs:pattern
that duplicates the validation of an xs:dateTime.