How to restrict the value of an XML element using xsi:type in XSD?

I would like to validate text values of an element based on attribute value. For example

<Device xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Parameter xsi:type="xsd:unsignedInt">-100</Parameter>
  <Parameter xsi:type="xsd:boolean"></Parameter>
  <Parameter>hello</Parameter>
</Device>

Both the above should fail. For boolean, anything shouldn't be accepted except "true" or "false" (even empty string)

My xml is much more complex with lot of Object and Parameter nodes and this is my xsd which is validating all those nodes recursively

    <xs:complexType name="deviceType">
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                    <xs:element ref="Object"/>
                    <xs:element ref="Parameter"/>
            </xs:choice>
    </xs:complexType>

    <xs:complexType name="objType">
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                    <xs:element ref="Object"/>
                    <xs:element ref="Parameter"/>
            </xs:choice>
            <!-- Add all valid attributes for 'Object' type here -->
            <xs:attribute name="Id" use="required"/>
            <xs:attribute name="Flag" use="required"/>
            <xs:anyAttribute processContents="lax"/>
    </xs:complexType>

    <xs:complexType name="paramType" mixed="true">
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                    <xs:element ref="Object"/>
                    <xs:element ref="Parameter"/>
            </xs:choice>
            <xs:attribute name="Id" use="required"/>
            <xs:attribute name="Flag" use="required"/>
            <xs:anyAttribute processContents="lax"/>
    </xs:complexType>

But I'm facing this error.

Type 'xsd:unsignedInt' is not validly derived from the type definition, 'paramType', of element 'Parameter'.
Type 'xsd:unsignedInt' is not validly derived from the type definition, 'paramType', of element 'Parameter'.

How can I fix this?


Solution 1:

To use xsi:type in your XML document:

  1. Declare the xsi namespace prefix, usually on the root element:

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    
  2. Declare the xs (or xsd) namespace prefix, usually on the root element:

    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    
  3. Add any XSD type to the element you wish to constrain:

    xsi:type="xs:boolean"
    

These changes are made directly in your XML document. You do not have to make any changes to your XSD. However, the chosen type must be validly derived from the type provided by the XSD for the given element.


Relevant W3C References

From XML Schema Part 1: Structures Second Edition...

2.6.1 xsi:type

The Simple Type Definition (§2.2.1.2) or Complex Type Definition (§2.2.1.3) used in ·validation· of an element is usually determined by reference to the appropriate schema components. An element information item in an instance may, however, explicitly assert its type using the attribute xsi:type. The value of this attribute is a ·QName·; see QName Interpretation (§3.15.3) for the means by which the ·QName· is associated with a type definition.

[...]

Validation Rule: Element Locally Valid (Element)

4.3 The ·local type definition· must be validly derived from the {type definition} given the union of the {disallowed substitutions} and the {type definition}'s {prohibited substitutions}, as defined in Type Derivation OK (Complex) (§3.4.6) (if it is a complex type definition), or given {disallowed substitutions} as defined in Type Derivation OK (Simple) (§3.14.6) (if it is a simple type definition).

From XML Schema Part 2: Datatypes Second Edition...

3 Built-in datatypes

enter image description here