Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

At least one XML element with no duplicates in XSD

I'm trying to create a validation scenario where I want to choose at least one non-repeating element from a list.

Somewhere along the lines of:

<xs:choice minOccurs="1" maxOccurs="7">
    <xs:element name="Sunday"/>
    <xs:element name="Monday"/>
    <xs:element name="Tuesday"/>
    <xs:element name="Wednesday"/>
    <xs:element name="Thursday"/>
    <xs:element name="Friday"/>
    <xs:element name="Saturday"/>
</xs:choice>

However the above solution allows duplicate elements to appear in a list, which I don't want.

Example of a valid XML:

<Monday/>
<Tuesday/>
<Friday/>

Example of an invalid XML:

<Monday/>
<Monday/>

Can this be achieved with an XSD without having to hardcode all the possible sequences? If so how?

like image 680
Daniel André Avatar asked Jan 28 '16 14:01

Daniel André


People also ask

What is minOccurs 1 in XSD?

When "minOccurs=1" is contained within an XML Schema Definition (XSD), it means that the first occurrence of the element is required. The element does not need to contain any data, it just needs to be present.

What is complexType and simpleType in XSD?

XSD elements can be of type simpleType , complexType , or anyType . An element of type simpleType contains only text. It cannot have attributes and elements. An element of type complexType can contain text, elements, and attributes.

What does complexType mean in XSD?

The complexType element defines a complex type. A complex type element is an XML element that contains other elements and/or attributes.

What is Nillable in XSD?

The nillable attribute can be defined on an xsd:element within an XML schema. It specifies that the xsi:nil attribute is valid for the element. If an XML schema has defined the nillable attribute as true, it is mapped as a required attribute and is included in the document, however, its values are nullified.


1 Answers

XSD 1.0 Solution

I do not believe your constraint can be expressed in XSD 1.0 "without having to hardcode all the possible sequences" (but see C. M. Sperberg-McQueen's clever solution that cuts down the combinatorics considerably) . The values of elements could be forced to be unique using xsd:unique, but subset of XPath used by xsd:unique does not include name(), which could otherwise help make a uniqueness statement about the names of the elements.

XSD 1.1 Solution

Your constrain can be expressed in XSD 1.1 using xs:assert:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" elementFormDefault="qualified"
  vc:minVersion="1.1">
  <xs:element name="Days">
    <xs:complexType>
      <xs:choice minOccurs="1" maxOccurs="7">
        <xs:element name="Sunday"/>
        <xs:element name="Monday"/>
        <xs:element name="Tuesday"/>
        <xs:element name="Wednesday"/>
        <xs:element name="Thursday"/>
        <xs:element name="Friday"/>
        <xs:element name="Saturday"/>
      </xs:choice>
      <xs:assert test="count(*[name() = following-sibling::*/name()]) = 0"/>
    </xs:complexType>
  </xs:element>  
</xs:schema>
like image 86
kjhughes Avatar answered Sep 23 '22 14:09

kjhughes