XML和XSD - 使用元素名称替换xsi:type for polymorphism

Ale*_*ing 5 xml polymorphism xsd xsitype

以W3C车辆XSD为例:

<schema xmlns="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://cars.example.com/schema"
           xmlns:target="http://cars.example.com/schema">

  <complexType name="Vehicle" abstract="true"/>

  <complexType name="Car">
    <complexContent>
      <extension base="target:Vehicle"/>
      ...
    </complexContent>
  </complexType>

  <complexType name="Plane">
    <complexContent>
      <extension base="target:Vehicle"/>
      <sequence>
        <element name="wingspan" type="integer"/>
      </sequence>
    </complexContent>
  </complexType>      
</schema>
Run Code Online (Sandbox Code Playgroud)

,以及'meansOfTravel'的以下定义:

<complexType name="MeansOfTravel">
  <complexContent>
    <sequence>        
      <element name="transport" type="target:Vehicle"/>        
    </sequence>
  </complexContent>
</complexType>

<element name="meansOfTravel" type="target:MeansOfTravel"/>
Run Code Online (Sandbox Code Playgroud)

使用此定义,您需要使用xsi:type指定实例的类型,如下所示:

<meansOfTravel>
  <transport xsi:type="Plane">
     <wingspan>3</wingspan>
  </transport>
</meansOfTravel>
Run Code Online (Sandbox Code Playgroud)

我只想实现一个'类型名称' - '元素名称'映射,以便可以用just替换它

<meansOfTravel>
  <plane>
    <wingspan>3</wingspan>
  </plane>
</meansOfTravel>
Run Code Online (Sandbox Code Playgroud)

直到现在我能做到这一点的唯一方法是明确:

<complexType name="MeansOfTravel">
  <sequence>        
    <choice>
      <element name="plane" type="target:Plane"/>
      <element name="car" type="target:Car"/>         
    </choice>
  </sequence>
</complexType>

<element name="meansOfTravel" type="target:MeansOfTravel"/>
Run Code Online (Sandbox Code Playgroud)

但这意味着我必须在'MeansOfTravel'复杂类型中列出所有可能的子类型.如果你调用元素'plane',是否有办法让XML解析器假设你的意思是'Plane'?或者我必须明确做出选择吗?我只想保持我的设计干 - 如果你有任何其他建议(如团体等) - 我都是耳朵.

xcu*_*cut 3

围绕此有一个常见的设计模式,您可以使用子类型(就像您已经在做的那样)和替换组中的元素。取代组中的元素必须是它们所取代的元素的子类型。

不幸的是,替换组元素需要定义为全局元素。所以你会得到这个:

<complexType name="MeansOfTravel">
  <complexContent>
    <sequence>        
      <element ref="transport"/>
    </sequence>
  </complexContent>
</complexType>

<element name="transport" type="target:Vehicle"/>
<element name="plane" type="target:Plane" substitutionGroup="target:transport"/>
Run Code Online (Sandbox Code Playgroud)

然后,在您的 XML 文档中您可以使用:

<meansOfTravel>
    <plane>...</plane>
</meansOfTravel>
Run Code Online (Sandbox Code Playgroud)

有关替代组的更多信息请参见此处。不,不幸的是,解析器无法猜测这一点,因此您仍然必须列出元素:( 不过,与选择相比,有一个优点:模式可以通过导入来外部扩展,而不需要修改它。选择无法扩展。

  • 如果整个模式都在你的控制之下,我会做出选择。除此之外,它使使用数据绑定生成的类更易于阅读,并避免引入所有这些全局元素。 (2认同)