代码之家  ›  专栏  ›  技术社区  ›  Alexander Torstling

XML和XSD-使用元素名替换多态性的xsi:type

  •  5
  • Alexander Torstling  · 技术社区  · 15 年前

    以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>
    

    以及“meansoftravel”的以下定义:

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

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

    <meansOfTravel>
      <transport xsi:type="Plane">
         <wingspan>3</wingspan>
      </transport>
    </meansOfTravel>
    

    我只想实现“类型名称”-“元素名称”映射,以便用

    <meansOfTravel>
      <plane>
        <wingspan>3</wingspan>
      </plane>
    </meansOfTravel>
    

    到目前为止,我唯一能做到这一点的方法是把它明确化:

    <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"/>
    

    但这意味着我必须在“meanSoftravel”复杂类型中列出所有可能的子类型。如果调用元素“plane”,是否无法使XML解析器假定您的意思是“plane”?还是我必须明确选择?我只想保持我的设计干燥-如果你有任何其他的建议(如团体或其他),我全神贯注。

    1 回复  |  直到 15 年前
        1
  •  3
  •   xcut    15 年前

    围绕这一点有一个常见的设计模式,您可以使用子类型(正如您已经做的那样),以及替换组中的元素。替换组中的元素必须是被替换元素的子类型。

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

    <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"/>
    

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

    <meansOfTravel>
        <plane>...</plane>
    </meansOfTravel>
    

    有关替换组的详细信息 here . 不,不幸的是,解析器无法猜到这一点,所以您仍然需要列出元素:(尽管与选择相比,有一个优势:模式可以通过导入而不修改,从外部扩展。无法扩展选择。