XSD:元素和属性之间的选择

axe*_*rod 3 xml xsd jaxb

我想要一个具有内容或某个属性的元素,但不能同时具有两者。元素可以如下所示:

<Location ref="blah"/>
Run Code Online (Sandbox Code Playgroud)

或这个:

<Location> <aaaLocation>...</aaaLocation> <Location>
Run Code Online (Sandbox Code Playgroud)

但不是这样的:

 <Location ref="blah"> <aaaLocation>...</aaaLocation> <Location>
Run Code Online (Sandbox Code Playgroud)

我尝试了一些变化:

<xs:complexType name="FatherOfLocatiion">
        <xs:choice>
            <xs:element name="Location">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name ="aaaLocation" type="Alocation"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
            <xs:element name="Location">
                <xs:complexType>
                    <xs:attribute name="ref" type="xs:string" />
                </xs:complexType>
            </xs:element>
        </xs:choice>
        <xs:attribute name="name" type="xs:string" use="required"/>
    </xs:complexType>
Run Code Online (Sandbox Code Playgroud)

该模式在XML spy等工具中有效,但是当我尝试使用jaxb从中生成对象时,出现以下错误:

模型组中会出现多个名称为“ Location”且具有不同类型的元素。

还有其他方法可以强制执行吗?

Pet*_*dea 5

在XSD 1.0中有一种方法可以做到这一点,其中涉及到使用xsi:type属性。xsi:type是XML属性,但是,支持XSD的XML处理器将按照您想要的方式对其进行不同的处理。(为完整起见,此方法是XSD 1.1中替代类型的先驱,这是实现所需目标的另一种方法)。

鉴于以下XSD 1.0:

<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="Location"/>
    <xsd:complexType name="LocationWithRef">
        <xsd:attribute name="ref" type="xsd:string" use="required"/>
    </xsd:complexType>
    <xsd:complexType name="LocationWithContent">
        <xsd:sequence>
            <xsd:element name="a"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:schema> 
Run Code Online (Sandbox Code Playgroud)

以下XML是有效的,但没有其他组合;具有属性:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<Location xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="LocationWithRef" ref="a"/>
Run Code Online (Sandbox Code Playgroud)

带有元素:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<Location xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="LocationWithContent"><a/></Location>
Run Code Online (Sandbox Code Playgroud)

以上内容足以对您在XML世界中指出的内容进行建模。但是,对于XSD编码绑定技术,您需要采取额外的步骤使其变得友好,例如JAXB(或.NET)。事情是将它们与抽象的基本类型(在下面是ALocation)链接起来。

<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="Location" type="ALocation"/>
    <xsd:complexType name="ALocation" abstract="true"/>
    <xsd:complexType name="LocationWithRef">
        <xsd:complexContent>
            <xsd:extension base="ALocation">
                <xsd:attribute name="ref" type="xsd:string" use="required"/>                
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
    <xsd:complexType name="LocationWithContent">
        <xsd:complexContent>
            <xsd:extension base="ALocation">
                <xsd:sequence>
                    <xsd:element name="a"/>
                </xsd:sequence>             
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
</xsd:schema> 
Run Code Online (Sandbox Code Playgroud)

上面的优点是,它基于几乎任何现有XSD处理器都支持的技术,为您提供了您所要求的(alas,xsi:type可能不适合您或其他人喜欢)。

不幸的是,对XSD 1.1的支持非常有限,如果我不得不猜测,它需要一段时间才能被JAXB支持(您似乎对此很感兴趣),更不用说其他XSD到代码绑定解决方案了。 。