Search code examples
c#xmlvalidationnamespaces

XML schema includes schema without Namespace compile error in C#


I have a shared XML schema which has not namespace declared department.xsd

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
            elementFormDefault="qualified"
            attributeFormDefault="unqualified"
            version="1-0">
    
    <xs:complexType name="Department">
        <xs:sequence>
            <xs:element name="Name"/>
            <xs:element name="Manager"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

And I want to import Department.xsd in Company.xsd which has the namespace MainNameSpace. I have tried all four solutions below, but none of them worked. Where did I get wrong here? Thanks

Solution 1 Error: "'Type 'MainNameSpace:Department' is not declared.'".

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns="MainNameSpace"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="MainNameSpace"
           elementFormDefault="unqualified"
           attributeFormDefault="unqualified">

    <xs:import schemaLocation="Department.xsd"/>

    <xs:element name="company" type="Company"/>

    <xs:complexType name="Company">
        <xs:sequence>
            <xs:element name="Name" type="xs:string"/>
            <xs:element name="Department" type="Department"/>
        </xs:sequence>
    </xs:complexType>

</xs:schema>


Solution 2 Error: Namespace attribute of an import must not match the real value of the enclosing targetNamespace of the .

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns="MainNameSpace"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:m="MainNameSpace"
           targetNamespace="MainNameSpace"
           elementFormDefault="unqualified"
           attributeFormDefault="unqualified">

    <xs:import schemaLocation="Department.xsd" namespace="MainNameSpace"/>

    <xs:element name="company" type="Company"/>

    <xs:complexType name="Company">
        <xs:sequence>
            <xs:element name="Name" type="xs:string"/>
            <xs:element name="Department" type="m:Department"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

Solution 3 Error: Type 'dummy_namespace:Department' is not declared.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns="MainNameSpace"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:m="dummy_namespace"
           targetNamespace="MainNameSpace"
           elementFormDefault="unqualified"
           attributeFormDefault="unqualified">

    <xs:import schemaLocation="Department.xsd" namespace="dummy_namespace"/>

    <xs:element name="company" type="Company"/>

    <xs:complexType name="Company">
        <xs:sequence>
            <xs:element name="Name" type="xs:string"/>
            <xs:element name="Department" type="m:Department"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

Solution 4 Error: Type 'MainNameSpace:Department' is not declared.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns="MainNameSpace"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="MainNameSpace"
           elementFormDefault="unqualified"
           attributeFormDefault="unqualified">

    <xs:include schemaLocation="Department.xsd"/>

    <xs:element name="company" type="Company"/>

    <xs:complexType name="Company">
        <xs:sequence>
            <xs:element name="Name" type="xs:string"/>
            <xs:element name="Department" type="Department"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

C# code is below:

    var schema = new XmlSchemaSet();

    schema.Add(null, Path.Combine(baseDirectory, "Department.xsd"));
    schema.Add(null, Path.Combine(baseDirectory, "Company.xsd"));

    schema.Compile();

Solution

  • Solution 1 fails because type="Department" is a reference to a type with local name Department in the default namespace. The default namespace (declared using xmlns=...) is MainNameSpace and there is no type Department in that namespace. The Saxon error message, if it helps, is:

    Error on line 15 of test.xsd:
       Unknown type Q{MainNameSpace}Department
    Error on line 15 of test.xsd:
       The type {Department} is referenced, but has not been declared
    

    Solutions 2 and 3 fail because the namespace on the xs:import doesn't match the actual targetNamespace of the schema document identified.

    Solution 4 succeeds in Saxon. It relies on a rather obscure feature of the XSD specification often called "chameleon include". (The actual term is used in the XSD 1.1 specification, but the feature is already present, without that name, in XSD 1.0). It's pretty well covered by a single sentence in §4.2.1:

    Such included schema documents must either (a) have the same targetNamespace as the including schema document, or (b) no targetNamespace at all, in which case the included schema document is converted to the including schema document's targetNamespace.

    It looks from your evidence as if the Microsoft schema processor does not implement this feature.

    I think you should be able to make it work using solution 1, but modifying the reference to the Department type to say:

    <xs:element name="Department" type="Department" xmlns=""/>
    

    so that Department is treated as being in no namespace.