I am working on a project where I need to generate XML files based on nested XSD's. e.g. ORDER has a reference to PERSON, PERSON has a reference to ADDRESS, etc.
I am creating an `XmlReaderSettings' instance to validate the XSD's, as well as validate the XML after it is generated.
I have added the XSD's as Resources to my assembly. I then create an XmlSchema
instance for each resource, from lowest to highest, and add it to the XmlReaderSettings.Schemas
collection.
However, this fails attempting to add a schema that references another schema. I get an XmlSchemaException: "For element declaration, either the name or the ref attribute must be present."
I have included sample XSD's and source code below:
ADDRESS.xsd - referenced by PERSON.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="ADDRESS.xsd" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ADDRESS" >
<xs:complexType>
<xs:sequence>
<xs:element name="ADDRESS1" type="xs:string"/>
<xs:element name="ADDRESS2" type="xs:string"/>
<xs:element name="CITY" type="xs:string"/>
<xs:element name="STATE" type="xs:string"/>
<xs:element name="ZIP" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
PERSON.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="PERSON.xsd" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="ADDRESS.xsd"/>
<xs:element name="PERSON" >
<xs:complexType>
<xs:sequence>
<xs:element name="L_NAME" type="xs:string"/>
<xs:element name="F_NAME" type="xs:string"/>
<xs:element name="Addresses">
<xs:complexType>
<xs:sequence>
<xs:element ref="ADDRESS" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Sample Code - Load and validate XSD's
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using SchemaTest.Properties;
namespace SchemaTest
{
class Program
{
static void Main(string[] args)
{
// create validation settings instance
var xmlReaderSettings = new XmlReaderSettings
{
ValidationType = ValidationType.Schema,
ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema |
XmlSchemaValidationFlags.ProcessSchemaLocation |
XmlSchemaValidationFlags.ReportValidationWarnings
};
xmlReaderSettings.ValidationEventHandler += SchemaValidationEventHandler;
// added XmlResourceResolver, per the accepted answer below
xMLReaderSettings.Schemas.XmlResolver = new XmlResourceResolver();
// load schemas into validation settings instance
LoadSchema(xmlReaderSettings, Resources.PERSON);
// validate schemas
xmlReaderSettings.Schemas.Compile();
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
private static void LoadSchema(XmlReaderSettings xmlReaderSettings, string schemaString)
{
using (var schemaStream = new MemoryStream(Encoding.Default.GetBytes(schemaString)))
{
var schema = XmlSchema.Read(schemaStream, null);
try
{
xmlReaderSettings.Schemas.Add(schema);
}
catch (Exception ex)
{
Console.WriteLine("EXCEPTION: {0}", ex.Message);
}
}
}
private static void SchemaValidationEventHandler(object sender, ValidationEventArgs e)
{
Console.WriteLine("{0}: {1}", e.Severity, e.Message);
}
}
}
I am not sure if this has anything to do with the ValidationFlags
, but I tried removing XmlSchemaValidationFlags.ProcessSchemaLocation
and still received the same error. I have also tried passing SchemaValidationEventHandler
to the XmlSchema.Read
method (instead of null in sample code), and the schema seems to be created OK, but it still throws the exception when attemtping to add it to the XmlReaderSettings.Schemas
collection.
EDIT - 2011.11.03
I resolved this issue (pun intended) by creating my own XmlUrlResolver
descendent called XmlResourceResolver
, based on the XmlResolver
class example in accepted answer below.
See Question&Answers more detail:
os