我的问题与this one几乎完全相同,但对于xs:dateTime类型而不是用户定义的元素。
我的XML中的元素(我没有创建)可能如下所示:
<parent>
...
<start>2012-01-01T00:00:00.000</start>
<end>2013-01-01T00:00:00.000</end>
...
</parent>
-OR -
<parent>
...
<start reference="a string" />
<end reference="a string" />
...
</parent>
换句话说,在父元素中,“start”和“end”字段可以包含xs:dateTime值,或者为空但具有“reference”属性(任一字段可能是一个或另一个)在父母中,他们不一定既是引用又是dateTime都是。我已尝试过各种方法在XSD中表示这一点,但还没有找到解决方案。我最接近的是(摘自更大的XSD):
<?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"> This does not validate-->
<xs:extension base="xs:string">
<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" />
<xs:element minOccurs="0" name="end" type="DateOrRef" />
</xs:sequence>
</xs:complexType>
</xs:schema>
确认,但不限制节点内容为xs:dateTime值。如果我将扩展基类型更改为xs:dateTime而不是注释掉的xs:string,则空元素将不再验证,因为不允许dateTime类型为空。
我如何构建XSD以将这些字段验证为xs:dateTime而不是xs:string?
答案 0 :(得分:10)
1您可以声明元素为nillable(由Ben建议)。
2您可以声明一个简单类型,它是xs:dateTime和空字符串的并集。如果我们分阶段建立它,这是最容易遵循的。首先,声明一个命名的简单类型,其唯一值为空字符串:
<xs:simpleType name="empty-string">
<xs:restriction base="xs:string">
<xs:enumeration value=""/>
</xs:restriction>
</xs:simpleType>
然后声明一个union类型,其成员是xs:dateTime和empty-string:
<xs:simpleType name="dateTime-or-nothing">
<xs:union memberTypes="xs:dateTime empty-string"/>
</xs:simpleType>
然后使用dateTime-or-nothing作为扩展步骤的基础:
<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>
如果且当且仅当元素没有内容时才会出现引用属性,那么您将需要XSD 1.1断言(或辅助Schematron架构,或应用层的临时验证代码)。 XSD内容模型可以很容易地说您必须拥有日期时间或引用,但前提是每个选项都由子元素表示。
答案 1 :(得分:0)
我不认为将这些元素验证为xs:dateTime如果它们为空。如果你控制了输入XML,我建议你可以将元素标记为“nil”,并将元素设置为在模式中可以为空。
这样做就意味着这个片段:
<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>
...将验证此架构:
<?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>
无法更改输入XML,我能想到的最好的方法是使用一个或多个xs:assertion
元素来验证字符串是否与dateTime格式匹配,即使用XPath“matches”函数。
您还可以声明xs:simpleType
xs:restriction
和xs:pattern
,复制xs:dateTime的验证。