XML Schema如何通过枚举来限制属性

90

我有以下的XML标签

<price currency="euros">20000.00</price>

我该如何限制货币属性只能是以下三种之一:

  • 欧元
  • 英镑
  • 美元

并将价格限制为双精度浮点数?

当我同时对这两个属性尝试进行类型限制时,会出现错误。这是目前我的代码:

<xs:element name="price">
    <xs:complexType>
        <xs:attribute name="currency">
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:enumeration value="pounds" />
                    <xs:enumeration value="euros" />
                    <xs:enumeration value="dollars" />
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
    </xs:complexType>
</xs:element>

1
如果你这样做,你需要从xs:attribute元素中删除type="xs:string"。当simpleType或complexType存在时,不能指定类型。 - Sal
3个回答

120

您的价格定义中似乎缺少数字值。 请尝试以下操作:

<xs:simpleType name="curr">
  <xs:restriction base="xs:string">
    <xs:enumeration value="pounds" />
    <xs:enumeration value="euros" />
    <xs:enumeration value="dollars" />
  </xs:restriction>
</xs:simpleType>



<xs:element name="price">
        <xs:complexType>
            <xs:extension base="xs:decimal">
              <xs:attribute name="currency" type="curr"/>
            </xs:extension>
        </xs:complexType>
</xs:element>

3
正如 @kjhughes 所回答的那样,<xs:extension> 不能直接作为<xs:complexType> 的子元素,而必须包含在 <xs:complexContent><xs:simpleContent> 中。 - HankCa

27

旧问题的新答案

对于这个旧问题,所有现有的答案都没有解决真正的问题。

真正的问题在于XSD中xs:complexType不能直接将xs:extension作为其子元素。解决方法是首先使用xs:simpleContent。详见以下内容...


您的XML:

<price currency="euros">20000.00</price>

对以下两个经过更正的XSD文件之一有效:

本地定义的属性类型

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="price">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:decimal">
          <xs:attribute name="currency">
            <xs:simpleType>
              <xs:restriction base="xs:string">
                <xs:enumeration value="pounds" />
                <xs:enumeration value="euros" />
                <xs:enumeration value="dollars" />
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
</xs:schema>

全局定义的属性类型

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:simpleType name="currencyType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="pounds" />
      <xs:enumeration value="euros" />
      <xs:enumeration value="dollars" />
    </xs:restriction>
  </xs:simpleType>

  <xs:element name="price">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:decimal">
          <xs:attribute name="currency" type="currencyType"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
</xs:schema>

注意事项

  • 正如@Paul在评论中提到的那样,这些确实将price的内容类型从xs:string更改为xs:decimal,但这并不是严格必要的,也不是真正的问题所在。
  • 如@user998692在回答中所说,您可以分离货币的定义,并将其更改为xs:decimal,但这也不是真正的问题所在。

真正的问题在于,在XSD中,xs:complexType不能直接将xs:extension作为子级; 需要先使用xs:simpleContent

一个相关的问题(虽然没有被问到,但可能会混淆其他答案):

如果元素具有属性,如何限制元素内容?

在这种情况下,需要一个单独的全局定义priceType;仅使用本地类型定义无法实现此目的。

如何限制具有属性的元素内容

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:simpleType name="priceType">  
    <xs:restriction base="xs:decimal">  
      <xs:minInclusive value="0.00"/>  
      <xs:maxInclusive value="99999.99"/>  
    </xs:restriction>  
  </xs:simpleType>

  <xs:element name="price">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="priceType">
          <xs:attribute name="currency">
            <xs:simpleType>
              <xs:restriction base="xs:string">
                <xs:enumeration value="pounds" />
                <xs:enumeration value="euros" />
                <xs:enumeration value="dollars" />
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
</xs:schema>

9

您需要创建一种类型并使该类型的属性:

<xs:simpleType name="curr">
  <xs:restriction base="xs:string">
    <xs:enumeration value="pounds" />
    <xs:enumeration value="euros" />
    <xs:enumeration value="dollars" />
  </xs:restriction>
</xs:simpleType>

然后:
<xs:complexType>
    <xs:attribute name="currency" type="curr"/>
</xs:complexType>

抱歉,这不能同时限制“价格”类型为“double”和“货币”属性的限制枚举。 - Luke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接