XSD 多态性不适用于 JAXP?
XSD polymorphism doesn't work with JAXP?
我有一个 XML 这样的:
<members>
<member>
<name>john</name>
<properties>
<age>20</age>
<address>20</address>
</properties>
</member>
<member>
<name>kayla</name>
<properties>
<gender>female</gender>
<address>20</address>
</properties>
</member>
</members>
这里会有几个成员节点,它们共享一个<name>
节点和一个properties
节点。但是,properties
中的元素不同,age+address
或gender+address
都是有效选择。
我试过这样写XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="members" type="membersType"/>
<xs:complexType name="membersType">
<xs:sequence>
<xs:element type="memberType" name="member" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="memberType">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element type="propertiesType" name="properties"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="propertiesType">
<xs:sequence>
<xs:element type="xs:string" name="address"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="propertiesTypeA">
<xs:complexContent>
<xs:extension base="propertiesType">
<xs:sequence>
<xs:element type="xs:string" name="age" minOccurs="0"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="propertiesTypeB">
<xs:complexContent>
<xs:extension base="propertiesType">
<xs:sequence>
<xs:element type="xs:string" name="gender" minOccurs="0"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
我希望这里可以有类似多态性的东西,但是当我使用 JAXP 验证时,它不起作用。
我也尝试使用group
功能,但是2组中有相同的address
元素,因此它仍然不可用。
那么,我应该如何设计XSD?
你可以像下面这样使用
<complexType name="MemberDTO">
<complexContent>
<extension base="tns:MemberEnumValueDTO">
<sequence />
</extension>
</complexContent>
</complexType>
<complexType name="MemberEnumValueDTO">
<sequence>
<element name="name" type="tns:NameEnumTextType" minOccurs="1"
maxOccurs="1" />
</sequence>
</complexType>
<simpleType name="NameEnumTextType">
<restriction base="string">
<enumeration value="john" />
<enumeration value="kayla" />
</restriction>
</simpleType>
您当前的XML架构
使用您的 XML 架构,您的 XML 需要如下所示:
<members xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<member>
<name>john</name>
<properties xsi:type="propertiesTypeA">
<address>20</address>
<age>20</age>
</properties>
</member>
<member>
<name>kayla</name>
<properties xsi:type="propertiesTypeB">
<address>20</address>
<gender>female</gender>
</properties>
</member>
</members>
注意以下事项:
- 继承的属性需要先出现。
- 您需要使用
xsi:type
属性将元素类型覆盖为子类型。
你可能想要什么
在您的 XML 架构中指定 "choice" 可能更适合您。您将不再需要子类型。
<xs:complexType name="propertiesType">
<xs:sequence>
<xs:choice>
<xs:element type="xs:string" name="age"/>
<xs:element type="xs:string" name="gender"/>
</xs:choice>
<xs:element type="xs:string" name="address"/>
</xs:sequence>
</xs:complexType>
我有一个 XML 这样的:
<members>
<member>
<name>john</name>
<properties>
<age>20</age>
<address>20</address>
</properties>
</member>
<member>
<name>kayla</name>
<properties>
<gender>female</gender>
<address>20</address>
</properties>
</member>
</members>
这里会有几个成员节点,它们共享一个<name>
节点和一个properties
节点。但是,properties
中的元素不同,age+address
或gender+address
都是有效选择。
我试过这样写XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="members" type="membersType"/>
<xs:complexType name="membersType">
<xs:sequence>
<xs:element type="memberType" name="member" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="memberType">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element type="propertiesType" name="properties"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="propertiesType">
<xs:sequence>
<xs:element type="xs:string" name="address"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="propertiesTypeA">
<xs:complexContent>
<xs:extension base="propertiesType">
<xs:sequence>
<xs:element type="xs:string" name="age" minOccurs="0"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="propertiesTypeB">
<xs:complexContent>
<xs:extension base="propertiesType">
<xs:sequence>
<xs:element type="xs:string" name="gender" minOccurs="0"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
我希望这里可以有类似多态性的东西,但是当我使用 JAXP 验证时,它不起作用。
我也尝试使用group
功能,但是2组中有相同的address
元素,因此它仍然不可用。
那么,我应该如何设计XSD?
你可以像下面这样使用
<complexType name="MemberDTO">
<complexContent>
<extension base="tns:MemberEnumValueDTO">
<sequence />
</extension>
</complexContent>
</complexType>
<complexType name="MemberEnumValueDTO">
<sequence>
<element name="name" type="tns:NameEnumTextType" minOccurs="1"
maxOccurs="1" />
</sequence>
</complexType>
<simpleType name="NameEnumTextType">
<restriction base="string">
<enumeration value="john" />
<enumeration value="kayla" />
</restriction>
</simpleType>
您当前的XML架构
使用您的 XML 架构,您的 XML 需要如下所示:
<members xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<member>
<name>john</name>
<properties xsi:type="propertiesTypeA">
<address>20</address>
<age>20</age>
</properties>
</member>
<member>
<name>kayla</name>
<properties xsi:type="propertiesTypeB">
<address>20</address>
<gender>female</gender>
</properties>
</member>
</members>
注意以下事项:
- 继承的属性需要先出现。
- 您需要使用
xsi:type
属性将元素类型覆盖为子类型。
你可能想要什么
在您的 XML 架构中指定 "choice" 可能更适合您。您将不再需要子类型。
<xs:complexType name="propertiesType">
<xs:sequence>
<xs:choice>
<xs:element type="xs:string" name="age"/>
<xs:element type="xs:string" name="gender"/>
</xs:choice>
<xs:element type="xs:string" name="address"/>
</xs:sequence>
</xs:complexType>