【问题标题】:Define an XSD element which can be a dateTime or empty with an attribute定义一个 XSD 元素,它可以是 dateTime 或带有属性的空
【发布时间】:2013-09-13 22:36:34
【问题描述】:

我的问题与this one 几乎完全相同,但针对的是 xs:dateTime 类型而不是用户定义的元素。

我的 XML 中的一个元素(我没有创建)可能如下所示:

<parent>
    ...
    <start>2012-01-01T00:00:00.000</start>
    <end>2013-01-01T00:00:00.000</end>
    ...
</parent>

-或-

<parent>
    ...
    <start reference="a string" />
    <end reference="a string" />
    ...
</parent>

换句话说,在父元素中,“start”和“end”字段可以包含 xs:dateTime 值,或者将为空但具有“reference”属性(任何一个字段都可能是一个或另一个在父级中,它们不一定都是参考或日期时间)。我尝试了各种方法在 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?

【问题讨论】:

    标签: xml xsd


    【解决方案1】:

    1 您可以将元素声明为 nillable(按照 Ben 的建议)。

    2 您可以声明一个简单类型,它是 xs:dateTime 和空字符串的联合。如果我们分阶段构建它,这是最容易遵循的。首先,声明一个命名简单类型,其唯一值是空字符串:

    <xs:simpleType name="empty-string">
      <xs:restriction base="xs:string">
        <xs:enumeration value=""/>
      </xs:restriction>
    </xs:simpleType>
    

    然后声明一个联合类型,其成员为 xs:dateTime 和空字符串:

    <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 内容模型很容易说您必须有一个 dateTime 或一个引用,但前提是这些选项中的每一个都由一个子元素表示。

    【讨论】:

      【解决方案2】:

      如果这些元素为空,我认为不可能将它们验证为 xs:dateTime。如果您可以控制输入 XML,我建议您可以将元素标记为“nil”,并将该元素设置为架构中的 nillable。

      这样做意味着这个片段:

      <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“匹配”函数。

      您还可以声明 xs:simpleTypexs:restrictionxs:pattern 重复 xs:dateTime 的验证。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-29
        • 2012-09-09
        • 1970-01-01
        相关资源
        最近更新 更多