我的项目遵循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需要进行哪些更改以使属性成为必需。
感谢。
答案 0 :(得分:18)
四种解决方案,其中一些涉及重新考虑信息的XML表示:
完成所描述内容的最简单方法是使用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>
出于某些目的,更好的方法是使用条件类型分配(也是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.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"/>
但事实上,这些都不是在设计中做任何工作。
如果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标志已经消失。
移动部件少,做得少,出错少。
在这四种设计中,我认为第四种设计可能是最好的。当然,您的里程可能会有所不同。