Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unique constraint on a complexType instead of an element

Tags:

xsd

I have the following XSD structure:

<xs:schema xmlns:ns="http://abc/">
  ...
  <xs:element name="abc">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="map"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  ...
  <xs:element name="map">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="entry" type="ns:MapEntryType" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
    <xs:unique name="entry">
      <xs:selector xpath="entry"/>
      <xs:field xpath="key"/>
    </xs:unique>
  </xs:element>
  <xs:complexType name="MapEntryType">
    <xs:sequence>
      <xs:element name="key" type="xs:string"/>
      <xs:element name="value" type="xs:anyType"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

This is doing its job.

The map element now has to be called something different based on whichever is the wrapper, so the name is sometimes map, sometimes properties, sometimes options, etc.

Therefore I want to genericize the map element.

I tried doing the following:

  • Making map a xs:complexType and changing ref to type.
    • This resulted in xs:unique not being accepted and failed
  • Making map a xs:complexType, changing ref to type and moving the xs:unique constraint to the element definitions.
    • This worked but resulted in the XSD having a lot of xs:unique present in the document.

Isn't there a way to simply tell that I want a specific structure and it containing unique elements without having to repeat the unique constraint everywhere?

like image 861
Olivier Grégoire Avatar asked Sep 28 '15 15:09

Olivier Grégoire


2 Answers

As Petru Gardea said in his answer

Both XSD 1.0 and 1.1 place the identity constraints under an element

So you have to add xs:unique to every element, but if you are using XSD 1.1 you can define only once a complete xs:unique and then in the rest of the elements use xs:unique ref="name". This is not valid for you as you are using XSD 1.0, but I let it here for future XSD 1.1 users that find this good question.

Example (namespaces removed for clarity):

<xs:element name="map">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="entry" type="MapEntryType" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
    <!-- Only completely defined once -->
    <xs:unique name="uniqueEntry">
        <xs:selector xpath="entry"/>
        <xs:field xpath="key"/>
    </xs:unique>
</xs:element>

<xs:element name="hashMap">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="entry" type="MapEntryType" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
    <!-- Referenced here and every other time -->
    <xs:unique ref="uniqueEntry"/>
</xs:element>
like image 174
sergioFC Avatar answered Feb 10 '23 16:02

sergioFC


Short answer, it is not possible. Both XSD 1.0 and 1.1 place the identity constraints under an element; a constraint cannot be globally defined, therefore there is no "reuse" per se, other than that of the enclosing element. Given your scenario (different element names for different needs) it is not possible to reuse.

like image 31
Petru Gardea Avatar answered Feb 10 '23 16:02

Petru Gardea