-//\r
-// System.Xml.Schema.XmlSchema.cs\r
-//\r
-// Author:\r
-// Dwivedi, Ajay kumar Adwiv@Yahoo.com\r
-// Atsushi Enomoto ginga@kit.hi-ho.ne.jp\r
-//\r
-using System;\r
-using System.Collections;\r
-using System.Xml;\r
-using System.IO;\r
-using System.Xml.Serialization;\r
-using System.ComponentModel;\r
-\r
-namespace System.Xml.Schema\r
-{\r
- /// <summary>\r
- /// Summary description for XmlSchema.\r
- /// </summary>\r
- [XmlRoot("schema",Namespace=XmlSchema.Namespace)]\r
- public class XmlSchema : XmlSchemaObject\r
- {\r
- //public constants\r
- public const string Namespace = "http://www.w3.org/2001/XMLSchema";\r
- public const string InstanceNamespace = "http://www.w3.org/2001/XMLSchema-instance";\r
-\r
- //private fields\r
- private XmlSchemaForm attributeFormDefault ;\r
- private XmlSchemaObjectTable attributeGroups ;\r
- private XmlSchemaObjectTable attributes ;\r
- private XmlSchemaDerivationMethod blockDefault ;\r
- private XmlSchemaForm elementFormDefault ;\r
- private XmlSchemaObjectTable elements ;\r
- private XmlSchemaDerivationMethod finalDefault ;\r
- private XmlSchemaObjectTable groups ;\r
- private string id ;\r
- private XmlSchemaObjectCollection includes ;\r
- private XmlSchemaObjectCollection items ;\r
- private XmlSchemaObjectTable notations ;\r
- private XmlSchemaObjectTable schemaTypes ;\r
- private string targetNamespace ;\r
- private XmlAttribute[] unhandledAttributes ;\r
- private string version;\r
- private string language;\r
-\r
- // other post schema compilation infoset\r
- private Hashtable idCollection;\r
- private XmlSchemaObjectTable namedIdentities;\r
- private XmlSchemaCollection schemas;\r
-\r
- private XmlNameTable nameTable;\r
-\r
- internal bool missedSubComponents;\r
-\r
- // Only compilation-time use\r
- private XmlSchemaObjectCollection compilationItems;\r
- private Hashtable handledUris;\r
-\r
- // Compiler specific things\r
- const string xmlname = "schema";\r
-\r
- public XmlSchema()\r
- {\r
- attributeFormDefault= XmlSchemaForm.None;\r
- blockDefault = XmlSchemaDerivationMethod.None;\r
- elementFormDefault = XmlSchemaForm.None;\r
- finalDefault = XmlSchemaDerivationMethod.None;\r
- includes = new XmlSchemaObjectCollection();\r
- isCompiled = false;\r
- items = new XmlSchemaObjectCollection();\r
- attributeGroups = new XmlSchemaObjectTable();\r
- attributes = new XmlSchemaObjectTable();\r
- elements = new XmlSchemaObjectTable();\r
- groups = new XmlSchemaObjectTable();\r
- notations = new XmlSchemaObjectTable();\r
- schemaTypes = new XmlSchemaObjectTable();\r
- idCollection = new Hashtable ();\r
- namedIdentities = new XmlSchemaObjectTable();\r
- }\r
-\r
- #region Properties\r
-\r
- [DefaultValue(XmlSchemaForm.None)]\r
- [System.Xml.Serialization.XmlAttribute("attributeFormDefault")]\r
- public XmlSchemaForm AttributeFormDefault\r
- {\r
- get{ return attributeFormDefault; }\r
- set{ this.attributeFormDefault = value;}\r
- }\r
-\r
- [DefaultValue(XmlSchemaDerivationMethod.None)]\r
- [System.Xml.Serialization.XmlAttribute("blockDefault")]\r
- public XmlSchemaDerivationMethod BlockDefault\r
- {\r
- get{ return blockDefault;}\r
- set{ blockDefault = value;}\r
- }\r
-\r
- [DefaultValue(XmlSchemaDerivationMethod.None)]\r
- [System.Xml.Serialization.XmlAttribute("finalDefault")]\r
- public XmlSchemaDerivationMethod FinalDefault\r
- {\r
- get{ return finalDefault;}\r
- set{ finalDefault = value;}\r
- }\r
-\r
- [DefaultValue(XmlSchemaForm.None)]\r
- [System.Xml.Serialization.XmlAttribute("elementFormDefault")]\r
- public XmlSchemaForm ElementFormDefault\r
- {\r
- get{ return elementFormDefault;}\r
- set{ elementFormDefault = value;}\r
- }\r
-\r
- [System.Xml.Serialization.XmlAttribute("targetNamespace")]\r
- public string TargetNamespace\r
- {\r
- get{ return targetNamespace;}\r
- set{ targetNamespace = value;}\r
- }\r
-\r
- [System.Xml.Serialization.XmlAttribute("version")]\r
- public string Version\r
- {\r
- get{ return version;}\r
- set{ version = value;}\r
- }\r
-\r
- [XmlElement("include",typeof(XmlSchemaInclude),Namespace="http://www.w3.org/2001/XMLSchema")]\r
- [XmlElement("import",typeof(XmlSchemaImport),Namespace="http://www.w3.org/2001/XMLSchema")]\r
- [XmlElement("redefine",typeof(XmlSchemaRedefine),Namespace="http://www.w3.org/2001/XMLSchema")]\r
- public XmlSchemaObjectCollection Includes\r
- {\r
- get{ return includes;}\r
- }\r
-\r
- [XmlElement("simpleType",typeof(XmlSchemaSimpleType),Namespace="http://www.w3.org/2001/XMLSchema")]\r
- [XmlElement("complexType",typeof(XmlSchemaComplexType),Namespace="http://www.w3.org/2001/XMLSchema")]\r
- [XmlElement("group",typeof(XmlSchemaGroup),Namespace="http://www.w3.org/2001/XMLSchema")]\r
- //Only Schema's attributeGroup has type XmlSchemaAttributeGroup.\r
- //Others (complextype, restrictions etc) must have XmlSchemaAttributeGroupRef\r
- [XmlElement("attributeGroup",typeof(XmlSchemaAttributeGroup),Namespace="http://www.w3.org/2001/XMLSchema")]\r
- [XmlElement("element",typeof(XmlSchemaElement),Namespace="http://www.w3.org/2001/XMLSchema")]\r
- [XmlElement("attribute",typeof(XmlSchemaAttribute),Namespace="http://www.w3.org/2001/XMLSchema")]\r
- [XmlElement("notation",typeof(XmlSchemaNotation),Namespace="http://www.w3.org/2001/XMLSchema")]\r
- [XmlElement("annotation",typeof(XmlSchemaAnnotation),Namespace="http://www.w3.org/2001/XMLSchema")]\r
- public XmlSchemaObjectCollection Items\r
- {\r
- get{ return items;}\r
- }\r
-\r
- [XmlIgnore]\r
- public bool IsCompiled\r
- {\r
- get{ return this.CompilationId != Guid.Empty;}\r
- }\r
-\r
- [XmlIgnore]\r
- public XmlSchemaObjectTable Attributes\r
- {\r
- get{ return attributes;}\r
- }\r
-\r
- [XmlIgnore]\r
- public XmlSchemaObjectTable AttributeGroups\r
- {\r
- get{ return attributeGroups; }\r
- }\r
-\r
- [XmlIgnore]\r
- public XmlSchemaObjectTable SchemaTypes\r
- {\r
- get{ return schemaTypes; }\r
- }\r
-\r
- [XmlIgnore]\r
- public XmlSchemaObjectTable Elements\r
- {\r
- get{ return elements;}\r
- }\r
-\r
- [System.Xml.Serialization.XmlAttribute("id")]\r
- public string Id\r
- {\r
- get{ return id;}\r
- set{ id = value;}\r
- }\r
-\r
- [XmlAnyAttribute]\r
- public XmlAttribute[] UnhandledAttributes\r
- {\r
- get\r
- {\r
- if(unhandledAttributeList != null)\r
- {\r
- unhandledAttributes = (XmlAttribute[]) unhandledAttributeList.ToArray(typeof(XmlAttribute));\r
- unhandledAttributeList = null;\r
- }\r
- return unhandledAttributes;\r
- }\r
- set\r
- {\r
- unhandledAttributes = value;\r
- unhandledAttributeList = null;\r
- }\r
- }\r
-\r
- [XmlIgnore]\r
- public XmlSchemaObjectTable Groups\r
- {\r
- get{ return groups;}\r
- }\r
-\r
- [XmlIgnore]\r
- public XmlSchemaObjectTable Notations\r
- {\r
- get{ return notations;}\r
- }\r
-\r
- internal Hashtable IDCollection\r
- {\r
- get { return idCollection; }\r
- }\r
-\r
- internal XmlSchemaObjectTable NamedIdentities\r
- {\r
- get { return namedIdentities; }\r
- }\r
-\r
- internal XmlSchemaCollection Schemas\r
- {\r
- get { return schemas; }\r
- }\r
- #endregion\r
-\r
- #region Compile\r
-\r
- // Methods\r
- /// <summary>\r
- /// This compile method does two things:\r
- /// 1. It compiles and fills the PSVI dataset\r
- /// 2. Validates the schema by calling Validate method.\r
- /// Every XmlSchemaObject has a Compile Method which gets called.\r
- /// </summary>\r
- /// <remarks>\r
- /// 1. blockDefault must be one of #all | List of (extension | restriction | substitution)\r
- /// 2. finalDefault must be one of (#all | List of (extension | restriction| union| list))\r
- /// 3. id must be of type ID\r
- /// 4. targetNamespace should be any uri\r
- /// 5. version should be a normalizedString\r
- /// 6. xml:lang should be a language\r
- /// </remarks>\r
- public void Compile (ValidationEventHandler handler)\r
- {\r
- Compile (handler, new XmlUrlResolver ());\r
- }\r
-\r
-#if NET_1_0\r
- internal void Compile (ValidationEventHandler handler, XmlResolver resolver)\r
-#else\r
- public void Compile (ValidationEventHandler handler, XmlResolver resolver)\r
-#endif\r
- {\r
- Compile (handler, new Stack (), this, null, resolver);\r
- isCompiled = true;\r
- }\r
-\r
- internal void Compile (ValidationEventHandler handler, XmlSchemaCollection col, XmlResolver resolver)\r
- {\r
- Compile (handler, new Stack (), this, col, resolver);\r
- }\r
-\r
- private void Compile (ValidationEventHandler handler, Stack schemaLocationStack, XmlSchema rootSchema, XmlSchemaCollection col, XmlResolver resolver)\r
- {\r
- if (rootSchema != this) {\r
- CompilationId = rootSchema.CompilationId;\r
- schemas = rootSchema.schemas;\r
- }\r
- else {\r
- schemas = col;\r
- if (schemas == null) {\r
- schemas = new XmlSchemaCollection ();\r
- schemas.SchemaSet.CompilationId = Guid.NewGuid ();\r
- }\r
- CompilationId = schemas.SchemaSet.CompilationId;\r
- this.idCollection.Clear ();\r
- }\r
- schemas.Add (this);\r
-\r
- attributeGroups.Clear ();\r
- attributes.Clear ();\r
- elements.Clear ();\r
- groups.Clear ();\r
- notations.Clear ();\r
- schemaTypes.Clear ();\r
-\r
- //1. Union and List are not allowed in block default\r
- if(BlockDefault != XmlSchemaDerivationMethod.All)\r
- {\r
- if((BlockDefault & XmlSchemaDerivationMethod.List)!=0 )\r
- error(handler, "list is not allowed in blockDefault attribute");\r
- if((BlockDefault & XmlSchemaDerivationMethod.Union)!=0 )\r
- error(handler, "union is not allowed in blockDefault attribute");\r
- }\r
-\r
- //2. Substitution is not allowed in finaldefault.\r
- if(FinalDefault != XmlSchemaDerivationMethod.All)\r
- {\r
- if((FinalDefault & XmlSchemaDerivationMethod.Substitution)!=0 )\r
- error(handler, "substitution is not allowed in finalDefault attribute");\r
- }\r
-\r
- //3. id must be of type ID\r
- XmlSchemaUtil.CompileID(Id, this, this.IDCollection, handler);\r
-\r
- //4. targetNamespace should be of type anyURI or absent\r
- if(TargetNamespace != null)\r
- {\r
- if(!XmlSchemaUtil.CheckAnyUri(TargetNamespace))\r
- error(handler, TargetNamespace+" is not a valid value for targetNamespace attribute of schema");\r
- }\r
-\r
- //5. version should be of type normalizedString\r
- if(!XmlSchemaUtil.CheckNormalizedString(Version))\r
- error(handler, Version + "is not a valid value for version attribute of schema");\r
-\r
- //6. xml:lang must be a language\r
-// if(!XmlSchemaUtil.CheckLanguage(Language))\r
-// error(handler, Language + " is not a valid language");\r
-\r
- // Compile the content of this schema\r
-\r
- compilationItems = new XmlSchemaObjectCollection ();\r
- for (int i = 0; i < Items.Count; i++)\r
- compilationItems.Add (Items [i]);\r
- if (this == rootSchema)\r
- handledUris = new Hashtable ();\r
-\r
- // First, we run into inclusion schemas to collect \r
- // compilation target items into compiledItems.\r
- for (int i = 0; i < Includes.Count; i++) {\r
- XmlSchemaExternal ext = Includes [i] as XmlSchemaExternal;\r
- if (ext != null) {\r
- if (ext.SchemaLocation == null) \r
- continue;\r
- Stream stream = null;\r
- string url = null;\r
- if (resolver != null) {\r
- url = GetResolvedUri (resolver, ext.SchemaLocation);\r
- if (schemaLocationStack.Contains (url)) {\r
- error(handler, "Nested inclusion was found: " + url);\r
- // must skip this inclusion\r
- continue;\r
- }\r
- if (rootSchema.handledUris.Contains (url))\r
- // This schema is already handled, so simply skip (otherwise, duplicate definition errrors occur.\r
- continue;\r
- rootSchema.handledUris.Add (url, url);\r
- try {\r
- stream = resolver.GetEntity (new Uri (url), null, typeof (Stream)) as Stream;\r
- } catch (Exception) {\r
- // LAMESPEC: This is not good way to handle errors, but since we cannot know what kind of XmlResolver will come, so there are no mean to avoid this ugly catch.\r
- warn (handler, "Could not resolve schema location URI: " + url);\r
- stream = null;\r
- }\r
- }\r
-\r
- // Process redefinition children in advance.\r
- XmlSchemaRedefine redefine = Includes [i] as XmlSchemaRedefine;\r
- if (redefine != null) {\r
- for (int j = 0; j < redefine.Items.Count; j++) {\r
- XmlSchemaObject redefinedObj = redefine.Items [j];\r
- redefinedObj.isRedefinedComponent = true;\r
- redefinedObj.isRedefineChild = true;\r
- if (redefinedObj is XmlSchemaType ||\r
- redefinedObj is XmlSchemaGroup ||\r
- redefinedObj is XmlSchemaAttributeGroup)\r
- compilationItems.Add (redefinedObj);\r
- else\r
- error (handler, "Redefinition is only allowed to simpleType, complexType, group and attributeGroup.");\r
- }\r
- }\r
-\r
- XmlSchema includedSchema = null;\r
- if (stream == null) {\r
- // It is missing schema components.\r
- missedSubComponents = true;\r
- continue;\r
- } else {\r
- schemaLocationStack.Push (url);\r
- includedSchema = XmlSchema.Read (new XmlTextReader (url, stream, nameTable), handler);\r
- includedSchema.schemas = schemas;\r
- }\r
-\r
- // Set - actual - target namespace for the included schema * before compilation*.\r
- XmlSchemaImport import = ext as XmlSchemaImport;\r
- if (import != null) {\r
- if (TargetNamespace == includedSchema.TargetNamespace) {\r
- error (handler, "Target namespace must be different from that of included schema.");\r
- continue;\r
- } else if (includedSchema.TargetNamespace != import.Namespace) {\r
- error (handler, "Attribute namespace and its importing schema's target namespace must be the same.");\r
- continue;\r
- }\r
- } else {\r
- if (TargetNamespace == null && \r
- includedSchema.TargetNamespace != null) {\r
- error (handler, "Target namespace is required to include a schema which has its own target namespace");\r
- continue;\r
- }\r
- else if (TargetNamespace != null && \r
- includedSchema.TargetNamespace == null)\r
- includedSchema.TargetNamespace = TargetNamespace;\r
- }\r
-\r
- // Compile included schema.\r
- includedSchema.idCollection = this.IDCollection;\r
- includedSchema.Compile (handler, schemaLocationStack, rootSchema, col, resolver);\r
- schemaLocationStack.Pop ();\r
-\r
- if (import != null)\r
- rootSchema.schemas.Add (includedSchema);\r
-\r
- // Note that we use compiled items. Items\r
- // may not exist in Items, since included\r
- // schema also includes another schemas.\r
- foreach (DictionaryEntry entry in includedSchema.Attributes)\r
- compilationItems.Add ((XmlSchemaObject) entry.Value);\r
- foreach (DictionaryEntry entry in includedSchema.Elements)\r
- compilationItems.Add ((XmlSchemaObject) entry.Value);\r
- foreach (DictionaryEntry entry in includedSchema.SchemaTypes)\r
- compilationItems.Add ((XmlSchemaObject) entry.Value);\r
- foreach (DictionaryEntry entry in includedSchema.AttributeGroups)\r
- compilationItems.Add ((XmlSchemaObject) entry.Value);\r
- foreach (DictionaryEntry entry in includedSchema.Groups)\r
- compilationItems.Add ((XmlSchemaObject) entry.Value);\r
- foreach (DictionaryEntry entry in includedSchema.Notations)\r
- compilationItems.Add ((XmlSchemaObject) entry.Value);\r
- }\r
- else\r
- {\r
- error(handler,"Object of Type "+Includes [i].GetType().Name+" is not valid in Includes Property of XmlSchema");\r
- }\r
- }\r
-\r
- // Compilation phase.\r
- // At least each Compile() must gives unique (qualified) name for each component.\r
- // It also checks self-resolvable properties correct.\r
- // Post compilation schema information contribution is not required here.\r
- // It should be done by Validate().\r
- for (int i = 0; i < compilationItems.Count; i++) {\r
- XmlSchemaObject obj = compilationItems [i];\r
- if(obj is XmlSchemaAnnotation)\r
- {\r
- int numerr = ((XmlSchemaAnnotation)obj).Compile(handler, this);\r
- errorCount += numerr;\r
- }\r
- else if(obj is XmlSchemaAttribute)\r
- {\r
- XmlSchemaAttribute attr = (XmlSchemaAttribute) obj;\r
- attr.ParentIsSchema = true;\r
- int numerr = attr.Compile(handler, this);\r
- errorCount += numerr;\r
- if(numerr == 0)\r
- {\r
- if (!attr.IsComplied (this.CompilationId))\r
- schemas.SchemaSet.GlobalAttributes.Add (attr.QualifiedName, attr);\r
- XmlSchemaUtil.AddToTable (Attributes, attr, attr.QualifiedName, handler);\r
- }\r
- }\r
- else if(obj is XmlSchemaAttributeGroup)\r
- {\r
- XmlSchemaAttributeGroup attrgrp = (XmlSchemaAttributeGroup) obj;\r
- int numerr = attrgrp.Compile(handler, this);\r
- errorCount += numerr;\r
- if(numerr == 0)\r
- {\r
- XmlSchemaUtil.AddToTable (AttributeGroups, attrgrp, attrgrp.QualifiedName, handler);\r
- }\r
- }\r
- else if(obj is XmlSchemaComplexType)\r
- {\r
- XmlSchemaComplexType ctype = (XmlSchemaComplexType) obj;\r
- ctype.ParentIsSchema = true;\r
- int numerr = ctype.Compile(handler, this);\r
- errorCount += numerr;\r
- if(numerr == 0)\r
- {\r
- if (!ctype.IsComplied (this.CompilationId))\r
- schemas.SchemaSet.GlobalTypes.Add (ctype.QualifiedName, ctype);\r
- XmlSchemaUtil.AddToTable (schemaTypes, ctype, ctype.QualifiedName, handler);\r
- }\r
- }\r
- else if(obj is XmlSchemaSimpleType)\r
- {\r
- XmlSchemaSimpleType stype = (XmlSchemaSimpleType) obj;\r
- stype.islocal = false; //This simple type is toplevel\r
- int numerr = stype.Compile(handler, this);\r
- errorCount += numerr;\r
- if(numerr == 0)\r
- {\r
- if (!stype.IsComplied (this.CompilationId))\r
- schemas.SchemaSet.GlobalTypes.Add (stype.QualifiedName, stype);\r
- XmlSchemaUtil.AddToTable (SchemaTypes, stype, stype.QualifiedName, handler);\r
- }\r
- }\r
- else if(obj is XmlSchemaElement)\r
- {\r
- XmlSchemaElement elem = (XmlSchemaElement) obj;\r
- elem.parentIsSchema = true;\r
- int numerr = elem.Compile(handler, this);\r
- errorCount += numerr;\r
- if(numerr == 0)\r
- {\r
- if (!elem.IsComplied (this.CompilationId))\r
- schemas.SchemaSet.GlobalElements.Add (elem.QualifiedName, elem);\r
- XmlSchemaUtil.AddToTable (Elements, elem, elem.QualifiedName, handler);\r
- }\r
- }\r
- else if(obj is XmlSchemaGroup)\r
- {\r
- XmlSchemaGroup grp = (XmlSchemaGroup) obj;\r
- int numerr = grp.Compile(handler, this);\r
- errorCount += numerr;\r
- if(numerr == 0)\r
- {\r
- XmlSchemaUtil.AddToTable (Groups, grp, grp.QualifiedName, handler);\r
- }\r
- }\r
- else if(obj is XmlSchemaNotation)\r
- {\r
- XmlSchemaNotation ntn = (XmlSchemaNotation) obj;\r
- int numerr = ntn.Compile(handler, this);\r
- errorCount += numerr;\r
- if(numerr == 0)\r
- {\r
- XmlSchemaUtil.AddToTable (Notations, ntn, ntn.QualifiedName, handler);\r
- }\r
- }\r
- else\r
- {\r
- ValidationHandler.RaiseValidationEvent (\r
- handler, null,\r
- "Object of Type "+obj.GetType().Name+" is not valid in Item Property of Schema",\r
- null, this, null, XmlSeverityType.Error);\r
- }\r
- }\r
-\r
- if (rootSchema == this)\r
- Validate(handler);\r
- }\r
-\r
- private string GetResolvedUri (XmlResolver resolver, string relativeUri)\r
- {\r
- Uri baseUri = null;\r
- if (this.SourceUri != null && this.SourceUri != String.Empty)\r
- baseUri = new Uri (this.SourceUri);\r
- return resolver.ResolveUri (baseUri, relativeUri).ToString ();\r
- }\r
-\r
- internal bool IsNamespaceAbsent (string ns)\r
- {\r
- return this.schemas [ns] == null;\r
- }\r
-\r
- #endregion\r
-\r
- private void Validate(ValidationEventHandler handler)\r
- {\r
- ValidationId = CompilationId;\r
-\r
- // Firstly Element needs to be filled their substitution group info\r
- foreach(XmlSchemaElement elem in Elements.Values)\r
- elem.FillSubstitutionElementInfo ();\r
-\r
- // Validate\r
- foreach(XmlSchemaAttribute attr in Attributes.Values)\r
- {\r
- errorCount += attr.Validate(handler, this);\r
- }\r
- foreach(XmlSchemaAttributeGroup attrgrp in AttributeGroups.Values)\r
- {\r
- errorCount += attrgrp.Validate(handler, this);\r
- }\r
- foreach(XmlSchemaType type in SchemaTypes.Values)\r
- {\r
- errorCount += type.Validate(handler, this);\r
- }\r
- foreach(XmlSchemaElement elem in Elements.Values)\r
- {\r
- errorCount += elem.Validate(handler, this);\r
- }\r
- foreach(XmlSchemaGroup grp in Groups.Values)\r
- {\r
- errorCount += grp.Validate(handler, this);\r
- }\r
- foreach(XmlSchemaNotation ntn in Notations.Values)\r
- {\r
- errorCount += ntn.Validate(handler, this);\r
- }\r
- }\r
-\r
- #region Read\r
-\r
- // We cannot use xml deserialization, since it does not provide line info, qname context, and so on.\r
- public static XmlSchema Read (TextReader reader, ValidationEventHandler validationEventHandler)\r
- {\r
- return Read (new XmlTextReader (reader),validationEventHandler);\r
- }\r
- public static XmlSchema Read (Stream stream, ValidationEventHandler validationEventHandler)\r
- {\r
- return Read (new XmlTextReader (stream),validationEventHandler);\r
- }\r
-\r
- public static XmlSchema Read (XmlReader rdr, ValidationEventHandler validationEventHandler)\r
- {\r
- XmlSchemaReader reader = new XmlSchemaReader (rdr, validationEventHandler);\r
-\r
- if (reader.ReadState == ReadState.Initial)\r
- reader.ReadNextElement ();\r
-\r
- int startDepth = reader.Depth;\r
-\r
- do\r
- {\r
- switch(reader.NodeType)\r
- {\r
- case XmlNodeType.Element:\r
- if(reader.LocalName == "schema")\r
- {\r
- XmlSchema schema = new XmlSchema ();\r
- schema.nameTable = rdr.NameTable;\r
-\r
- schema.LineNumber = reader.LineNumber;\r
- schema.LinePosition = reader.LinePosition;\r
- schema.SourceUri = reader.BaseURI;\r
-\r
- ReadAttributes(schema, reader, validationEventHandler);\r
- //IsEmptyElement does not behave properly if reader is\r
- //positioned at an attribute.\r
- reader.MoveToElement();\r
- if(!reader.IsEmptyElement)\r
- {\r
- ReadContent(schema, reader, validationEventHandler);\r
- }\r
- else\r
- rdr.Skip ();\r
-\r
- if (rdr.NodeType == XmlNodeType.EndElement)\r
- rdr.Read ();\r
- return schema;\r
- }\r
- else\r
- //Schema can't be generated. Throw an exception\r
- error (validationEventHandler, "The root element must be schema", null);\r
- break;\r
- default:\r
- error(validationEventHandler, "This should never happen. XmlSchema.Read 1 ",null);\r
- break;\r
- }\r
- } while(reader.Depth > startDepth && reader.ReadNextElement());\r
-\r
- // This is thrown regardless of ValidationEventHandler existence.\r
- throw new XmlSchemaException ("The top level schema must have namespace " + XmlSchema.Namespace, null);\r
- }\r
-\r
- private static void ReadAttributes(XmlSchema schema, XmlSchemaReader reader, ValidationEventHandler h)\r
- {\r
- Exception ex;\r
-\r
- reader.MoveToElement();\r
- while(reader.MoveToNextAttribute())\r
- {\r
- switch(reader.Name)\r
- {\r
- case "attributeFormDefault" :\r
- schema.attributeFormDefault = XmlSchemaUtil.ReadFormAttribute(reader,out ex);\r
- if(ex != null)\r
- error(h, reader.Value + " is not a valid value for attributeFormDefault.", ex);\r
- break;\r
- case "blockDefault" :\r
- schema.blockDefault = XmlSchemaUtil.ReadDerivationAttribute(reader,out ex, "blockDefault",\r
- XmlSchemaUtil.ElementBlockAllowed);\r
- if(ex != null)\r
- error (h, ex.Message, ex);\r
- break;\r
- case "elementFormDefault":\r
- schema.elementFormDefault = XmlSchemaUtil.ReadFormAttribute(reader, out ex);\r
- if(ex != null)\r
- error(h, reader.Value + " is not a valid value for elementFormDefault.", ex);\r
- break;\r
- case "finalDefault":\r
- schema.finalDefault = XmlSchemaUtil.ReadDerivationAttribute(reader, out ex, "finalDefault",\r
- XmlSchemaUtil.FinalAllowed);\r
- if(ex != null)\r
- error (h, ex.Message , ex);\r
- break;\r
- case "id":\r
- schema.id = reader.Value;\r
- break;\r
- case "targetNamespace":\r
- schema.targetNamespace = reader.Value;\r
- break;\r
- case "version":\r
- schema.version = reader.Value;\r
- break;\r
- case "xml:lang":\r
- schema.language = reader.Value;\r
- break;\r
- default:\r
- if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)\r
- error(h, reader.Name + " attribute is not allowed in schema element",null);\r
- else\r
- {\r
- XmlSchemaUtil.ReadUnhandledAttribute(reader,schema);\r
- }\r
- break;\r
- }\r
- }\r
- }\r
-\r
- private static void ReadContent(XmlSchema schema, XmlSchemaReader reader, ValidationEventHandler h)\r
- {\r
- reader.MoveToElement();\r
- if(reader.LocalName != "schema" && reader.NamespaceURI != XmlSchema.Namespace && reader.NodeType != XmlNodeType.Element)\r
- error(h, "UNREACHABLE CODE REACHED: Method: Schema.ReadContent, " + reader.LocalName + ", " + reader.NamespaceURI,null);\r
-\r
- //(include | import | redefine | annotation)*,\r
- //((simpleType | complexType | group | attributeGroup | element | attribute | notation | annotation)*\r
- int level = 1;\r
- while(reader.ReadNextElement())\r
- {\r
- if(reader.NodeType == XmlNodeType.EndElement)\r
- {\r
- if(reader.LocalName != xmlname)\r
- error(h,"Should not happen :2: XmlSchema.Read, name="+reader.Name,null);\r
- break;\r
- }\r
- if(level <= 1)\r
- {\r
- if(reader.LocalName == "include")\r
- {\r
- XmlSchemaInclude include = XmlSchemaInclude.Read(reader,h);\r
- if(include != null)\r
- schema.includes.Add(include);\r
- continue;\r
- }\r
- if(reader.LocalName == "import")\r
- {\r
- XmlSchemaImport import = XmlSchemaImport.Read(reader,h);\r
- if(import != null)\r
- schema.includes.Add(import);\r
- continue;\r
- }\r
- if(reader.LocalName == "redefine")\r
- {\r
- XmlSchemaRedefine redefine = XmlSchemaRedefine.Read(reader,h);\r
- if(redefine != null)\r
- schema.includes.Add(redefine);\r
- continue;\r
- }\r
- if(reader.LocalName == "annotation")\r
- {\r
- XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);\r
- if(annotation != null)\r
- schema.items.Add(annotation);\r
- continue;\r
- }\r
- }\r
- if(level <=2)\r
- {\r
- level = 2;\r
- if(reader.LocalName == "simpleType")\r
- {\r
- XmlSchemaSimpleType stype = XmlSchemaSimpleType.Read(reader,h);\r
- if(stype != null)\r
- schema.items.Add(stype);\r
- continue;\r
- }\r
- if(reader.LocalName == "complexType")\r
- {\r
- XmlSchemaComplexType ctype = XmlSchemaComplexType.Read(reader,h);\r
- if(ctype != null)\r
- schema.items.Add(ctype);\r
- continue;\r
- }\r
- if(reader.LocalName == "group")\r
- {\r
- XmlSchemaGroup group = XmlSchemaGroup.Read(reader,h);\r
- if(group != null)\r
- schema.items.Add(group);\r
- continue;\r
- }\r
- if(reader.LocalName == "attributeGroup")\r
- {\r
- XmlSchemaAttributeGroup attributeGroup = XmlSchemaAttributeGroup.Read(reader,h);\r
- if(attributeGroup != null)\r
- schema.items.Add(attributeGroup);\r
- continue;\r
- }\r
- if(reader.LocalName == "element")\r
- {\r
- XmlSchemaElement element = XmlSchemaElement.Read(reader,h);\r
- if(element != null)\r
- schema.items.Add(element);\r
- continue;\r
- }\r
- if(reader.LocalName == "attribute")\r
- {\r
- XmlSchemaAttribute attr = XmlSchemaAttribute.Read(reader,h);\r
- if(attr != null)\r
- schema.items.Add(attr);\r
- continue;\r
- }\r
- if(reader.LocalName == "notation")\r
- {\r
- XmlSchemaNotation notation = XmlSchemaNotation.Read(reader,h);\r
- if(notation != null)\r
- schema.items.Add(notation);\r
- continue;\r
- }\r
- if(reader.LocalName == "annotation")\r
- {\r
- XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);\r
- if(annotation != null)\r
- schema.items.Add(annotation);\r
- continue;\r
- }\r
- }\r
- reader.RaiseInvalidElementError();\r
- }\r
- }\r
- #endregion\r
-\r
- #region write\r
-\r
- public void Write(System.IO.Stream stream)\r
- {\r
- Write(stream,null);\r
- }\r
- public void Write(System.IO.TextWriter writer)\r
- {\r
- Write(writer,null);\r
- }\r
- public void Write(System.Xml.XmlWriter writer)\r
- {\r
- Write(writer,null);\r
- }\r
- public void Write(System.IO.Stream stream, System.Xml.XmlNamespaceManager namespaceManager)\r
- {\r
- Write(new XmlTextWriter(stream,null),namespaceManager);\r
- }\r
- public void Write(System.IO.TextWriter writer, System.Xml.XmlNamespaceManager namespaceManager)\r
- {\r
- XmlTextWriter xwriter = new XmlTextWriter(writer);\r
- xwriter.Formatting = Formatting.Indented;\r
- Write(xwriter,namespaceManager);\r
- }\r
-\r
- public void Write (System.Xml.XmlWriter writer, System.Xml.XmlNamespaceManager namespaceManager)\r
- {\r
- XmlSerializerNamespaces nss = new XmlSerializerNamespaces ();\r
-\r
- if (namespaceManager != null) {\r
- if (nss == null)\r
- nss = new XmlSerializerNamespaces ();\r
- foreach (string name in namespaceManager) {\r
- //xml and xmlns namespaces are added by default in namespaceManager.\r
- //So we should ignore them\r
- if (name !="xml" && name != "xmlns")\r
- nss.Add (name, namespaceManager.LookupNamespace (name));\r
- }\r
- }\r
-\r
- if (Namespaces != null && Namespaces.Count > 0) {\r
- nss.Add (String.Empty, XmlSchema.Namespace);\r
- foreach (XmlQualifiedName qn in Namespaces.ToArray ()) {\r
- nss.Add (qn.Name, qn.Namespace);\r
- }\r
- }\r
-\r
- if (nss.Count == 0) {\r
- // Add the xml schema namespace. (It is done \r
- // only when no entry exists in Namespaces).\r
- nss.Add ("xs", XmlSchema.Namespace);\r
- if (TargetNamespace != null)\r
- nss.Add ("tns", TargetNamespace);\r
- }\r
-\r
-// XmlSerializer xser = new XmlSerializer (typeof (XmlSchema));\r
-// xser.Serialize (writer, this, nss);\r
- XmlSchemaSerializer xser = new XmlSchemaSerializer ();\r
- xser.Serialize (writer, this, nss);\r
- writer.Flush();\r
- }\r
- #endregion\r
- }\r
-
- class XmlSchemaSerializer : XmlSerializer\r
- {\r
- protected override void Serialize (object o, XmlSerializationWriter writer)\r
- {\r
- XmlSchemaSerializationWriter w = writer as XmlSchemaSerializationWriter;\r
- w.WriteRoot_XmlSchema ((XmlSchema) o);\r
- }\r
-\r
- protected override XmlSerializationWriter CreateWriter ()\r
- {\r
- return new XmlSchemaSerializationWriter ();\r
- }\r
- }\r
+//
+// System.Xml.Schema.XmlSchema.cs
+//
+// Author:
+// Dwivedi, Ajay kumar Adwiv@Yahoo.com
+// Atsushi Enomoto ginga@kit.hi-ho.ne.jp
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections;
+using System.Xml;
+using System.IO;
+using System.Xml.Serialization;
+using System.ComponentModel;
+
+namespace System.Xml.Schema
+{
+ /// <summary>
+ /// Summary description for XmlSchema.
+ /// </summary>
+ [XmlRoot ("schema",Namespace=XmlSchema.Namespace)]
+ public class XmlSchema : XmlSchemaObject
+ {
+ //public constants
+ public const string Namespace = "http://www.w3.org/2001/XMLSchema";
+ public const string InstanceNamespace = "http://www.w3.org/2001/XMLSchema-instance";
+ internal const string XdtNamespace = "http://www.w3.org/2003/11/xpath-datatypes";
+
+ //private fields
+ private XmlSchemaForm attributeFormDefault ;
+ private XmlSchemaObjectTable attributeGroups ;
+ private XmlSchemaObjectTable attributes ;
+ private XmlSchemaDerivationMethod blockDefault ;
+ private XmlSchemaForm elementFormDefault ;
+ private XmlSchemaObjectTable elements ;
+ private XmlSchemaDerivationMethod finalDefault ;
+ private XmlSchemaObjectTable groups ;
+ private string id ;
+ private XmlSchemaObjectCollection includes ;
+ private XmlSchemaObjectCollection items ;
+ private XmlSchemaObjectTable notations ;
+ private XmlSchemaObjectTable schemaTypes ;
+ private string targetNamespace ;
+ private XmlAttribute[] unhandledAttributes ;
+ private string version;
+
+ // other post schema compilation infoset
+ private Hashtable idCollection;
+ private XmlSchemaObjectTable namedIdentities;
+ private XmlSchemaSet schemas;
+
+ private XmlNameTable nameTable;
+
+ internal bool missedSubComponents;
+
+ // Only compilation-time use
+ private XmlSchemaObjectCollection compilationItems;
+ private Hashtable handledUris;
+
+ // Compiler specific things
+ const string xmlname = "schema";
+
+ public XmlSchema ()
+ {
+ attributeFormDefault= XmlSchemaForm.None;
+ blockDefault = XmlSchemaDerivationMethod.None;
+ elementFormDefault = XmlSchemaForm.None;
+ finalDefault = XmlSchemaDerivationMethod.None;
+ includes = new XmlSchemaObjectCollection();
+ isCompiled = false;
+ items = new XmlSchemaObjectCollection();
+ attributeGroups = new XmlSchemaObjectTable();
+ attributes = new XmlSchemaObjectTable();
+ elements = new XmlSchemaObjectTable();
+ groups = new XmlSchemaObjectTable();
+ notations = new XmlSchemaObjectTable();
+ schemaTypes = new XmlSchemaObjectTable();
+ idCollection = new Hashtable ();
+ namedIdentities = new XmlSchemaObjectTable();
+ }
+
+ #region Properties
+
+ [DefaultValue (XmlSchemaForm.None)]
+ [System.Xml.Serialization.XmlAttribute ("attributeFormDefault")]
+ public XmlSchemaForm AttributeFormDefault
+ {
+ get{ return attributeFormDefault; }
+ set{ this.attributeFormDefault = value;}
+ }
+
+ [DefaultValue (XmlSchemaDerivationMethod.None)]
+ [System.Xml.Serialization.XmlAttribute ("blockDefault")]
+ public XmlSchemaDerivationMethod BlockDefault
+ {
+ get{ return blockDefault;}
+ set{ blockDefault = value;}
+ }
+
+ [DefaultValue (XmlSchemaDerivationMethod.None)]
+ [System.Xml.Serialization.XmlAttribute ("finalDefault")]
+ public XmlSchemaDerivationMethod FinalDefault
+ {
+ get{ return finalDefault; }
+ set{ finalDefault = value; }
+ }
+
+ [DefaultValue (XmlSchemaForm.None)]
+ [System.Xml.Serialization.XmlAttribute ("elementFormDefault")]
+ public XmlSchemaForm ElementFormDefault
+ {
+ get{ return elementFormDefault; }
+ set{ elementFormDefault = value; }
+ }
+
+ [System.Xml.Serialization.XmlAttribute ("targetNamespace")]
+ public string TargetNamespace
+ {
+ get{ return targetNamespace; }
+ set{ targetNamespace = value; }
+ }
+
+ [System.Xml.Serialization.XmlAttribute ("version")]
+ public string Version
+ {
+ get{ return version; }
+ set{ version = value; }
+ }
+
+ [XmlElement ("include",typeof(XmlSchemaInclude), Namespace="http://www.w3.org/2001/XMLSchema")]
+ [XmlElement ("import",typeof(XmlSchemaImport), Namespace="http://www.w3.org/2001/XMLSchema")]
+ [XmlElement ("redefine",typeof(XmlSchemaRedefine), Namespace="http://www.w3.org/2001/XMLSchema")]
+ public XmlSchemaObjectCollection Includes
+ {
+ get{ return includes;}
+ }
+
+ [XmlElement ("simpleType", typeof (XmlSchemaSimpleType), Namespace="http://www.w3.org/2001/XMLSchema")]
+ [XmlElement ("complexType", typeof (XmlSchemaComplexType), Namespace="http://www.w3.org/2001/XMLSchema")]
+ [XmlElement ("group", typeof (XmlSchemaGroup),Namespace="http://www.w3.org/2001/XMLSchema")]
+ //Only Schema's attributeGroup has type XmlSchemaAttributeGroup.
+ //Others (complextype, restrictions etc) must have XmlSchemaAttributeGroupRef
+ [XmlElement ("attributeGroup", typeof (XmlSchemaAttributeGroup), Namespace="http://www.w3.org/2001/XMLSchema")]
+ [XmlElement ("element", typeof (XmlSchemaElement), Namespace="http://www.w3.org/2001/XMLSchema")]
+ [XmlElement ("attribute", typeof (XmlSchemaAttribute), Namespace="http://www.w3.org/2001/XMLSchema")]
+ [XmlElement ("notation", typeof (XmlSchemaNotation), Namespace="http://www.w3.org/2001/XMLSchema")]
+ [XmlElement ("annotation", typeof (XmlSchemaAnnotation), Namespace="http://www.w3.org/2001/XMLSchema")]
+ public XmlSchemaObjectCollection Items
+ {
+ get{ return items; }
+ }
+
+ [XmlIgnore]
+ public bool IsCompiled
+ {
+ get{ return this.CompilationId != Guid.Empty; }
+ }
+
+ [XmlIgnore]
+ public XmlSchemaObjectTable Attributes
+ {
+ get{ return attributes; }
+ }
+
+ [XmlIgnore]
+ public XmlSchemaObjectTable AttributeGroups
+ {
+ get{ return attributeGroups; }
+ }
+
+ [XmlIgnore]
+ public XmlSchemaObjectTable SchemaTypes
+ {
+ get{ return schemaTypes; }
+ }
+
+ [XmlIgnore]
+ public XmlSchemaObjectTable Elements
+ {
+ get{ return elements; }
+ }
+
+ [System.Xml.Serialization.XmlAttribute ("id")]
+ public string Id
+ {
+ get{ return id; }
+ set{ id = value; }
+ }
+
+ [XmlAnyAttribute]
+ public XmlAttribute [] UnhandledAttributes
+ {
+ get {
+ if (unhandledAttributeList != null) {
+ unhandledAttributes = (XmlAttribute []) unhandledAttributeList.ToArray (typeof (XmlAttribute));
+ unhandledAttributeList = null;
+ }
+ return unhandledAttributes;
+ }
+ set {
+ unhandledAttributes = value;
+ unhandledAttributeList = null;
+ }
+ }
+
+ [XmlIgnore]
+ public XmlSchemaObjectTable Groups
+ {
+ get{ return groups; }
+ }
+
+ [XmlIgnore]
+ public XmlSchemaObjectTable Notations
+ {
+ get{ return notations; }
+ }
+
+ internal Hashtable IDCollection
+ {
+ get { return idCollection; }
+ }
+
+ internal XmlSchemaObjectTable NamedIdentities
+ {
+ get { return namedIdentities; }
+ }
+
+ internal XmlSchemaSet Schemas
+ {
+ get { return schemas; }
+ }
+ #endregion
+
+ #region Compile
+
+ // Methods
+ /// <summary>
+ /// This compile method does two things:
+ /// 1. It compiles and fills the PSVI dataset
+ /// 2. Validates the schema by calling Validate method.
+ /// Every XmlSchemaObject has a Compile Method which gets called.
+ /// </summary>
+ /// <remarks>
+ /// 1. blockDefault must be one of #all | List of (extension | restriction | substitution)
+ /// 2. finalDefault must be one of (#all | List of (extension | restriction| union| list))
+ /// 3. id must be of type ID
+ /// 4. targetNamespace should be any uri
+ /// 5. version should be a normalizedString
+ /// </remarks>
+ public void Compile (ValidationEventHandler handler)
+ {
+ Compile (handler, new XmlUrlResolver ());
+ }
+
+#if NET_1_1
+ public void Compile (ValidationEventHandler handler, XmlResolver resolver)
+#else
+ internal void Compile (ValidationEventHandler handler, XmlResolver resolver)
+#endif
+ {
+ Compile (handler, new Stack (), this, null, resolver);
+ }
+
+ internal void Compile (ValidationEventHandler handler, XmlSchemaSet col, XmlResolver resolver)
+ {
+ Compile (handler, new Stack (), this, col, resolver);
+ }
+
+ private void Compile (ValidationEventHandler handler, Stack schemaLocationStack, XmlSchema rootSchema, XmlSchemaSet col, XmlResolver resolver)
+ {
+ if (rootSchema != this) {
+ CompilationId = rootSchema.CompilationId;
+ schemas = rootSchema.schemas;
+ }
+ else {
+ schemas = col;
+ if (schemas == null) {
+ schemas = new XmlSchemaSet ();
+ schemas.CompilationId = Guid.NewGuid ();
+ }
+ CompilationId = schemas.CompilationId;
+ this.idCollection.Clear ();
+ }
+ if (!schemas.Contains (this)) // e.g. xs:import
+ schemas.Add (this);
+
+ attributeGroups.Clear ();
+ attributes.Clear ();
+ elements.Clear ();
+ groups.Clear ();
+ notations.Clear ();
+ schemaTypes.Clear ();
+ namedIdentities.Clear ();
+
+ //1. Union and List are not allowed in block default
+ if (BlockDefault != XmlSchemaDerivationMethod.All) {
+ if((BlockDefault & XmlSchemaDerivationMethod.List)!=0 )
+ error(handler, "list is not allowed in blockDefault attribute");
+ if((BlockDefault & XmlSchemaDerivationMethod.Union)!=0 )
+ error(handler, "union is not allowed in blockDefault attribute");
+ }
+
+ //2. Substitution is not allowed in finaldefault.
+ if (FinalDefault != XmlSchemaDerivationMethod.All) {
+ if((FinalDefault & XmlSchemaDerivationMethod.Substitution)!=0 )
+ error(handler, "substitution is not allowed in finalDefault attribute");
+ }
+
+ //3. id must be of type ID
+ XmlSchemaUtil.CompileID(Id, this, this.IDCollection, handler);
+
+ //4. targetNamespace should be of type anyURI or absent
+ if (TargetNamespace != null) {
+ if(!XmlSchemaUtil.CheckAnyUri (TargetNamespace))
+ error(handler, TargetNamespace+" is not a valid value for targetNamespace attribute of schema");
+ }
+
+ //5. version should be of type normalizedString
+ if (!XmlSchemaUtil.CheckNormalizedString(Version))
+ error(handler, Version + "is not a valid value for version attribute of schema");
+
+ // Compile the content of this schema
+
+ compilationItems = new XmlSchemaObjectCollection ();
+ for (int i = 0; i < Items.Count; i++) {
+#if NET_2_0
+ Items [i].Parent = this;
+#endif
+ compilationItems.Add (Items [i]);
+ }
+ if (this == rootSchema)
+ handledUris = new Hashtable ();
+
+ // First, we run into inclusion schemas to collect
+ // compilation target items into compiledItems.
+ for (int i = 0; i < Includes.Count; i++) {
+#if NET_2_0
+ Includes [i].Parent = this;
+#endif
+ XmlSchemaExternal ext = Includes [i] as XmlSchemaExternal;
+ if (ext == null) {
+ error (handler, String.Format ("Object of Type {0} is not valid in Includes Property of XmlSchema", Includes [i].GetType().Name));
+ continue;
+ }
+
+ if (ext.SchemaLocation == null)
+ continue;
+
+ Stream stream = null;
+ string url = null;
+ if (resolver != null) {
+ url = GetResolvedUri (resolver, ext.SchemaLocation);
+ if (schemaLocationStack.Contains (url)) {
+ // Just skip nested inclusion.
+ // The spec is "carefully written"
+ // not to handle it as an error.
+// error (handler, "Nested inclusion was found: " + url);
+ // must skip this inclusion
+ continue;
+ }
+ if (rootSchema.handledUris.Contains (url))
+ // This schema is already handled, so simply skip (otherwise, duplicate definition errrors occur.
+ continue;
+ rootSchema.handledUris.Add (url, url);
+ try {
+ stream = resolver.GetEntity (new Uri (url), null, typeof (Stream)) as Stream;
+ } catch (Exception) {
+ // LAMESPEC: This is not good way to handle errors, but since we cannot know what kind of XmlResolver will come, so there are no mean to avoid this ugly catch.
+ warn (handler, "Could not resolve schema location URI: " + url);
+ stream = null;
+ }
+ }
+
+ // Process redefinition children in advance.
+ XmlSchemaRedefine redefine = Includes [i] as XmlSchemaRedefine;
+ if (redefine != null) {
+ for (int j = 0; j < redefine.Items.Count; j++) {
+ XmlSchemaObject redefinedObj = redefine.Items [j];
+ redefinedObj.isRedefinedComponent = true;
+ redefinedObj.isRedefineChild = true;
+ if (redefinedObj is XmlSchemaType ||
+ redefinedObj is XmlSchemaGroup ||
+ redefinedObj is XmlSchemaAttributeGroup)
+ compilationItems.Add (redefinedObj);
+ else
+ error (handler, "Redefinition is only allowed to simpleType, complexType, group and attributeGroup.");
+ }
+ }
+
+ XmlSchema includedSchema = null;
+ if (stream == null) {
+ // It is missing schema components.
+ missedSubComponents = true;
+ continue;
+ } else {
+ schemaLocationStack.Push (url);
+ XmlTextReader xtr = null;
+ try {
+ xtr = new XmlTextReader (url, stream, nameTable);
+ includedSchema = XmlSchema.Read (xtr, handler);
+ } finally {
+ if (xtr != null)
+ xtr.Close ();
+ }
+ includedSchema.schemas = schemas;
+ }
+
+ // Set - actual - target namespace for the included schema * before compilation*.
+ XmlSchemaImport import = ext as XmlSchemaImport;
+ if (import != null) {
+ if (TargetNamespace == includedSchema.TargetNamespace) {
+ error (handler, "Target namespace must be different from that of included schema.");
+ continue;
+ } else if (includedSchema.TargetNamespace != import.Namespace) {
+ error (handler, "Attribute namespace and its importing schema's target namespace must be the same.");
+ continue;
+ }
+ } else {
+ if (TargetNamespace == null &&
+ includedSchema.TargetNamespace != null) {
+ error (handler, "Target namespace is required to include a schema which has its own target namespace");
+ continue;
+ }
+ else if (TargetNamespace != null &&
+ includedSchema.TargetNamespace == null)
+ includedSchema.TargetNamespace = TargetNamespace;
+ }
+
+ // Compile included schema.
+ includedSchema.idCollection = this.IDCollection;
+ includedSchema.Compile (handler, schemaLocationStack, rootSchema, col, resolver);
+ schemaLocationStack.Pop ();
+
+ if (import != null)
+ rootSchema.schemas.Add (includedSchema);
+
+ // Note that we use compiled items. Items
+ // may not exist in Items, since included
+ // schema also includes another schemas.
+ foreach (DictionaryEntry entry in includedSchema.Attributes)
+ compilationItems.Add ((XmlSchemaObject) entry.Value);
+ foreach (DictionaryEntry entry in includedSchema.Elements)
+ compilationItems.Add ((XmlSchemaObject) entry.Value);
+ foreach (DictionaryEntry entry in includedSchema.SchemaTypes)
+ compilationItems.Add ((XmlSchemaObject) entry.Value);
+ foreach (DictionaryEntry entry in includedSchema.AttributeGroups)
+ compilationItems.Add ((XmlSchemaObject) entry.Value);
+ foreach (DictionaryEntry entry in includedSchema.Groups)
+ compilationItems.Add ((XmlSchemaObject) entry.Value);
+ foreach (DictionaryEntry entry in includedSchema.Notations)
+ compilationItems.Add ((XmlSchemaObject) entry.Value);
+ }
+
+ // Compilation phase.
+ // At least each Compile() must gives unique (qualified) name for each component.
+ // It also checks self-resolvable properties correct.
+ // Post compilation schema information contribution is not required here.
+ // It should be done by Validate().
+ for (int i = 0; i < compilationItems.Count; i++) {
+ XmlSchemaObject obj = compilationItems [i];
+ if(obj is XmlSchemaAnnotation) {
+ int numerr = ((XmlSchemaAnnotation)obj).Compile (handler, this);
+ errorCount += numerr;
+ } else if (obj is XmlSchemaAttribute) {
+ XmlSchemaAttribute attr = (XmlSchemaAttribute) obj;
+ attr.ParentIsSchema = true;
+ int numerr = attr.Compile (handler, this);
+ errorCount += numerr;
+ if(numerr == 0)
+ {
+ XmlSchemaUtil.AddToTable (Attributes, attr, attr.QualifiedName, handler);
+ }
+ } else if (obj is XmlSchemaAttributeGroup) {
+ XmlSchemaAttributeGroup attrgrp = (XmlSchemaAttributeGroup) obj;
+ int numerr = attrgrp.Compile(handler, this);
+ errorCount += numerr;
+ if (numerr == 0)
+ XmlSchemaUtil.AddToTable (
+ AttributeGroups,
+ attrgrp,
+ attrgrp.QualifiedName,
+ handler);
+ } else if (obj is XmlSchemaComplexType) {
+ XmlSchemaComplexType ctype = (XmlSchemaComplexType) obj;
+ ctype.ParentIsSchema = true;
+ int numerr = ctype.Compile (handler, this);
+ errorCount += numerr;
+ if (numerr == 0)
+ XmlSchemaUtil.AddToTable (
+ schemaTypes,
+ ctype,
+ ctype.QualifiedName,
+ handler);
+ } else if (obj is XmlSchemaSimpleType) {
+ XmlSchemaSimpleType stype = (XmlSchemaSimpleType) obj;
+ stype.islocal = false; //This simple type is toplevel
+ int numerr = stype.Compile (handler, this);
+ errorCount += numerr;
+ if (numerr == 0)
+ XmlSchemaUtil.AddToTable (
+ SchemaTypes,
+ stype,
+ stype.QualifiedName,
+ handler);
+ } else if (obj is XmlSchemaElement) {
+ XmlSchemaElement elem = (XmlSchemaElement) obj;
+ elem.parentIsSchema = true;
+ int numerr = elem.Compile (handler, this);
+ errorCount += numerr;
+ if (numerr == 0)
+ XmlSchemaUtil.AddToTable (
+ Elements,
+ elem,
+ elem.QualifiedName,
+ handler);
+ } else if (obj is XmlSchemaGroup) {
+ XmlSchemaGroup grp = (XmlSchemaGroup) obj;
+ int numerr = grp.Compile (handler, this);
+ errorCount += numerr;
+ if (numerr == 0)
+ XmlSchemaUtil.AddToTable (
+ Groups,
+ grp,
+ grp.QualifiedName,
+ handler);
+ } else if (obj is XmlSchemaNotation) {
+ XmlSchemaNotation ntn = (XmlSchemaNotation) obj;
+ int numerr = ntn.Compile (handler, this);
+ errorCount += numerr;
+ if (numerr == 0)
+ XmlSchemaUtil.AddToTable (
+ Notations,
+ ntn,
+ ntn.QualifiedName,
+ handler);
+ } else {
+ ValidationHandler.RaiseValidationEvent (
+ handler,
+ null,
+ String.Format ("Object of Type {0} is not valid in Item Property of Schema", obj.GetType ().Name),
+ null,
+ this,
+ null,
+ XmlSeverityType.Error);
+ }
+ }
+
+ if (rootSchema == this)
+ Validate(handler);
+
+ if (errorCount == 0)
+ isCompiled = true;
+ errorCount = 0;
+ }
+
+ private string GetResolvedUri (XmlResolver resolver, string relativeUri)
+ {
+ Uri baseUri = null;
+ if (this.SourceUri != null && this.SourceUri != String.Empty)
+ baseUri = new Uri (this.SourceUri);
+ Uri abs = resolver.ResolveUri (baseUri, relativeUri);
+ return abs != null ? abs.ToString () : String.Empty;
+ }
+
+ internal bool IsNamespaceAbsent (string ns)
+ {
+ return !schemas.Contains (ns);
+ }
+
+ #endregion
+
+ private void Validate (ValidationEventHandler handler)
+ {
+ ValidationId = CompilationId;
+
+ // Firstly Element needs to be filled their substitution group info
+ foreach (XmlSchemaElement elem in Elements.Values)
+ elem.FillSubstitutionElementInfo ();
+
+ // Validate
+ foreach (XmlSchemaAttribute attr in Attributes.Values)
+ errorCount += attr.Validate (handler, this);
+ foreach (XmlSchemaAttributeGroup attrgrp in AttributeGroups.Values)
+ errorCount += attrgrp.Validate (handler, this);
+ foreach (XmlSchemaType type in SchemaTypes.Values)
+ errorCount += type.Validate (handler, this);
+ foreach (XmlSchemaElement elem in Elements.Values)
+ errorCount += elem.Validate (handler, this);
+ foreach (XmlSchemaGroup grp in Groups.Values)
+ errorCount += grp.Validate (handler, this);
+ foreach (XmlSchemaNotation ntn in Notations.Values)
+ errorCount += ntn.Validate (handler, this);
+ }
+
+ #region Read
+
+ // We cannot use xml deserialization, since it does not provide line info, qname context, and so on.
+ public static XmlSchema Read (TextReader reader, ValidationEventHandler validationEventHandler)
+ {
+ return Read (new XmlTextReader (reader),validationEventHandler);
+ }
+ public static XmlSchema Read (Stream stream, ValidationEventHandler validationEventHandler)
+ {
+ return Read (new XmlTextReader (stream),validationEventHandler);
+ }
+
+ public static XmlSchema Read (XmlReader rdr, ValidationEventHandler validationEventHandler)
+ {
+ XmlSchemaReader reader = new XmlSchemaReader (rdr, validationEventHandler);
+
+ if (reader.ReadState == ReadState.Initial)
+ reader.ReadNextElement ();
+
+ int startDepth = reader.Depth;
+
+ do
+ {
+ switch(reader.NodeType)
+ {
+ case XmlNodeType.Element:
+ if(reader.LocalName == "schema")
+ {
+ XmlSchema schema = new XmlSchema ();
+ schema.nameTable = rdr.NameTable;
+
+ schema.LineNumber = reader.LineNumber;
+ schema.LinePosition = reader.LinePosition;
+ schema.SourceUri = reader.BaseURI;
+
+ ReadAttributes(schema, reader, validationEventHandler);
+ //IsEmptyElement does not behave properly if reader is
+ //positioned at an attribute.
+ reader.MoveToElement();
+ if(!reader.IsEmptyElement)
+ {
+ ReadContent(schema, reader, validationEventHandler);
+ }
+ else
+ rdr.Skip ();
+
+ if (rdr.NodeType == XmlNodeType.EndElement)
+ rdr.Read ();
+ return schema;
+ }
+ else
+ //Schema can't be generated. Throw an exception
+ error (validationEventHandler, "The root element must be schema", null);
+ break;
+ default:
+ error(validationEventHandler, "This should never happen. XmlSchema.Read 1 ",null);
+ break;
+ }
+ } while(reader.Depth > startDepth && reader.ReadNextElement());
+
+ // This is thrown regardless of ValidationEventHandler existence.
+ throw new XmlSchemaException ("The top level schema must have namespace " + XmlSchema.Namespace, null);
+ }
+
+ private static void ReadAttributes(XmlSchema schema, XmlSchemaReader reader, ValidationEventHandler h)
+ {
+ Exception ex;
+
+ reader.MoveToElement();
+ while(reader.MoveToNextAttribute())
+ {
+ switch(reader.Name)
+ {
+ case "attributeFormDefault" :
+ schema.attributeFormDefault = XmlSchemaUtil.ReadFormAttribute(reader,out ex);
+ if(ex != null)
+ error(h, reader.Value + " is not a valid value for attributeFormDefault.", ex);
+ break;
+ case "blockDefault" :
+ schema.blockDefault = XmlSchemaUtil.ReadDerivationAttribute(reader,out ex, "blockDefault",
+ XmlSchemaUtil.ElementBlockAllowed);
+ if(ex != null)
+ error (h, ex.Message, ex);
+ break;
+ case "elementFormDefault":
+ schema.elementFormDefault = XmlSchemaUtil.ReadFormAttribute(reader, out ex);
+ if(ex != null)
+ error(h, reader.Value + " is not a valid value for elementFormDefault.", ex);
+ break;
+ case "finalDefault":
+ schema.finalDefault = XmlSchemaUtil.ReadDerivationAttribute(reader, out ex, "finalDefault",
+ XmlSchemaUtil.FinalAllowed);
+ if(ex != null)
+ error (h, ex.Message , ex);
+ break;
+ case "id":
+ schema.id = reader.Value;
+ break;
+ case "targetNamespace":
+ schema.targetNamespace = reader.Value;
+ break;
+ case "version":
+ schema.version = reader.Value;
+ break;
+ default:
+ if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)
+ error(h, reader.Name + " attribute is not allowed in schema element",null);
+ else
+ {
+ XmlSchemaUtil.ReadUnhandledAttribute(reader,schema);
+ }
+ break;
+ }
+ }
+ }
+
+ private static void ReadContent(XmlSchema schema, XmlSchemaReader reader, ValidationEventHandler h)
+ {
+ reader.MoveToElement();
+ if(reader.LocalName != "schema" && reader.NamespaceURI != XmlSchema.Namespace && reader.NodeType != XmlNodeType.Element)
+ error(h, "UNREACHABLE CODE REACHED: Method: Schema.ReadContent, " + reader.LocalName + ", " + reader.NamespaceURI,null);
+
+ //(include | import | redefine | annotation)*,
+ //((simpleType | complexType | group | attributeGroup | element | attribute | notation | annotation)*
+ int level = 1;
+ while(reader.ReadNextElement())
+ {
+ if(reader.NodeType == XmlNodeType.EndElement)
+ {
+ if(reader.LocalName != xmlname)
+ error(h,"Should not happen :2: XmlSchema.Read, name="+reader.Name,null);
+ break;
+ }
+ if(level <= 1)
+ {
+ if(reader.LocalName == "include")
+ {
+ XmlSchemaInclude include = XmlSchemaInclude.Read(reader,h);
+ if(include != null)
+ schema.includes.Add(include);
+ continue;
+ }
+ if(reader.LocalName == "import")
+ {
+ XmlSchemaImport import = XmlSchemaImport.Read(reader,h);
+ if(import != null)
+ schema.includes.Add(import);
+ continue;
+ }
+ if(reader.LocalName == "redefine")
+ {
+ XmlSchemaRedefine redefine = XmlSchemaRedefine.Read(reader,h);
+ if(redefine != null)
+ schema.includes.Add(redefine);
+ continue;
+ }
+ if(reader.LocalName == "annotation")
+ {
+ XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);
+ if(annotation != null)
+ schema.items.Add(annotation);
+ continue;
+ }
+ }
+ if(level <=2)
+ {
+ level = 2;
+ if(reader.LocalName == "simpleType")
+ {
+ XmlSchemaSimpleType stype = XmlSchemaSimpleType.Read(reader,h);
+ if(stype != null)
+ schema.items.Add(stype);
+ continue;
+ }
+ if(reader.LocalName == "complexType")
+ {
+ XmlSchemaComplexType ctype = XmlSchemaComplexType.Read(reader,h);
+ if(ctype != null)
+ schema.items.Add(ctype);
+ continue;
+ }
+ if(reader.LocalName == "group")
+ {
+ XmlSchemaGroup group = XmlSchemaGroup.Read(reader,h);
+ if(group != null)
+ schema.items.Add(group);
+ continue;
+ }
+ if(reader.LocalName == "attributeGroup")
+ {
+ XmlSchemaAttributeGroup attributeGroup = XmlSchemaAttributeGroup.Read(reader,h);
+ if(attributeGroup != null)
+ schema.items.Add(attributeGroup);
+ continue;
+ }
+ if(reader.LocalName == "element")
+ {
+ XmlSchemaElement element = XmlSchemaElement.Read(reader,h);
+ if(element != null)
+ schema.items.Add(element);
+ continue;
+ }
+ if(reader.LocalName == "attribute")
+ {
+ XmlSchemaAttribute attr = XmlSchemaAttribute.Read(reader,h);
+ if(attr != null)
+ schema.items.Add(attr);
+ continue;
+ }
+ if(reader.LocalName == "notation")
+ {
+ XmlSchemaNotation notation = XmlSchemaNotation.Read(reader,h);
+ if(notation != null)
+ schema.items.Add(notation);
+ continue;
+ }
+ if(reader.LocalName == "annotation")
+ {
+ XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);
+ if(annotation != null)
+ schema.items.Add(annotation);
+ continue;
+ }
+ }
+ reader.RaiseInvalidElementError();
+ }
+ }
+ #endregion
+
+ #region write
+
+ public void Write(System.IO.Stream stream)
+ {
+ Write(stream,null);
+ }
+ public void Write(System.IO.TextWriter writer)
+ {
+ Write(writer,null);
+ }
+ public void Write(System.Xml.XmlWriter writer)
+ {
+ Write(writer,null);
+ }
+ public void Write(System.IO.Stream stream, System.Xml.XmlNamespaceManager namespaceManager)
+ {
+ Write(new XmlTextWriter(stream,null),namespaceManager);
+ }
+ public void Write(System.IO.TextWriter writer, System.Xml.XmlNamespaceManager namespaceManager)
+ {
+ XmlTextWriter xwriter = new XmlTextWriter(writer);
+ xwriter.Formatting = Formatting.Indented;
+ Write(xwriter,namespaceManager);
+ }
+
+ public void Write (System.Xml.XmlWriter writer, System.Xml.XmlNamespaceManager namespaceManager)
+ {
+ XmlSerializerNamespaces nss = new XmlSerializerNamespaces ();
+
+ if (namespaceManager != null) {
+ foreach (string name in namespaceManager) {
+ //xml and xmlns namespaces are added by default in namespaceManager.
+ //So we should ignore them
+ if (name !="xml" && name != "xmlns")
+ nss.Add (name, namespaceManager.LookupNamespace (name));
+ }
+ }
+
+ if (Namespaces != null && Namespaces.Count > 0) {
+ XmlQualifiedName [] qnames = Namespaces.ToArray ();
+ foreach (XmlQualifiedName qn in qnames)
+ nss.Add (qn.Name, qn.Namespace);
+ string p = String.Empty;
+ bool loop = true;
+ for (int idx = 1; loop; idx++) {
+ loop = false;
+ foreach (XmlQualifiedName qn in qnames)
+ if (qn.Name == p) {
+ p = "q" + idx;
+ loop = true;
+ break;
+ }
+ }
+ nss.Add (p, XmlSchema.Namespace);
+ }
+
+ if (nss.Count == 0) {
+ // Add the xml schema namespace. (It is done
+ // only when no entry exists in Namespaces).
+ nss.Add ("xs", XmlSchema.Namespace);
+ if (TargetNamespace != null)
+ nss.Add ("tns", TargetNamespace);
+ }
+
+ XmlSchemaSerializer xser = new XmlSchemaSerializer ();
+ XmlSerializerNamespaces backup = Namespaces;
+ try {
+ Namespaces = null;
+ xser.Serialize (writer, this, nss);
+ } finally {
+ Namespaces = backup;
+ }
+ writer.Flush();
+ }
+ #endregion
+ }
+
+ class XmlSchemaSerializer : XmlSerializer
+ {
+ protected override void Serialize (object o, XmlSerializationWriter writer)
+ {
+ XmlSchemaSerializationWriter w = writer as XmlSchemaSerializationWriter;
+ w.WriteRoot_XmlSchema ((XmlSchema) o);
+ }
+
+ protected override XmlSerializationWriter CreateWriter ()
+ {
+ return new XmlSchemaSerializationWriter ();
+ }
+ }
}