Search code examples
xmlxsdxsd-validationxml-validation

XSD for mandatory elements followed by any additional optional elements?


I need to validate XML. XML should contain the following tags - country, population, area, capital. Any additional tag (ex: citycode) should be okay even if it's not part of the XSD. My requirement is, I need to accept XML requests coming only from valid source. Hence I need to check if the request I receive is the one I am expecting since it contains few fields at least which is included in XSD.

I created the below XSD, but I am getting an error:

Error: Element 'citycode': No matching global element declaration available, but demanded by the strict wildcard.

XML

<?xml version="1.0"?>
<country>
  <population>32225560</population>
  <area>652000</area>
  <capital>Kabul</capital>
  <citycode>123</citycode>
</country>

XSD

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="country">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="population" type="xs:integer"/>
        <xs:element name="area" type="xs:integer"/>
        <xs:element name="capital" type="xs:string"/>
        <xs:any minOccurs="0"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Solution

  • Change

    <xs:any minOccurs="0"/>
    

    to

    <xs:any processContents="lax" minOccurs="0"/>
    

    or

    <xs:any processContents="skip" minOccurs="0"/>
    

    The default value of processContents is strict, which means it's a validation violation if the XSD processor is unable to obtain the XSD definition for, in this case, citycode, and use it to successfully validate the element(s) at the position of the xsd:any. The other processContents options allow for the element(s) to be undefined: lax won't require definitions but will check the element(s) against any found definitions; skip will allow the element(s) without validating them even if definitions are found.

    Note that if you wish to allow more than one optional element, add maxOccurs="unbounded" to xs:any because the default allows only up to 1 element.

    See also