现在我有一个可用的XSD:
<Portal layout="blah" />
现在,我想扩展系统,所以我可以做(但我也想支持上面的OLD风格):
<Portal>
<layout xsi:type="type1">
<attribute ... />
<attribute ... />
<attribute ... />
</layout>
</Portal>
<Portal>
<layout xsi:type="type2">
<otherAttribute ... />
<someVal ... />
</layout>
</Portal>
所以我想拥有传统的简单字符串,然后在xsi类型上打开一个更复杂的类型......你不应该把它们混合起来。
这可能吗?
答案 0 :(得分:1)
我尝试简化这样的问题:元素Portal
允许更复杂的组合,例如表示为属性的layout
或表示为元素。所以我们有以下内容模型:
<Portal layout="blah" />
<Portal>
<layout >
<attribute ... />
<attribute ... />
</layout>
</Portal>
为此,您将定义一个基本类型,它是两个内容模型的超集:
<xs:complexType name="PortalBase" abstract="true">
<xs:sequence>
<xs:element ref="layout" minOccurs="0"/>
</xs:sequence>
<xs:attribute ref="layout"/>
</xs:complexType>
此基本类型接受portal
元素,并将可选layout
定义为属性或元素。我们可以通过限制推导出只接受layout
属性的第一种类型:
<xs:complexType name="layoutAttribute">
<xs:complexContent>
<xs:restriction base="PortalBase">
<xs:attribute ref="layout" use="required"/>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
我们可以派生第二种只接受layout
定义为元素的类型:
<xs:complexType name="layoutElement">
<xs:complexContent>
<xs:restriction base="PortalBase">
<xs:sequence>
<xs:element ref="layout" minOccurs="1"/>
</xs:sequence>
<xs:attribute ref="layout" use="prohibited"/>
</xs:restriction>
</xs:complexContent>
</xs:complexType>
我们可以在架构中使用它们将portal
元素定义为类型PortalBase
:
<xs:element name="portal" type="PortalBase"/>
然后我们可以在实例文档中使用它们来声明我们使用的派生类型:
<portal xsi:type= "layoutElement">
<layout attr1=""/>
</portal>
或:
<portal xsi:type= "layoutAttribute" layout="blah"/>
答案 1 :(得分:0)
您可以使用Portal类型定义中的Mixed Content attribute来实现此目的。
类似的东西:
<xs:element name="Portal">
<xs:complexType mixed="true"> <!-- this allows "old school" text content -->
<xs:choice minOccurs="0"> <!-- this allows use of one of the two layout types, or none at all. -->
<xs:element name="Layout1" type="layout1" />
<xs:element name="Layout2" type="layout2" />
</xs:sequence>
</xs:complexType>
</xs:element>
这里的限制是你不能在同一个“grouping”元素中定义具有相同名称的不同类型的元素(在这种情况下是选择元素)