Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using XSDs with includes

Here is an XSD:

<?xml version="1.0"?>
<xsd:schema 
elementFormDefault='unqualified' 
attributeFormDefault='unqualified' 
xmlns:xsd='http://www.w3.org/2001/XMLSchema' 
>

  <xsd:simpleType name='TheSimpleType'>
    <xsd:restriction base='xsd:string' />
  </xsd:simpleType>
</xsd:schema>

Here is a second XSD that includes the one above:

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

  <xsd:include schemaLocation='Include.xsd' />

  <xsd:element name = "TheElement" >
  <xsd:complexType>
  <xsd:attribute name="Code" type="TheSimpleType" use="required"/>
  </xsd:complexType>
  </xsd:element>
</xsd:schema>

I need to read the (second) XSD into C# and:

  1. check that it is a valid XSD, and
  2. validate documents against it.

Here is some C# to read in the schemata:

    XmlSchemaSet schemaSet = new XmlSchemaSet();
    foreach (string sd in Schemas)
    {
        using (XmlReader r = XmlReader.Create(new FileStream(sd, FileMode.Open)))
        {
            schemaSet.Add(XmlSchema.Read(r, null));
        }
    }
    schemaSet.CompilationSettings = new XmlSchemaCompilationSettings();
    schemaSet.Compile();

The .Compile() fails because "Type 'a:TheSimpleType' is not declared, or is not a simple type."

However, it works if either:

  • the namespace is removed from the schema, or
  • the namespace is added to the include.

The question is: how do I get C# to accept it without editing the schemata?

I suspect the problem is that although I have put both schemata into the XmlSchemaSet, I still need to tell C# that one is included into the other, i.e., it hasn't worked it out for itself. Indeed, if I only tell the XmlSchemaSet about the main XSD (and not the include) (both without (or with) namespaces) then "Type 'TheSimpleType' is not declared, or is not a simple type."

Thus this seems to be a question about resolving includes: how?!

like image 261
Richard Barraclough Avatar asked Apr 12 '12 17:04

Richard Barraclough


People also ask

What does include do in XML?

The include element is used to add multiple schemas with the same target namespace to a document.

What is the difference between include and import in XSD?

The difference between the include element and the import element is that import element allows references to schema components from schema documents with different target namespaces and the include element adds the schema components from other schema documents that have the same target namespace (or no specified ...

HOW include XSD in XML?

Reference the XSD schema in the XML document using XML schema instance attributes such as either xsi:schemaLocation or xsi:noNamespaceSchemaLocation. Add the XSD schema file to a schema cache and then connect that cache to the DOM document or SAX reader, prior to loading or parsing the XML document.

How do I add one XSD to another?

xsd" /> where 'res' is a folder where the XSD is residing and this folder is at the same level of the folder from where you are referencing it. If you are giving Absolute path, then you need to write <xs:include schemaLocation="file:D:/workspace/Test/res/header.


2 Answers

The problem is with the way the schema is opened for reading on the line:

XmlReader.Create(new FileStream(sd, FileMode.Open)

I had to write my own XmlResolver before I could see how the paths to the include files were being resolved: it was from the directory of the executable and not from the directory of the parent schema. The problem is that the parent schema was not getting its BaseURI set. Here's how the schema must be opened:

XmlReader.Create(new FileStream(pathname, FileMode.Open, FileAccess.Read),null, pathname)
like image 125
Richard Barraclough Avatar answered Oct 16 '22 13:10

Richard Barraclough


You can use the XmlSchema.Includes to link them together. Then, you just need to add the main schema to the schema set:

var includeSchema = XmlSchema.Read(XmlReader.Create(...), null);
var mainSchema = XmlSchema.Read(XmlReader.Create(...), null);

var include = new XmlSchemaInclude();
include.Schema = includeSchema;
mainSchema.Includes.Add(include);

var schemaSet = new XmlSchemaSet();
schemaSet.Add(mainSchema);
schemaSet.Compile();
like image 33
Jordão Avatar answered Oct 16 '22 13:10

Jordão