private void LoadExternals(XmlSchema schema) {
if (schema.IsProcessing) {
return;
}
schema.IsProcessing = true;
foreach(XmlSchemaExternal include in schema.Includes) {
Uri includeLocation = null;
//CASE 1: If the Schema object of the include has been set
XmlSchema includedSchema = include.Schema;
if (includedSchema != null) {
// already loaded
includeLocation = includedSchema.BaseUri;
if (includeLocation != null && schemaLocations[includeLocation] == null) {
schemaLocations.Add(includeLocation, includedSchema);
}
LoadExternals(includedSchema);
continue;
}
//CASE 2: Try & Parse schema from the provided location
string schemaLocation = include.SchemaLocation;
Uri ruri = null;
Exception innerException = null;
if (schemaLocation != null) {
try {
ruri = ResolveSchemaLocationUri(schema, schemaLocation);
}
catch(Exception e) {
ruri = null;
innerException = e;
}
}
if (include.Compositor == Compositor.Import) {
XmlSchemaImport import = include as XmlSchemaImport;
Debug.Assert(import != null);
string importNS = import.Namespace != null ? import.Namespace : string.Empty;
if (!schema.ImportedNamespaces.Contains(importNS)) {
schema.ImportedNamespaces.Add(importNS);
}
//CASE 2.1: If the imported namespace is the XML namespace,
// If the parent schemaSet already has schema for XML ns loaded, use that
// Else if the location is null use the built-in one
// else go through regular processing of parsing from location
if (importNS == XmlReservedNs.NsXml) {
if (ruri == null) { //Resolved location is null, hence get the built-in one
include.Schema = Preprocessor.GetBuildInSchema();
continue;
}
}
}
//CASE 3: Parse schema from the provided location
if (ruri == null) {
if (schemaLocation != null) {
SendValidationEvent(new XmlSchemaException(Res.Sch_InvalidIncludeLocation, null, innerException, include.SourceUri, include.LineNumber, include.LinePosition, include), XmlSeverityType.Warning);
}
continue;
}
if (schemaLocations[ruri] == null) { // Only if location already not processed
object obj = null;
try {
obj = GetSchemaEntity(ruri);
}
catch(Exception eInner) {
innerException = eInner;
obj = null;
}
if (obj != null) {
include.BaseUri = ruri;
Type returnType = obj.GetType();
if (typeof(XmlSchema).IsAssignableFrom(returnType)) { //To handle XmlSchema and all its derived types
include.Schema = (XmlSchema)obj;
schemaLocations.Add(ruri, include.Schema);
LoadExternals(include.Schema);
}
else {
XmlReader reader = null;
if (returnType.IsSubclassOf(typeof(Stream)) ) {
readerSettings.CloseInput = true;
readerSettings.XmlResolver = xmlResolver;
reader = XmlReader.Create((Stream)obj, readerSettings, ruri.ToString() );
}
else if (returnType.IsSubclassOf(typeof(XmlReader)) ) {
reader = (XmlReader)obj;
}
else if (returnType.IsSubclassOf(typeof(TextReader))) {
readerSettings.CloseInput = true;
readerSettings.XmlResolver = xmlResolver;
reader = XmlReader.Create((TextReader)obj, readerSettings, ruri.ToString() );
}
if (reader == null) {
SendValidationEvent(Res.Sch_InvalidIncludeLocation, include, XmlSeverityType.Warning);
continue;
}
try {
Parser parser = new Parser(SchemaType.XSD, NameTable, SchemaNames, EventHandler);
parser.Parse(reader, null);
while(reader.Read());// wellformness check
includedSchema = parser.XmlSchema;
include.Schema = includedSchema;
schemaLocations.Add(ruri, includedSchema);
LoadExternals(includedSchema);
}
catch(XmlSchemaException e) {
SendValidationEvent(Res.Sch_CannotLoadSchemaLocation, schemaLocation, e.Message, e.SourceUri, e.LineNumber, e.LinePosition);
}
catch(Exception eInner) {
SendValidationEvent(new XmlSchemaException(Res.Sch_InvalidIncludeLocation, null, eInner, include.SourceUri, include.LineNumber, include.LinePosition, include), XmlSeverityType.Warning);
}
finally {
reader.Close();
}
}
}
else {
SendValidationEvent(new XmlSchemaException(Res.Sch_InvalidIncludeLocation, null, innerException, include.SourceUri, include.LineNumber, include.LinePosition, include), XmlSeverityType.Warning);
}
}
else { //Location already in table and now seeing duplicate import / include
include.Schema = (XmlSchema)schemaLocations[ruri]; //Set schema object even for duplicates
}
}
}