xmlxsd

Confusion about controlling XSD type substitution


The following XSD defines the complex types Base, which specifies block="", and Derived, which extends Base and also specifies block="".

<?xml version="1.0" encoding="utf-8"?>

<xs:schema
    targetNamespace ="http://example.org/scratch-type-substitution"
    xmlns           ="http://example.org/scratch-type-substitution"
    xmlns:xs        ="http://www.w3.org/2001/XMLSchema"
    blockDefault    ="">
  
  <xs:complexType name="Base" block=""/>

  <xs:complexType name="Derived" block="">
    <xs:complexContent>
      <xs:extension base="Base"/>
    </xs:complexContent>
  </xs:complexType>

  <xs:element name="root">
    <xs:complexType>
      <xs:choice maxOccurs="unbounded">
        <xs:element name="base" type="Base"/>     
      </xs:choice>
    </xs:complexType>
  </xs:element>
  
</xs:schema>

The following instance is valid per the XSD. It specifies a Base type element which is explicitly substituted by the Derived type via xsi:type:

<pre:root
  xmlns:pre="http://example.org/scratch-type-substitution"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <base xsi:type="pre:Derived"/>
  
</pre:root>

However, if the attribute blockDefault="#all" is added to <schema>, the instance fails validation. In particular, the .NET 8.0 XmlDocument method Load emits:

The xsi:type attribute value 'http://example.org/scratch-type-substitution:Derived' is not valid for the element 'base', either because it is not a type validly derived from the type in the schema, or because it has xsi:type derivation blocked.

I don't think the former could be true. If the latter is true, I don't understand why, given that the PSVI information for both types' resolved block attribute values is 'Empty' -and- that an empty string (or any value) overrides the blockDefault value.


Solution

  • The Saxon schema validator gives the same results. Here is the error message:

    Validation error on line 5 column 33 of test.xml: FORG0001: The xsi:type is not validly derived from the declared type. Derivation of the requested type Q{http://example.org/scratch-type-substitution}Derived is blocked either by the base type Q{http://example.org/scratch-type-substitution}Derived or by the element declaration See https://www.w3.org/TR/xmlschema11-1/#cvc-elt clause 4.3

    I think the last bit gives the clue: although the type declaration overrides blockDefault, the element declaration doesn't.

    Changing the element declaration to

    <xs:element name="base" type="Base" block=""/>   
    

    fixes it.