Search code examples
xmluniquealtovaspy

XML Schema: element attribute as unique value?


I'm making XSD schema to validate my XML file generated from java. Its about weather and I want to make value inside date unique.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="forecast">
<xs:complexType>
<xs:sequence>
<xs:element name="city" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="weather">
<xs:complexType>
<xs:sequence>
    <xs:element name="date" maxOccurs="unbounded">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="maxtemp">
                    <xs:simpleType>
                        <xs:restriction base="xs:int"/>
                    </xs:simpleType>
                </xs:element>
                <xs:element name="mintemp" type="xs:int"/>
                <xs:element name="cloudcover">
                    <xs:simpleType>
                        <xs:restriction base="xs:int">
                            <xs:minInclusive value="0"/>
                            <xs:maxInclusive value="100"/>
                        </xs:restriction>
                    </xs:simpleType>
                </xs:element>
                <xs:element name="humidity">
                    <xs:simpleType>
                        <xs:restriction base="xs:int">
                            <xs:minInclusive value="0"/>
                            <xs:maxInclusive value="100"/>
                        </xs:restriction>
                    </xs:simpleType>
                </xs:element>
                <xs:element name="precipitation" type="xs:double"/>
                <xs:element name="windspeed">
                    <xs:simpleType>
                        <xs:restriction base="xs:int">
                            <xs:minInclusive value="0"/>
                            <xs:maxInclusive value="100"/>
                        </xs:restriction>
                    </xs:simpleType>
                </xs:element>
                <xs:element name="description">
                    <xs:simpleType>
                        <xs:restriction base="xs:string">
                            <xs:enumeration value="Heavy rain"/>
                        </xs:restriction>
                    </xs:simpleType>
                </xs:element>
            </xs:sequence>
            <xs:attribute name="value" use="required">
                <xs:simpleType>
                    <xs:restriction base="xs:string">
                        <xs:pattern value="\d\d-\d\d-\d\d"/>
                    </xs:restriction>
                </xs:simpleType>
            </xs:attribute>
        </xs:complexType>
        <xs:unique name="dateuq">
            <xs:selector xpath="date"/>
            <xs:field xpath="@value"/>
        </xs:unique>
    </xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="zip" use="required">
<xs:simpleType>
<xs:restriction base="xs:positiveInteger">
<xs:totalDigits value="5"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

And here is test XML file:

<forecast> 
    <city name="Podgorica" zip="81000">
        <weather>
            <date value="01-01-14">
                <maxtemp>10</maxtemp>
                <mintemp>5</mintemp>
                <cloudcover>40</cloudcover>
                <humidity>20</humidity>
                <precipitation>10.2</precipitation>
                <windspeed>3</windspeed>
                <description>Heavy rain</description>
            </date>
            <date value="01-01-14">
                <maxtemp>10</maxtemp>
                <mintemp>5</mintemp>
                <cloudcover>40</cloudcover>
                <humidity>20</humidity>
                <precipitation>10.2</precipitation>
                <windspeed>3</windspeed>
                <description>Heavy rain</description>
            </date>
        </weather>
    </city>
</forecast>

So this should not be passing validation here because value should be unique, why this isn't working?


Solution

  • You placed the uniqueness constraint in date, but it doesn't make any sense in that context. You can declare an uniqueness constraint for date in the weather context (or in a higher context such as city or forecast.

    To guarantee an unique data for each weather declare it inside the weather element declaration:

    <xs:element name="weather">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="date" maxOccurs="unbounded">
                    <xs:complexType> 
                     ...
                    </xs:complexType>
                    <!-- remove it from here -->
                </xs:element>
            </xs:sequence>
        </xs:complexType>
        <!-- and place it here -->
        <xs:unique name="dateuq">
            <xs:selector xpath="date"/>
            <xs:field xpath="@value"/>
        </xs:unique>
    </xs:element>