XSD条件基于元素值

时间:2012-09-11 20:41:15

标签: .net xml vb.net xsd

我遇到一个具有3个属性的对象: 1)行动 2)身份证 3)姓名

Action可以是UpdateRemove,也是必填项。 ID是一个int并且是必需的。名称是一个字符串,在Action=Remove时是可选的,在Action=Update时是强制性的。

我如何在XSD中描述这一点? 谢谢!

吉姆

这是我到目前为止所做的:

   <s:element name="UpdateAccount">
    <s:complexType>
      <s:sequence>
        <s:element minOccurs="0" maxOccurs="1" name="myAccount" type="tns:WSUpdate" />
      </s:sequence>
    </s:complexType>
  </s:element>
  <s:complexType name="WSUpdate">
    <s:sequence>
      <s:element minOccurs="1" maxOccurs="1" name="ID" type="s:int" />
      <s:element minOccurs="1" maxOccurs="1" name="Name" nillable="false" type="s:string" />
      <s:element minOccurs="1" maxOccurs="1" name="action" type="tns:UpdateAction" />
    </s:sequence>
  </s:complexType>
  <s:simpleType name="UpdateAction">
    <s:restriction base="s:string">
      <s:enumeration value="Update" />
      <s:enumeration value="Remove" />
    </s:restriction>
  </s:simpleType>

编辑2012年9月12日美国东部时间上午9:28 在做了一些更多的思考后,我修补了一些东西。这不是我想要的,但也许足够让我的客户接受。它并没有完全涉及条件细节,但它确实为客户端提供了结构定义。你觉得怎么样?

  <s:element name="UpdateAccount">
    <s:complexType>
      <s:sequence>
        <s:choice>
    <s:element minOccurs="0" maxOccurs="1" name="myAccount" type="tns:WSUpdate" />
    <s:element minOccurs="0" maxOccurs="1" name="myAccount" type="tns:WSDelete" />
    </s:choice>
      </s:sequence>
    </s:complexType>
  </s:element>
  <s:complexType name="WSUpdate">
    <s:sequence>
      <s:element minOccurs="1" maxOccurs="1" name="ID" type="s:int" />
      <s:element minOccurs="1" maxOccurs="1" name="Name" nillable="false" type="s:string" />
      <s:element minOccurs="1" maxOccurs="1" name="action" type="tns:UpdateAction" />
    </s:sequence>
  </s:complexType>
  <s:complexType name="WSDelete">
    <s:sequence>
      <s:element minOccurs="1" maxOccurs="1" name="ID" type="s:int" />
      <s:element minOccurs="0" maxOccurs="1" name="Name" nillable="true" type="s:string" />
      <s:element minOccurs="1" maxOccurs="1" name="action" type="tns:UpdateAction" />
    </s:sequence>
  </s:complexType>
  <s:simpleType name="UpdateAction">
    <s:restriction base="s:string">
      <s:enumeration value="Update" />
      <s:enumeration value="Remove" />
    </s:restriction>
  </s:simpleType>

2 个答案:

答案 0 :(得分:3)

在XSD 1.0中解决问题的一种简单方法是稍微更改问题的术语:将当前WSUpdate元素替换为同名的抽象元素;定义可替代它的UpdateRemove元素。根据需要在UpdateRemove上将属性声明为可选或必需。

在XSD 1.0中检查这样的条件所需要的只是条件取决于元素名称而不是元素的其他属性。

[2012年9月12日编辑:OP要求提供更完整的示例。]

这是一个使用抽象元素的简单例子。

首先,我们使UpdateAccount类型引用其子元素,而不是在本地声明它。这允许其他元素也引用它,并声明自己可以替代它。

<xs:element name="UpdateAccount">
  <xs:complexType>
    <xs:sequence>
      <xs:element minOccurs="0" maxOccurs="1" 
                  ref="tns:myAccount" />
    </xs:sequence>
  </xs:complexType>
</xs:element>

然后我们将myAccount元素本身声明为 abstract 元素。实际上不会接受名为myAccount的元素,只会声明可以替代myAccount的具体元素。

<xs:element name="myAccount" abstract="true"/>

然后我们声明两个可替代myAccount的具体元素,并为它们提供具有适当约束的类型。不再需要action子元素:删除和更新之间的差异现在由元素的名称(update vs remove)给出。

<xs:element name="update" type="tns:WSUpdate" 
            substitutionGroup="tns:myAccount"/>
<xs:complexType name="WSUpdate">
  <xs:sequence>
    <xs:element minOccurs="1" maxOccurs="1" 
                name="ID" type="xs:int" />
    <xs:element minOccurs="1" maxOccurs="1" 
                name="Name" nillable="false" type="xs:string" />
  </xs:sequence>
</xs:complexType>

<xs:element name="remove" type="tns:WSDelete" 
            substitutionGroup="tns:myAccount"/>
<xs:complexType name="WSDelete">
  <xs:sequence>
    <xs:element minOccurs="1" maxOccurs="1" 
                name="ID" type="xs:int" />
    <xs:element minOccurs="0" maxOccurs="1" 
                name="Name" 
                nillable="false" type="xs:string" />
  </xs:sequence>
</xs:complexType>

在某些情况下,可能需要将元素myAccount声明为具有命名类型(如原始示例中的tns:WSUpdate)并声明update和{的类型{1}}作为该类型的限制。这会让这个例子变得更长,更乏味,所以我满足于自己在这里提到它。它是否有意义取决于您对维护架构的人员的信任程度以及您的其他架构感知工具是否会对信息做有用的事情。

答案 1 :(得分:1)

您描述的情况,其中一个属性的规则取决于另一个属性的值,通常被称为“共现约束”,并且在XSD 1.0中无法执行此操作。它在XSD 1.1中完全支持使用称为“条件类型赋值”的机制,但要使用它,您需要采用Saxon或Xerces作为XSD验证器。