Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to extend a complex type in a different namespace without changing name

Tags:

xml

xsd

I have an existing namespace that I cannot change. I need to add elements to a complex type such that the resulting XML looks like this:

Original XML:

<?xml version="1.0"?>
<Book xmlns="http://bookshop.com">
  <Author>Frank Herbert</Author>
  <Title>Dune</Title>
</Book>

New XML:

<?xml version="1.0"?>
<Book xmlns="http://bookshop.com" 
      xlmns:custom="http://custombookshop.com">
  <Author>Frank Herbert</Author>
  <Title>Dune</Title>
  <custom:Publisher>Ace</custom:Publisher>
</Book>

I have requirements that the custom elements must appear as above with the namespace prefix, and that the complex type name must not change.

Here is the original XSD and the new XSD I've attempted using redefine. Will this work, or is there a better way to accomplish this? Thanks in advance for your advice.

Original XSD:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           xmlns="http://bookshop.com" 
           targetNamespace="bookshop.com">
  <xs:complexType name="Book">
    <xs:complexContent>
      <xs:sequence>
        <xs:element name="Author" type="String32" 
                    minOccurs="1" maxOccurs="1" />
        <xs:element name="Title" type="String32" 
                    minOccurs="1" maxOccurs="1" />
      </xs:sequence>
    </xs:complexContent>
  </xs:complexType>
</xs:schema>

My attempted new XSD:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           xmlns="http://custombookshop.com" 
           targetNamespace="custombookshop.com">
  <xs:redefine schemaLocation="http://bookshop.com">
    <xs:complexType name="Book">
      <xs:complexContent>
        <xs:extension base="Book">
          <xs:sequence>
            <xs:element name="Publisher" type="String32" 
                        minOccurs="1" maxOccurs="1" />
          </xs:sequence>
        </xs:extension>
      </xs:complexContent>
    </xs:complexType>
  </xs:redefine>
</xs:schema>
like image 581
user3708014 Avatar asked Oct 01 '22 15:10

user3708014


1 Answers

Your original schema should declare the sequence inside the complexType:

<xs:complexType name="Book">
    <xs:sequence>
        <xs:element name="Author" type="String32" 
            minOccurs="1" maxOccurs="1" />
        <xs:element name="Title" type="String32" 
            minOccurs="1" maxOccurs="1" />
    </xs:sequence>
</xs:complexType>

It should also declare the targetNamespace equal to the default xmlns namespace, and include the attribute elementFormDefault="qualified" so you can use unqualified elements in your instance. The schema below (to which I added an element declaration and a simpleType declaration) validates your original XML:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns="http://bookshop.com" 
    targetNamespace="http://bookshop.com"
    elementFormDefault="qualified">

    <xs:complexType name="Book">
        <xs:sequence>
            <xs:element name="Author" type="String32" 
                minOccurs="1" maxOccurs="1" />
            <xs:element name="Title" type="String32" 
                minOccurs="1" maxOccurs="1" />
        </xs:sequence>
    </xs:complexType>

    <xs:element name="Book" type="Book"/>

    <xs:simpleType name="String32">
        <xs:restriction base="xs:string"></xs:restriction>
    </xs:simpleType>
</xs:schema>

Assuming that the schema above as your original schema, you can redefine the Book complex type in a new schema with the same target namespace as your original schema. If it needs to contain a Publisher element from another namespace, you have to declare it in a third schema. In a schema with the same target namespace as your original schema, you can redefine the Book type like this (assuming your original schema is in bookshop.xsd:

<xs:redefine schemaLocation="bookshop.xsd">
    <xs:complexType name="Book">
        <xs:complexContent>
            <xs:extension base="Book">
                <xs:sequence>
                    <xs:element ref="cs:Publisher" minOccurs="1" maxOccurs="1" />
                </xs:sequence>
            </xs:extension>
        </xs:complexContent>
    </xs:complexType>
</xs:redefine>

For that to work you have to import the schema where the Publisher element is declared. Suppose it is declared in this schema, with the http://custombookshop.com namespace:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    elementFormDefault="qualified"
    xmlns="http://custombookshop.com" 
    xmlns:bs="http://bookshop.com" 
    targetNamespace="http://custombookshop.com"> 

    <xs:import namespace="http://bookshop.com" schemaLocation="bookshop.xsd"/>
    <xs:element name="Publisher" type="bs:String32" />

</xs:schema>

You can then import it into your redefined schema:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    elementFormDefault="qualified"
    xmlns="http://bookshop.com" 
    targetNamespace="http://bookshop.com"
    xmlns:cs="http://custombookshop.com"> 

    <xs:import schemaLocation="custombookshop.xsd" namespace="http://custombookshop.com"/>

    <xs:redefine schemaLocation="bookshop.xsd">
        ...
    </xs:redefine>

</xs:schema>

And now, you can validate your second XML file using the redefined schema.

like image 62
helderdarocha Avatar answered Oct 05 '22 08:10

helderdarocha