XML and XSD - use an element name as a replacement for xsi: type for polymorphism

Take the XSD W3C as an example:

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

and the following definition "means OfTravel":

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

With this definition, you need to specify the type of your instance using xsi: type, for example:

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

I just would like to get the name "type name" - "element name" so that it can be replaced simply

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

The only way to do this so far is to make it explicit:

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

But that means that I have to list all the possible subtypes in the complex "MeansOfTravel" type. Isn't there a way to force the XML parser to assume that you mean β€œplane” if you call the β€œplane” of an element? Or do I need to make the choice explicit? I just wanted to keep my DRY design - if you have other suggestions (like groups or so) - I'm all ears.

+4
source share
1 answer

There is a common design pattern, you can use subtypes (as you already do) and elements in the substitution group. Elements in a lookup group must be a subtype of the element for which they are replaced.

Unfortuntaly, members of a substitution group must be defined as global members. So you will have the following:

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

Then in your XML document you can use:

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

Additional information on substitution groups is here . And no, unfortunately, the parser cannot guess about it, so you still have to list the elements :( There is one advantage over the choice: the scheme can be expanded from the outside, importing it without changing it. The selection cannot be expanded.

+3
source

Source: https://habr.com/ru/post/1311522/


All Articles