根据枚举值需要xsd属性集

时间:2013-05-28 08:28:22

标签: xsd xsd-validation

我的项目遵循xsd我试图根据付款方式枚举属性为xmls ACH和CC制作单个xsd,如果付款方式是Ach则需要ACHInfo,否则为CreditCardInfo ..

<xs:element name="PaymentMethod">
  <xs:simpleType>
    <xs:restriction base="xs:string">
      <xs:enumeration value="ACH"/>
      <xs:enumeration value="CreditCard"/>
    </xs:restriction>
  </xs:simpleType>
</xs:element>
<xs:element name="CreditCardInfo" minOccurs="0">
  <xs:complexType>
    <xs:all>
      <xs:element name="Cvv2No">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:maxLength value="4"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element name="CardNumber">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:maxLength value="20"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
     </xs:all>
  </xs:complexType>
</xs:element>
<xs:element name="ACHInfo" minOccurs="0">
  <xs:complexType>
    <xs:all>
      <xs:element name="RoutingNumber" nillable="false">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:maxLength value="50"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element name="AccountNumber" nillable="false">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:maxLength value="50"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
    </xs:all>
  </xs:complexType>
</xs:element>

任何人都可以为我提供解决方案,根据枚举值,xsd需要进行哪些更改以使属性成为必需。

感谢。

1 个答案:

答案 0 :(得分:18)

四种解决方案,其中一些涉及重新考虑信息的XML表示:

XSD 1.1断言

完成所描述内容的最简单方法是使用XSD 1.1并使用断言定义您所考虑的约束。你没有说出父元素被调用了什么;我称之为付款。我将使用前缀tns作为目标命名空间。

<xs:element name="Payment">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="tns:PaymentMethod"/>
      <xs:choice>
        <xs:element ref="tns:ACHInfo" minOccurs="0"/>
        <xs:element ref="tns:CreditCardInfo" minOccurs="0"/>
      </xs:choice>
    </xs:sequence>
    <xs:assert test="(tns:PaymentType = 'ACH' and ./tns:ACHInfo)
                     or
                     (tns:PaymentType = 'CreditCard' 
                       and ./tns:CreditCardInfo)"/>
  </xs:complexType>
</xs:element>

XSD 1.1条件类型赋值

出于某些目的,更好的方法是使用条件类型分配(也是1.1功能)进行付款。由于技术原因,这需要将PaymentType作为Payment的属性,而不是子项:

<xs:element name="Payment">
  <xs:alternative test="@PaymentMethod='ACH'" 
                  type="tns:ACHPayment"/>
  <xs:alternative test="@PaymentMethod='CreditCard'" 
                  type="tns:CCPayment"/>
  <xs:alternative type="xs:error"/>
</xs:element>

此声明表示:如果PaymentMethod属性的值为“ACH”,则元素Payment的类型为tns:ACHPayment(我们稍后会定义)。否则,如果PaymentMethod的值是“CreditCard”,那么付款的类型是tns:CCPayment。否则,该元素无效。

我们声明命名类型ACHPayment和CCPayment包含适当的子节点(并且还提供了PaymentMethod属性) - 我们可以内联它们,但命名它们使条件类型分配模式更容易看到:

<xs:complexType name="ACHPayment">
  <xs:sequence>
    <xs:element ref="tns:ACHPayment"/>
  </xs:sequence>
  <xs:attribute name="PaymentMethod" type="tns:PaymentMethod"/>
</xs:complexType>

<xs:complexType name="CCPayment">
  <xs:sequence>
    <xs:element ref="tns:CreditCardPayment"/>
  </xs:sequence>
  <xs:attribute name="PaymentMethod" type="tns:PaymentMethod"/>
</xs:complexType>

出于同样的原因,我们为PaymentMethod属性的类型提供了一个命名声明:

<xs:simpleType name="PaymentMethod">
  <xs:restriction base="xs:string">
    <xs:enumeration value="ACH"/>
    <xs:enumeration value="CreditCard"/>
  </xs:restriction>
</xs:simpleType>

XSD 1.0,将支付方式转移到内容模型

但是,您不需要XSD 1.1来制作适合您应用程序的XML;你只需要对你的设计有不同的看法。如果您在元素名称而不是内容中选择付款类型,则很容易使ACH付款和信用卡付款所需的CreditCardInfo成为必需的ACHinfo。而不是将父类型定义为:

<xs:complexType>
  <xs:sequence>
    <xs:element ref="tns:PaymentMethod"/>
    <xs:element ref="CreditCardInfo" minOccurs="0"/>
    <xs:element ref="ACHInfo" minOccurs="0"/>
  </xs:sequence>
</xs:complexType>
你可以用这种方式声明:

<xs:complexType>
  <xs:choice>
    <xs:sequence>
      <xs:element ref="tns:ACHPayment"/>
      <xs:element ref="tns:ACHInfo" minOccurs="0"/>
    </xs:sequence>
    <xs:sequence>
      <xs:element ref="tns:CCPayment"/>
      <xs:element ref="tns:CreditCardInfo" minOccurs="0"/>
    </xs:sequence>       
  </xs:choice>
</xs:complexType>

CCPayment和ACHPayment这两个标志元素可以是空元素:

<xs:complexType name="EMPTY">
  <xs:sequence/>
</xs:complexType>

<xs:element name='ACHPayment' type="tns:EMPTY"/>
<xs:element name='CCPayment' type="tns:EMPTY"/>

但事实上,这些都不是在设计中做任何工作。

XSD 1.0,简化

如果ACHPayment和CCPayment元素都没有做任何工作,除了(a)表明付款使用这种方法,以及(b)确保以下兄弟是正确的,那么他们都没有做任何工作。

您可以通过这种方式轻松定义父元素:

<xs:element name="Payment">
  <xs:complexType>
    <xs:choice>
      <xs:element ref="tns:ACHInfo" minOccurs="0"/>
      <xs:element ref="tns:CreditCardInfo" minOccurs="0"/>
    </xs:choice>
  </xs:complexType>
</xs:element>

您仍然可以查看付款是否为ACH付款(付款元素的子名称为ACHInfo)或信用卡付款(该子名称为CreditCardInfo),您不再需要检查以确保详细信息与PaymentMethod标志一致,因为PaymentMethod标志已经消失。

移动部件少,做得少,出错少。

在这四种设计中,我认为第四种设计可能是最好的。当然,您的里程可能会有所不同。