4

I am trying to use data within an element without breaking this element existing contract.
Let's simplify my case:

<xs:element name="ExistingContract">
     <xs:complexType>
          <xs:sequence>
               <xs:element name="first" type="FirstType"/>
               <xs:element name="second" type="SecondType"/>
          </xs:sequence> 
      </xs:complexType>
</xs:element>

<xs:element name="NewContract">
     <xs:complexType>
          <xs:sequence>
               <xs:element name="first" type="FirstType"/>
               <xs:element name="second" type="SecondType"/>
               <xs:element name="additionalData" type="AdditionalDataType"/>
          </xs:sequence> 
      </xs:complexType>
</xs:element>

These two inner types are duplicated, and I want to avoid it. Since there isn't any existing wrapping xs:complexType for the inner data, I can take it out from ExistingContract and use it in my NewContract. But then I will break the first contract (which I don't want to).

Are you familiar with any XSD method that I can keep the first contract the same and extract its inner data to my new contract?

kjhughes
  • 106,133
  • 27
  • 181
  • 240
Rotem.O
  • 93
  • 1
  • 11

2 Answers2

4

In addition to the technique described by @kjhughes, you can use a named ModelGroup:

<xs:group name="common">
    <xs:sequence>
      <xs:element name="first" type="FirstType"/>
      <xs:element name="second" type="SecondType"/>
    </xs:sequence>
</xs:group> 

<xs:complexType name="ExistingContractType">
   <xs:sequence>
    <xs:group ref="common"> 
   </xs:sequence>
</xs:complexType>

<xs:complexType name="NewContractType">
   <xs:sequence>
    <xs:group ref="common">
    <xs:element name="additionalData" type="AdditionalDataType"/> 
   </xs:sequence>
</xs:complexType>

Both these are very similar from the point of view of maintainability. There is a difference in terms of instance validation: a type derived by extension can be used in place of the base type if you specify xsi:type on the instance element, unless you block it. They might also have different results if you are using data binding tools (I don't know), and you might feel that they have different "semantics" in terms of modelling the real-world relationship between the objects being represented.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
3

You can use xs:extension to extend NewContractType from ExistingContractType:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="ExistingContract" type="ExistingContractType"/>

  <xs:complexType name="ExistingContractType">
    <xs:sequence>
      <xs:element name="first" type="FirstType"/>
      <xs:element name="second" type="SecondType"/>
    </xs:sequence> 
  </xs:complexType>

  <xs:complexType name="NewContractType">
    <xs:complexContent>
      <xs:extension base="ExistingContractType">
        <xs:sequence>
          <xs:element name="additionalData" type="AdditionalDataType"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:element name="NewContract" type="NewContractType"/>

  <xs:complexType name="FirstType"/>
  <xs:complexType name="SecondType"/>
  <xs:complexType name="AdditionalDataType"/>

</xs:schema>
kjhughes
  • 106,133
  • 27
  • 181
  • 240