XSD:属性</xs:choice>的<xs:choice>等价物

时间:2014-02-28 09:54:10

标签: xml xsd

我希望创建一个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>

3 个答案:

答案 0 :(得分:1)

您可以使用“类型”替换,例如

<?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”究竟是什么类型。但它可能是你的一种方式。

答案 1 :(得分:0)

使用断言或条件类型赋值很容易在XSD 1.1中实现所需,但在XSD 1.0中无法实现。

XSD 1.1目前由Saxon,Xerces和Altova支持。

答案 2 :(得分:0)

您可以使用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>