我可以设置XSD,以便在具有不同基本类型的两个属性之间共享xs:枚举 - xs:ID和xs:string

时间:2012-10-19 12:27:19

标签: xml xsd xsd-validation

我正在尝试确定如何修改我的XSD以在XML中的两个位置使用枚举但具有不同的数据类型。我正在使用Visual Studio 2010作为我的XML编辑器。

想象一下一个XML文档,其中包含两种类型的车辆和所述车辆的订单。规则如下:

  • 每辆车必须具有唯一的属性 - 模型 - 所以属性 应该是xs:ID类型。
  • 每个订单可以有多辆车,所以 model属性应为xs:string等类型。

这是我的XML文件 - Test.xml

<?xml version="1.0" encoding="utf-8" ?>

<sample xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="Test.xsd">
  <vehicles>
    <vehicle model="Equinox" />
    <vehicle model="Impala"/>
    <!-- This should not be allowed because it's not unique -->
    <vehicle model="Impala" />
    <!-- This should not be allowed because it is not a valid model -->
    <vehicle model="Apple" />
  </vehicles>
  <orders>
    <order orderid="123">
      <item quantity="3"  model="Equinox" />
      <item quantity="2"  model="Impala" />
      <item quantity="3"  model="Impala" />
    </order>
  </orders>
</sample>

这是我的XSD文件 - Test.xsd(与XML位于同一位置)

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           attributeFormDefault="unqualified"
           elementFormDefault="qualified"
           xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="sample">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="vehicles">
          <xs:complexType>
            <xs:sequence>
              <xs:element maxOccurs="unbounded" name="vehicle">
                <xs:complexType>
                  <!-- this instance of model should be unique -->
                  <xs:attribute name="model" type="UniqueModel" use="required" />
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="orders">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="order">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="item" maxOccurs="unbounded">
                      <xs:complexType>
                        <xs:attribute name="quantity" type="xs:unsignedByte" use="required" />
                        <!-- this instance of model can be repeated -->
                        <xs:attribute name="model" type="ModelList" use="required" />
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                  <xs:attribute name="orderid" type="xs:unsignedByte" use="required" />
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:simpleType name="UniqueModel">
    <xs:restriction base="xs:ID">
      <!-- I want to import ModelList here-->
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="ModelList">
    <xs:union memberTypes="ChevyModelList DodgeModelList" />
  </xs:simpleType>

  <xs:simpleType name="ChevyModelList">
    <xs:restriction base="xs:normalizedString">
      <xs:enumeration value="Equinox" />
      <xs:enumeration value="Impala" />
    </xs:restriction>
  </xs:simpleType>

  <xs:simpleType name="DodgeModelList">
    <xs:restriction base="xs:normalizedString">
      <xs:enumeration value="Charger" />
      <xs:enumeration value="Ram" />
    </xs:restriction>
  </xs:simpleType>

</xs:schema>

我已经完成了许多Google和Stack Overflow搜索,试图确定这是否可行,但找不到任何相关内容。

也许我需要回到我原来的想法 - 这是使用xs:unique来限制数据。我不能让这个工作:

<xs:element name="vehicles">
  <!-- vehicle complexType here -->
  <xs:unique name="uniqueModel">
    <xs:selector xpath="vechicle" />
    <xs:field xpath="@model" />
  </xs:unique>
</xs:element>

任何有关获得任何一种解决方案的帮助都会很棒!

谢谢! 萨德

1 个答案:

答案 0 :(得分:2)

xs:ID类型不仅仅意味着唯一性,它还将值限制为有效的XML名称,这特别意味着没有空格而不是以数字开头(例如,您不能拥有)一个名为“307”的标致车型。我可能通过使用密钥来解决问题

<xs:element name="sample">
  <xs:key name="modelName">
    <xs:selector xpath="vehicles/vehicle" />
    <xs:field xpath="@model" />
  </xs:key>
  <xs:keyRef name="orderModel" refer="modelName">
    <xs:selector xpath="orders/order/item" />
    <xs:field xpath="@model" />
  </xs:keyRef>

并使vehicle元素的model属性属于ModelList类型。 key应该确保vehicles中的模型名称是唯一的,keyRef检查每个订单项中提到的模型实际上是vehicles下列出的模型之一。这样,您实际上根本不需要限制item/@model属性的类型,它可能只是普通xs:string,因为keyRef会强制执行枚举。