我希望创建一个XML文档,其中必须使用两个已知属性之一(但不能同时定义两个)来定义其元素之一。
例如,我想如下定义“ webAddress”元素:
<xs:element name="webAddress">
<xs:complexType>
<xs:attribute name="hostName" type="xs:string"/>
<xs:attribute name="hostAddress" type="xs:string"/>
</xs:complexType>
</xs:element>
但是我只希望用户能够定义hostName属性(例如,hostName =“”)或hostAddress(例如,hostAddress =“”)属性,但不能同时定义两者。似乎该构造为元素完成了此操作。是否有功能上等效的属性,或者有更好的方法来解决此问题?
[如果发现我们无法使用W3C XML Schema执行此操作。我们可以使用嵌入的schematron规则,但是可以通过同时检查元素和属性来在选择元素上做到这一点吗?例如这样的东西:
<xs:choice>
<xs:element name="webAddress">
<xs:complexType>
<xs:attribute name="hostName" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="webAddress">
<xs:complexType>
<xs:attribute name="hostAddress" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:choice>
您可以使用“类型”替换,例如
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<!-- Some abstract type - it might define some common parts too. It is abstract and cannot be used directly for instance -->
<xs:complexType name="abstractType" abstract="true"/>
<!-- First "children" type of abstract type-->
<xs:complexType name="hostNameType">
<xs:complexContent>
<!-- it is derived from abstractType and adds attribute hostName -->
<xs:extension base="abstractType">
<xs:attribute name="hostName" type="xs:string" use="required" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
<!-- Second "children" type of abstract type -->
<xs:complexType name="hostAddressType">
<xs:complexContent>
<!-- it is also derived from abstractType and adds attribute hostAddress -->
<xs:extension base="abstractType">
<xs:attribute name="hostAddress" type="xs:string" use="required" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
<!-- Element of abstractType -->
<xs:element name="webAddress" type="abstractType" />
</xs:schema>
在实例文档中,您必须指定实际使用的类型:
<?xml version="1.0" encoding="UTF-8"?>
<!-- by xsi:type you defined which "concrete" type is really used -->
<webAddress xsi:type="hostNameType" hostName="String" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
或
<?xml version="1.0" encoding="UTF-8"?>
<webAddress xsi:type="hostAddressType" hostAddress="xxxx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
但是该定义有点冗长,而且乍一看“ webAddress”实际上是什么类型也不是很明显。但这可能是您的一种方式。
使用断言或条件类型分配很容易在XSD 1.1中实现所需的功能,但是在XSD 1.0中是不可能的。
[SSDon,Xerces和Altova当前支持XSD 1.1。
您可以使用XSD密钥来实现:
<xs:element name="webAddress">
<xs:complexType>
<xs:attribute name="hostName" type="xs:string" use="optional" />
<xs:attribute name="hostAddress" type="xs:string" use="optional" />
</xs:complexType>
<!-- Validate either name or address attribute specified (but not both). -->
<xs:key name="WebAddressHostNameOrAddressAttributePresent">
<xs:selector xpath="." />
<xs:field xpath="@hostName | @hostAddress" />
</xs:key>
</xs:element>