The Labs \ Source Viewer \ SSCLI \ System.Xml.Schema \ Preprocessor

  1. //------------------------------------------------------------------------------
  2. // <copyright file="Preprocessor.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. // <owner current="true" primary="true">priyal</owner>
  15. //------------------------------------------------------------------------------
  16. namespace System.Xml.Schema
  17. {
  18.    
  19.     using System.Collections;
  20.     using System.IO;
  21.     using System.Threading;
  22.     using System.Diagnostics;
  23.     using System.Collections.Generic;
  24.    
  25.     internal enum Compositor
  26.     {
  27.         Root,
  28.         Include,
  29.         Import,
  30.         Redefine
  31.     }
  32.    
  33.     class RedefineEntry
  34.     {
  35.         internal XmlSchemaRedefine redefine;
  36.         internal XmlSchema schemaToUpdate;
  37.        
  38.         public RedefineEntry(XmlSchemaRedefine external, XmlSchema schema)
  39.         {
  40.             redefine = external;
  41.             schemaToUpdate = schema;
  42.         }
  43.     }
  44.    
  45.     internal sealed class Preprocessor : BaseProcessor
  46.     {
  47.        
  48.         string Xmlns;
  49.         string NsXsi;
  50.         string targetNamespace;
  51.        
  52.         XmlSchema rootSchema;
  53.         XmlSchema currentSchema;
  54.        
  55.         XmlSchemaForm elementFormDefault;
  56.         XmlSchemaForm attributeFormDefault;
  57.         XmlSchemaDerivationMethod blockDefault;
  58.         XmlSchemaDerivationMethod finalDefault;
  59.        
  60. /*Dictionary<Uri, XmlSchema> schemaLocations;
  61.         Dictionary<ChameleonKey, XmlSchema> chameleonSchemas;*/       
  62.         Hashtable schemaLocations;
  63.         Hashtable chameleonSchemas;
  64.        
  65.         Hashtable referenceNamespaces;
  66.         Hashtable processedExternals;
  67.         SortedList lockList;
  68.        
  69.         XmlReaderSettings readerSettings;
  70.        
  71.         //For redefines
  72.         XmlSchema rootSchemaForRedefine = null;
  73.         ArrayList redefinedList;
  74.        
  75.         static XmlSchema builtInSchemaForXmlNS;
  76.        
  77.         const XmlSchemaDerivationMethod schemaBlockDefaultAllowed = XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.Extension | XmlSchemaDerivationMethod.Substitution;
  78.         const XmlSchemaDerivationMethod schemaFinalDefaultAllowed = XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.Extension | XmlSchemaDerivationMethod.List | XmlSchemaDerivationMethod.Union;
  79.         const XmlSchemaDerivationMethod elementBlockAllowed = XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.Extension | XmlSchemaDerivationMethod.Substitution;
  80.         const XmlSchemaDerivationMethod elementFinalAllowed = XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.Extension;
  81.         const XmlSchemaDerivationMethod simpleTypeFinalAllowed = XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.Extension | XmlSchemaDerivationMethod.List | XmlSchemaDerivationMethod.Union;
  82.         const XmlSchemaDerivationMethod complexTypeBlockAllowed = XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.Extension;
  83.         const XmlSchemaDerivationMethod complexTypeFinalAllowed = XmlSchemaDerivationMethod.Restriction | XmlSchemaDerivationMethod.Extension;
  84.        
  85.         private XmlResolver xmlResolver = null;
  86.        
  87.         public Preprocessor(XmlNameTable nameTable, SchemaNames schemaNames, ValidationEventHandler eventHandler) : this(nameTable, schemaNames, eventHandler, new XmlSchemaCompilationSettings())
  88.         {
  89.         }
  90.        
  91.         public Preprocessor(XmlNameTable nameTable, SchemaNames schemaNames, ValidationEventHandler eventHandler, XmlSchemaCompilationSettings compilationSettings) : base(nameTable, schemaNames, eventHandler, compilationSettings)
  92.         {
  93.             referenceNamespaces = new Hashtable();
  94.             processedExternals = new Hashtable();
  95.             lockList = new SortedList();
  96.         }
  97.        
  98.        
  99.         public bool Execute(XmlSchema schema, string targetNamespace, bool loadExternals)
  100.         {
  101.             rootSchema = schema;
  102.             //Need to lock main schema here
  103.             Xmlns = NameTable.Add("xmlns");
  104.             NsXsi = NameTable.Add(XmlReservedNs.NsXsi);
  105.            
  106.             rootSchema.ImportedSchemas.Clear();
  107.             rootSchema.ImportedNamespaces.Clear();
  108.            
  109.             //Add root schema to the schemaLocations table
  110.             if (rootSchema.BaseUri != null) {
  111.                 if (schemaLocations[rootSchema.BaseUri] == null) {
  112.                     schemaLocations.Add(rootSchema.BaseUri, rootSchema);
  113.                 }
  114.             }
  115.             //Check targetNamespace for rootSchema
  116.             if (rootSchema.TargetNamespace != null) {
  117.                 if (targetNamespace == null) {
  118.                     targetNamespace = rootSchema.TargetNamespace;
  119.                 }
  120.                 else if (targetNamespace != rootSchema.TargetNamespace) {
  121.                     SendValidationEvent(Res.Sch_MismatchTargetNamespaceEx, targetNamespace, rootSchema.TargetNamespace, rootSchema);
  122.                 }
  123.             }
  124.             else if (targetNamespace != null && targetNamespace.Length != 0) {
  125.                 //if schema.TargetNamespace == null & targetNamespace != null, we will force the schema components into targetNamespace
  126.                 rootSchema = GetChameleonSchema(targetNamespace, rootSchema);
  127.                 //Chameleon include at top-level
  128.             }
  129.             if (loadExternals && xmlResolver != null) {
  130.                 LoadExternals(rootSchema);
  131.             }
  132.             BuildSchemaList(rootSchema);
  133.             int schemaIndex = 0;
  134.             XmlSchema listSchema;
  135.             try {
  136.                 //Accquire locks on all schema objects; Need to lock only on pre-created schemas and not parsed schemas
  137.                 for (schemaIndex = 0; schemaIndex < lockList.Count; schemaIndex++) {
  138.                     listSchema = (XmlSchema)lockList.GetByIndex(schemaIndex);
  139.                     Monitor.Enter(listSchema);
  140.                     listSchema.IsProcessing = false;
  141.                     //Reset processing flag from LoadExternals
  142.                 }
  143.                 //Preprocess
  144.                 rootSchemaForRedefine = rootSchema;
  145.                 Preprocess(rootSchema, targetNamespace, rootSchema.ImportedSchemas);
  146.                 if (redefinedList != null) {
  147.                     //If there were redefines
  148.                     foreach (RedefineEntry redefineEntry in redefinedList) {
  149.                         PreprocessRedefine(redefineEntry);
  150.                     }
  151.                 }
  152.             }
  153.             finally {
  154.                 //Releasing locks in finally block
  155.                 if (schemaIndex == lockList.Count) {
  156.                     schemaIndex--;
  157.                 }
  158.                
  159.                 for (int i = schemaIndex; schemaIndex >= 0; schemaIndex--) {
  160.                     listSchema = (XmlSchema)lockList.GetByIndex(schemaIndex);
  161.                     listSchema.IsProcessing = false;
  162.                     //Reset processing flag from Preprocess
  163.                     if (listSchema == Preprocessor.GetBuildInSchema()) {
  164.                         //dont re-set compiled flags for xml namespace schema
  165.                         Monitor.Exit(listSchema);
  166.                         continue;
  167.                     }
  168.                     listSchema.IsCompiledBySet = false;
  169.                     listSchema.IsPreprocessed = !HasErrors;
  170.                     Monitor.Exit(listSchema);
  171.                     //Release locks on all schema objects
  172.                 }
  173.             }
  174.             rootSchema.IsPreprocessed = !HasErrors;
  175.             //For chameleon at top-level
  176.             return !HasErrors;
  177.         }
  178.        
  179.         private void Cleanup(XmlSchema schema)
  180.         {
  181.             if (schema == Preprocessor.GetBuildInSchema()) {
  182.                 return;
  183.             }
  184.             schema.Attributes.Clear();
  185.             schema.AttributeGroups.Clear();
  186.             schema.SchemaTypes.Clear();
  187.             schema.Elements.Clear();
  188.             schema.Groups.Clear();
  189.             schema.Notations.Clear();
  190.             schema.Ids.Clear();
  191.             schema.IdentityConstraints.Clear();
  192.             schema.IsRedefined = false;
  193.             schema.IsCompiledBySet = false;
  194.         }
  195.        
  196.         private void CleanupRedefine(XmlSchemaExternal include)
  197.         {
  198.             XmlSchemaRedefine rdef = include as XmlSchemaRedefine;
  199.             rdef.AttributeGroups.Clear();
  200.             rdef.Groups.Clear();
  201.             rdef.SchemaTypes.Clear();
  202.         }
  203.        
  204.         internal XmlResolver XmlResolver {
  205.             set { xmlResolver = value; }
  206.         }
  207.        
  208.         internal XmlReaderSettings ReaderSettings {
  209.             get {
  210.                 if (readerSettings == null) {
  211.                     readerSettings = new XmlReaderSettings();
  212.                     readerSettings.ProhibitDtd = true;
  213.                 }
  214.                 return readerSettings;
  215.             }
  216.             set { readerSettings = value; }
  217.         }
  218.        
  219.         //internal Dictionary<Uri, XmlSchema> SchemaLocations {
  220.         internal Hashtable SchemaLocations {
  221.             set { schemaLocations = value; }
  222.         }
  223.        
  224.        
  225.         //internal Dictionary<ChameleonKey, XmlSchema> ChameleonSchemas {
  226.         internal Hashtable ChameleonSchemas {
  227.             set { chameleonSchemas = value; }
  228.         }
  229.        
  230.         internal XmlSchema RootSchema {
  231.                 //This is required to get back a cloned chameleon
  232.             get { return rootSchema; }
  233.         }
  234.        
  235.         private void BuildSchemaList(XmlSchema schema)
  236.         {
  237.             if (lockList.Contains(schema.SchemaId)) {
  238.                 return;
  239.             }
  240.             lockList.Add(schema.SchemaId, schema);
  241.             foreach (XmlSchemaExternal ext in schema.Includes) {
  242.                 if (ext.Schema != null) {
  243.                     BuildSchemaList(ext.Schema);
  244.                 }
  245.             }
  246.         }
  247.        
  248.         private void LoadExternals(XmlSchema schema)
  249.         {
  250.             if (schema.IsProcessing) {
  251.                 return;
  252.             }
  253.             schema.IsProcessing = true;
  254.             foreach (XmlSchemaExternal include in schema.Includes) {
  255.                 Uri includeLocation = null;
  256.                 //CASE 1: If the Schema object of the include has been set
  257.                 XmlSchema includedSchema = include.Schema;
  258.                 if (includedSchema != null) {
  259.                     // already loaded
  260.                     includeLocation = includedSchema.BaseUri;
  261.                     if (includeLocation != null && schemaLocations[includeLocation] == null) {
  262.                         schemaLocations.Add(includeLocation, includedSchema);
  263.                     }
  264.                     LoadExternals(includedSchema);
  265.                     continue;
  266.                 }
  267.                
  268.                 //CASE 2: Try & Parse schema from the provided location
  269.                 string schemaLocation = include.SchemaLocation;
  270.                 Uri ruri = null;
  271.                 Exception innerException = null;
  272.                 if (schemaLocation != null) {
  273.                     try {
  274.                         ruri = ResolveSchemaLocationUri(schema, schemaLocation);
  275.                     }
  276.                     catch (Exception e) {
  277.                         ruri = null;
  278.                         innerException = e;
  279.                     }
  280.                 }
  281.                
  282.                 if (include.Compositor == Compositor.Import) {
  283.                     XmlSchemaImport import = include as XmlSchemaImport;
  284.                     Debug.Assert(import != null);
  285.                     string importNS = import.Namespace != null ? import.Namespace : string.Empty;
  286.                     if (!schema.ImportedNamespaces.Contains(importNS)) {
  287.                         schema.ImportedNamespaces.Add(importNS);
  288.                     }
  289.                     //CASE 2.1: If the imported namespace is the XML namespace,
  290.                     // If the parent schemaSet already has schema for XML ns loaded, use that
  291.                     // Else if the location is null use the built-in one
  292.                     // else go through regular processing of parsing from location
  293.                     if (importNS == XmlReservedNs.NsXml) {
  294.                         if (ruri == null) {
  295.                             //Resolved location is null, hence get the built-in one
  296.                             include.Schema = Preprocessor.GetBuildInSchema();
  297.                             continue;
  298.                         }
  299.                     }
  300.                 }
  301.                
  302.                 //CASE 3: Parse schema from the provided location
  303.                 if (ruri == null) {
  304.                     if (schemaLocation != null) {
  305.                         SendValidationEvent(new XmlSchemaException(Res.Sch_InvalidIncludeLocation, null, innerException, include.SourceUri, include.LineNumber, include.LinePosition, include), XmlSeverityType.Warning);
  306.                     }
  307.                     continue;
  308.                 }
  309.                
  310.                 if (schemaLocations[ruri] == null) {
  311.                     // Only if location already not processed
  312.                     object obj = null;
  313.                     try {
  314.                         obj = GetSchemaEntity(ruri);
  315.                     }
  316.                     catch (Exception eInner) {
  317.                         innerException = eInner;
  318.                         obj = null;
  319.                     }
  320.                    
  321.                     if (obj != null) {
  322.                         include.BaseUri = ruri;
  323.                         Type returnType = obj.GetType();
  324.                         if (typeof(XmlSchema).IsAssignableFrom(returnType)) {
  325.                             //To handle XmlSchema and all its derived types
  326.                             include.Schema = (XmlSchema)obj;
  327.                             schemaLocations.Add(ruri, include.Schema);
  328.                             LoadExternals(include.Schema);
  329.                         }
  330.                         else {
  331.                             XmlReader reader = null;
  332.                             if (returnType.IsSubclassOf(typeof(Stream))) {
  333.                                 readerSettings.CloseInput = true;
  334.                                 readerSettings.XmlResolver = xmlResolver;
  335.                                 reader = XmlReader.Create((Stream)obj, readerSettings, ruri.ToString());
  336.                             }
  337.                             else if (returnType.IsSubclassOf(typeof(XmlReader))) {
  338.                                 reader = (XmlReader)obj;
  339.                             }
  340.                             else if (returnType.IsSubclassOf(typeof(TextReader))) {
  341.                                 readerSettings.CloseInput = true;
  342.                                 readerSettings.XmlResolver = xmlResolver;
  343.                                 reader = XmlReader.Create((TextReader)obj, readerSettings, ruri.ToString());
  344.                             }
  345.                             if (reader == null) {
  346.                                 SendValidationEvent(Res.Sch_InvalidIncludeLocation, include, XmlSeverityType.Warning);
  347.                                 continue;
  348.                             }
  349.                             try {
  350.                                 Parser parser = new Parser(SchemaType.XSD, NameTable, SchemaNames, EventHandler);
  351.                                 parser.Parse(reader, null);
  352.                                 while (reader.Read())
  353.                                     ;
  354.                                 // wellformness check
  355.                                 includedSchema = parser.XmlSchema;
  356.                                 include.Schema = includedSchema;
  357.                                 schemaLocations.Add(ruri, includedSchema);
  358.                                 LoadExternals(includedSchema);
  359.                             }
  360.                             catch (XmlSchemaException e) {
  361.                                 SendValidationEvent(Res.Sch_CannotLoadSchemaLocation, schemaLocation, e.Message, e.SourceUri, e.LineNumber, e.LinePosition);
  362.                             }
  363.                             catch (Exception eInner) {
  364.                                 SendValidationEvent(new XmlSchemaException(Res.Sch_InvalidIncludeLocation, null, eInner, include.SourceUri, include.LineNumber, include.LinePosition, include), XmlSeverityType.Warning);
  365.                             }
  366.                             finally {
  367.                                 reader.Close();
  368.                             }
  369.                         }
  370.                     }
  371.                     else {
  372.                         SendValidationEvent(new XmlSchemaException(Res.Sch_InvalidIncludeLocation, null, innerException, include.SourceUri, include.LineNumber, include.LinePosition, include), XmlSeverityType.Warning);
  373.                     }
  374.                 }
  375.                 else {
  376.                     //Location already in table and now seeing duplicate import / include
  377.                     include.Schema = (XmlSchema)schemaLocations[ruri];
  378.                     //Set schema object even for duplicates
  379.                 }
  380.             }
  381.         }
  382.        
  383.        
  384.         static internal XmlSchema GetBuildInSchema()
  385.         {
  386.             if (builtInSchemaForXmlNS == null) {
  387.                 XmlSchema tempSchema = new XmlSchema();
  388.                 tempSchema.TargetNamespace = XmlReservedNs.NsXml;
  389.                 tempSchema.Namespaces.Add("xml", XmlReservedNs.NsXml);
  390.                
  391.                 XmlSchemaAttribute lang = new XmlSchemaAttribute();
  392.                 lang.Name = "lang";
  393.                 lang.SchemaTypeName = new XmlQualifiedName("language", XmlReservedNs.NsXs);
  394.                 tempSchema.Items.Add(lang);
  395.                
  396.                 XmlSchemaAttribute xmlbase = new XmlSchemaAttribute();
  397.                 xmlbase.Name = "base";
  398.                 xmlbase.SchemaTypeName = new XmlQualifiedName("anyURI", XmlReservedNs.NsXs);
  399.                 tempSchema.Items.Add(xmlbase);
  400.                
  401.                 XmlSchemaAttribute space = new XmlSchemaAttribute();
  402.                 space.Name = "space";
  403.                 XmlSchemaSimpleType type = new XmlSchemaSimpleType();
  404.                 XmlSchemaSimpleTypeRestriction r = new XmlSchemaSimpleTypeRestriction();
  405.                 r.BaseTypeName = new XmlQualifiedName("NCName", XmlReservedNs.NsXs);
  406.                 XmlSchemaEnumerationFacet space_default = new XmlSchemaEnumerationFacet();
  407.                 space_default.Value = "default";
  408.                 r.Facets.Add(space_default);
  409.                 XmlSchemaEnumerationFacet space_preserve = new XmlSchemaEnumerationFacet();
  410.                 space_preserve.Value = "preserve";
  411.                 r.Facets.Add(space_preserve);
  412.                 type.Content = r;
  413.                 space.SchemaType = type;
  414.                 space.DefaultValue = "preserve";
  415.                 tempSchema.Items.Add(space);
  416.                
  417.                 XmlSchemaAttributeGroup attributeGroup = new XmlSchemaAttributeGroup();
  418.                 attributeGroup.Name = "specialAttrs";
  419.                 XmlSchemaAttribute langRef = new XmlSchemaAttribute();
  420.                 langRef.RefName = new XmlQualifiedName("lang", XmlReservedNs.NsXml);
  421.                 attributeGroup.Attributes.Add(langRef);
  422.                 XmlSchemaAttribute spaceRef = new XmlSchemaAttribute();
  423.                 spaceRef.RefName = new XmlQualifiedName("space", XmlReservedNs.NsXml);
  424.                 attributeGroup.Attributes.Add(spaceRef);
  425.                 XmlSchemaAttribute baseRef = new XmlSchemaAttribute();
  426.                 baseRef.RefName = new XmlQualifiedName("base", XmlReservedNs.NsXml);
  427.                 attributeGroup.Attributes.Add(baseRef);
  428.                 tempSchema.Items.Add(attributeGroup);
  429.                 tempSchema.IsPreprocessed = true;
  430.                 tempSchema.CompileSchemaInSet(new NameTable(), null, null);
  431.                 //compile built-in schema
  432.                 Interlocked.CompareExchange<XmlSchema>(ref builtInSchemaForXmlNS, tempSchema, null);
  433.             }
  434.             return builtInSchemaForXmlNS;
  435.         }
  436.        
  437.         private void BuildRefNamespaces(XmlSchema schema)
  438.         {
  439.             referenceNamespaces.Clear();
  440.             XmlSchemaImport import;
  441.             string ns;
  442.            
  443.             //Add XSD namespace
  444.             referenceNamespaces.Add(XmlReservedNs.NsXs, XmlReservedNs.NsXs);
  445.            
  446.             foreach (XmlSchemaExternal include in schema.Includes) {
  447.                 if (include is XmlSchemaImport) {
  448.                     import = include as XmlSchemaImport;
  449.                     ns = import.Namespace;
  450.                     if (ns == null) {
  451.                         ns = string.Empty;
  452.                     }
  453.                     if (referenceNamespaces[ns] == null)
  454.                         referenceNamespaces.Add(ns, ns);
  455.                 }
  456.             }
  457.            
  458.             //Add the schema's targetnamespace
  459.             string tns = schema.TargetNamespace;
  460.             if (tns == null) {
  461.                 tns = string.Empty;
  462.             }
  463.             if (referenceNamespaces[tns] == null) {
  464.                 referenceNamespaces.Add(tns, tns);
  465.             }
  466.            
  467.         }
  468.        
  469.         private void ParseUri(string uri, string code, XmlSchemaObject sourceSchemaObject)
  470.         {
  471.             try {
  472.                 XmlConvert.ToUri(uri);
  473.                 // can throw
  474.             }
  475.             catch (FormatException eInner) {
  476.                 SendValidationEvent(code, new string[] {uri}, eInner, sourceSchemaObject);
  477.             }
  478.         }
  479.        
  480.         private void Preprocess(XmlSchema schema, string targetNamespace, ArrayList imports)
  481.         {
  482.             XmlSchema prevRootSchemaForRedefine = null;
  483.             if (schema.IsProcessing) {
  484.                 return;
  485.             }
  486.             schema.IsProcessing = true;
  487.            
  488.             string tns = schema.TargetNamespace;
  489.             if (tns != null) {
  490.                 schema.TargetNamespace = tns = NameTable.Add(tns);
  491.                 if (tns.Length == 0) {
  492.                     SendValidationEvent(Res.Sch_InvalidTargetNamespaceAttribute, schema);
  493.                 }
  494.                 else {
  495.                     ParseUri(tns, Res.Sch_InvalidNamespace, schema);
  496.                 }
  497.             }
  498.             if (schema.Version != null) {
  499.                 XmlSchemaDatatype tokenDt = DatatypeImplementation.GetSimpleTypeFromTypeCode(XmlTypeCode.Token).Datatype;
  500.                 object version;
  501.                 Exception exception = tokenDt.TryParseValue(schema.Version, null, null, out version);
  502.                 if (exception != null) {
  503.                     SendValidationEvent(Res.Sch_AttributeValueDataTypeDetailed, new string[] {"version", schema.Version, tokenDt.TypeCodeString, exception.Message}, exception, schema);
  504.                 }
  505.                 else {
  506.                     schema.Version = (string)version;
  507.                 }
  508.             }
  509.            
  510.             //Begin processing the schema after checking targetNamespace and verifying chameleon
  511.             Cleanup(schema);
  512.            
  513.             foreach (XmlSchemaExternal include in schema.Includes) {
  514.                 XmlSchema externalSchema = include.Schema;
  515.                 SetParent(include, schema);
  516.                 PreprocessAnnotation(include);
  517.                 string loc = include.SchemaLocation;
  518.                 if (loc != null) {
  519.                     ParseUri(loc, Res.Sch_InvalidSchemaLocation, include);
  520.                 }
  521.                 else if ((include.Compositor == Compositor.Include || include.Compositor == Compositor.Redefine) && include.Schema == null) {
  522.                     SendValidationEvent(Res.Sch_MissRequiredAttribute, "schemaLocation", include);
  523.                    
  524.                 }
  525.                
  526.                 switch (include.Compositor) {
  527.                     case Compositor.Import:
  528.                         XmlSchemaImport import = include as XmlSchemaImport;
  529.                         string importNS = import.Namespace;
  530.                         if (importNS == schema.TargetNamespace) {
  531.                             SendValidationEvent(Res.Sch_ImportTargetNamespace, include);
  532.                         }
  533.                         if (externalSchema != null) {
  534.                             if (importNS != externalSchema.TargetNamespace) {
  535.                                 SendValidationEvent(Res.Sch_MismatchTargetNamespaceImport, importNS, externalSchema.TargetNamespace, import);
  536.                             }
  537.                             //SetParent(externalSchema, import);
  538.                             prevRootSchemaForRedefine = rootSchemaForRedefine;
  539.                             rootSchemaForRedefine = externalSchema;
  540.                             //Make the imported schema the root schema for redefines
  541.                             Preprocess(externalSchema, importNS, imports);
  542.                             rootSchemaForRedefine = prevRootSchemaForRedefine;
  543.                             //Reset the root schema for redefines
  544.                         }
  545.                         else {
  546.                             if (importNS != null) {
  547.                                 if (importNS.Length == 0) {
  548.                                     SendValidationEvent(Res.Sch_InvalidNamespaceAttribute, importNS, include);
  549.                                 }
  550.                                 else {
  551.                                     ParseUri(importNS, Res.Sch_InvalidNamespace, include);
  552.                                 }
  553.                             }
  554.                         }
  555.                         break;
  556.                     case Compositor.Include:
  557.                         XmlSchema includedSchema = include.Schema;
  558.                         if (includedSchema != null) {
  559.                             //SetParent(includedSchema, include);
  560.                             goto default;
  561.                         }
  562.                         break;
  563.                     case Compositor.Redefine:
  564.                        
  565.                         if (externalSchema != null) {
  566.                             //SetParent(externalSchema, include);
  567.                             CleanupRedefine(include);
  568.                             goto default;
  569.                         }
  570.                         break;
  571.                     default:
  572.                        
  573.                         //For include, redefine common case
  574.                         if (externalSchema.TargetNamespace != null) {
  575.                             if (schema.TargetNamespace != externalSchema.TargetNamespace) {
  576.                                 //namespaces for includes should be the same
  577.                                 SendValidationEvent(Res.Sch_MismatchTargetNamespaceInclude, externalSchema.TargetNamespace, schema.TargetNamespace, include);
  578.                             }
  579.                         }
  580.                         else if (targetNamespace != null && targetNamespace.Length != 0) {
  581.                             //Chameleon redefine
  582.                             externalSchema = GetChameleonSchema(targetNamespace, externalSchema);
  583.                             include.Schema = externalSchema;
  584.                             //Reset the schema property to the cloned schema
  585.                         }
  586.                         Preprocess(externalSchema, schema.TargetNamespace, imports);
  587.                         break;
  588.                 }
  589.             }
  590.            
  591.             //Begin processing the current schema passed to preprocess
  592.             //Build the namespaces that can be referenced in the current schema
  593.             this.currentSchema = schema;
  594.             BuildRefNamespaces(schema);
  595.             ValidateIdAttribute(schema);
  596.            
  597.             this.targetNamespace = targetNamespace == null ? string.Empty : targetNamespace;
  598.            
  599.             SetSchemaDefaults(schema);
  600.            
  601.             processedExternals.Clear();
  602.             XmlSchemaExternal external;
  603.             for (int i = 0; i < schema.Includes.Count; i++) {
  604.                 external = (XmlSchemaExternal)schema.Includes[i];
  605.                 XmlSchema includedSchema = external.Schema;
  606.                 if (includedSchema != null) {
  607.                     switch (external.Compositor) {
  608.                         case Compositor.Include:
  609.                             if (processedExternals[includedSchema] != null) {
  610.                                 continue;
  611.                             }
  612.                             processedExternals.Add(includedSchema, external);
  613.                             CopyIncludedComponents(includedSchema, schema);
  614.                             break;
  615.                         case Compositor.Redefine:
  616.                            
  617.                             if (redefinedList == null) {
  618.                                 redefinedList = new ArrayList();
  619.                             }
  620.                             redefinedList.Add(new RedefineEntry(external as XmlSchemaRedefine, rootSchemaForRedefine));
  621.                             if (processedExternals[includedSchema] != null) {
  622.                                 continue;
  623.                             }
  624.                             processedExternals.Add(includedSchema, external);
  625.                             CopyIncludedComponents(includedSchema, schema);
  626.                             break;
  627.                         case Compositor.Import:
  628.                            
  629.                             if (includedSchema != rootSchema) {
  630.                                 XmlSchemaImport import = external as XmlSchemaImport;
  631.                                 string importNS = import.Namespace != null ? import.Namespace : string.Empty;
  632.                                 if (!imports.Contains(includedSchema)) {
  633.                                     //TODO Change ImportedSchemas to Hashtable
  634.                                     imports.Add(includedSchema);
  635.                                 }
  636.                                 if (!rootSchema.ImportedNamespaces.Contains(importNS)) {
  637.                                     rootSchema.ImportedNamespaces.Add(importNS);
  638.                                 }
  639.                             }
  640.                             break;
  641.                         default:
  642.                            
  643.                             Debug.Assert(false);
  644.                             break;
  645.                     }
  646.                 }
  647.                 else if (external.Compositor == Compositor.Redefine) {
  648.                     XmlSchemaRedefine redefine = external as XmlSchemaRedefine;
  649.                     if (redefine.BaseUri == null) {
  650.                         foreach (XmlSchemaObject item in redefine.Items) {
  651.                             if (!(item is XmlSchemaAnnotation)) {
  652.                                 SendValidationEvent(Res.Sch_RedefineNoSchema, redefine);
  653.                                 break;
  654.                             }
  655.                         }
  656.                     }
  657.                 }
  658.                 ValidateIdAttribute(external);
  659.             }
  660.            
  661.             ArrayList removeItemsList = new ArrayList();
  662.             foreach (XmlSchemaObject item in schema.Items) {
  663.                 SetParent(item, schema);
  664.                 if (item is XmlSchemaAttribute) {
  665.                     XmlSchemaAttribute attribute = (XmlSchemaAttribute)item;
  666.                     PreprocessAttribute(attribute);
  667.                     AddToTable(schema.Attributes, attribute.QualifiedName, attribute);
  668.                 }
  669.                 else if (item is XmlSchemaAttributeGroup) {
  670.                     XmlSchemaAttributeGroup attributeGroup = (XmlSchemaAttributeGroup)item;
  671.                     PreprocessAttributeGroup(attributeGroup);
  672.                     AddToTable(schema.AttributeGroups, attributeGroup.QualifiedName, attributeGroup);
  673.                 }
  674.                 else if (item is XmlSchemaComplexType) {
  675.                     XmlSchemaComplexType complexType = (XmlSchemaComplexType)item;
  676.                     PreprocessComplexType(complexType, false);
  677.                     AddToTable(schema.SchemaTypes, complexType.QualifiedName, complexType);
  678.                 }
  679.                 else if (item is XmlSchemaSimpleType) {
  680.                     XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)item;
  681.                     PreprocessSimpleType(simpleType, false);
  682.                     AddToTable(schema.SchemaTypes, simpleType.QualifiedName, simpleType);
  683.                 }
  684.                 else if (item is XmlSchemaElement) {
  685.                     XmlSchemaElement element = (XmlSchemaElement)item;
  686.                     PreprocessElement(element);
  687.                     AddToTable(schema.Elements, element.QualifiedName, element);
  688.                 }
  689.                 else if (item is XmlSchemaGroup) {
  690.                     XmlSchemaGroup group = (XmlSchemaGroup)item;
  691.                     PreprocessGroup(group);
  692.                     AddToTable(schema.Groups, group.QualifiedName, group);
  693.                 }
  694.                 else if (item is XmlSchemaNotation) {
  695.                     XmlSchemaNotation notation = (XmlSchemaNotation)item;
  696.                     PreprocessNotation(notation);
  697.                     AddToTable(schema.Notations, notation.QualifiedName, notation);
  698.                 }
  699.                 else if (item is XmlSchemaAnnotation) {
  700.                     PreprocessAnnotation(item as XmlSchemaAnnotation);
  701.                 }
  702.                 else {
  703.                     SendValidationEvent(Res.Sch_InvalidCollection, (XmlSchemaObject)item);
  704.                     removeItemsList.Add(item);
  705.                 }
  706.             }
  707.             foreach (XmlSchemaObject item in removeItemsList) {
  708.                 schema.Items.Remove(item);
  709.             }
  710.         }
  711.        
  712.         private void CopyIncludedComponents(XmlSchema includedSchema, XmlSchema schema)
  713.         {
  714.             foreach (XmlSchemaElement element in includedSchema.Elements.Values) {
  715.                 AddToTable(schema.Elements, element.QualifiedName, element);
  716.             }
  717.             foreach (XmlSchemaAttribute attribute in includedSchema.Attributes.Values) {
  718.                 AddToTable(schema.Attributes, attribute.QualifiedName, attribute);
  719.             }
  720.             foreach (XmlSchemaGroup group in includedSchema.Groups.Values) {
  721.                 AddToTable(schema.Groups, group.QualifiedName, group);
  722.             }
  723.             foreach (XmlSchemaAttributeGroup attributeGroup in includedSchema.AttributeGroups.Values) {
  724.                 AddToTable(schema.AttributeGroups, attributeGroup.QualifiedName, attributeGroup);
  725.             }
  726.             foreach (XmlSchemaType type in includedSchema.SchemaTypes.Values) {
  727.                 AddToTable(schema.SchemaTypes, type.QualifiedName, type);
  728.             }
  729.             foreach (XmlSchemaNotation notation in includedSchema.Notations.Values) {
  730.                 AddToTable(schema.Notations, notation.QualifiedName, notation);
  731.             }
  732.         }
  733.        
  734.         private void PreprocessRedefine(RedefineEntry redefineEntry)
  735.         {
  736.             XmlSchemaRedefine redefine = redefineEntry.redefine;
  737.             XmlSchema originalSchema = redefine.Schema;
  738.            
  739.             currentSchema = GetParentSchema(redefine);
  740.             //Set this for correct schema context in ValidateIdAttribute & ValidateQNameAttribute for redefines
  741.             Debug.Assert(currentSchema != null);
  742.             SetSchemaDefaults(currentSchema);
  743.            
  744.             if (originalSchema.IsRedefined) {
  745.                 SendValidationEvent(Res.Sch_MultipleRedefine, redefine, XmlSeverityType.Warning);
  746.                 return;
  747.             }
  748.             originalSchema.IsRedefined = true;
  749.            
  750.             XmlSchema schemaToUpdate = redefineEntry.schemaToUpdate;
  751.             ArrayList includesOfRedefine = new ArrayList();
  752.             GetIncludedSet(originalSchema, includesOfRedefine);
  753.             string targetNS = schemaToUpdate.TargetNamespace == null ? string.Empty : schemaToUpdate.TargetNamespace;
  754.            
  755.             foreach (XmlSchemaObject item in redefine.Items) {
  756.                 SetParent(item, redefine);
  757.                 if (item is XmlSchemaGroup) {
  758.                     XmlSchemaGroup group = (XmlSchemaGroup)item;
  759.                     PreprocessGroup(group);
  760.                     group.QualifiedName.SetNamespace(targetNS);
  761.                     //Since PreprocessGroup will use this.targetNamespace and that will be that of the root schema's
  762.                     if (redefine.Groups[group.QualifiedName] != null) {
  763.                         SendValidationEvent(Res.Sch_GroupDoubleRedefine, group);
  764.                     }
  765.                     else {
  766.                         AddToTable(redefine.Groups, group.QualifiedName, group);
  767.                         XmlSchemaGroup originalGroup = (XmlSchemaGroup)schemaToUpdate.Groups[group.QualifiedName];
  768.                         XmlSchema parentSchema = GetParentSchema(originalGroup);
  769.                         if (originalGroup == null || (parentSchema != originalSchema && !includesOfRedefine.Contains(parentSchema))) {
  770.                             SendValidationEvent(Res.Sch_ComponentRedefineNotFound, "<group>", group.QualifiedName.ToString(), group);
  771.                         }
  772.                         else {
  773.                             group.Redefined = originalGroup;
  774.                             schemaToUpdate.Groups.Insert(group.QualifiedName, group);
  775.                             CheckRefinedGroup(group);
  776.                         }
  777.                     }
  778.                 }
  779.                 else if (item is XmlSchemaAttributeGroup) {
  780.                     XmlSchemaAttributeGroup attributeGroup = (XmlSchemaAttributeGroup)item;
  781.                     PreprocessAttributeGroup(attributeGroup);
  782.                     attributeGroup.QualifiedName.SetNamespace(targetNS);
  783.                     //Since PreprocessAttributeGroup will use this.targetNamespace and that will be that of the root schema's
  784.                     if (redefine.AttributeGroups[attributeGroup.QualifiedName] != null) {
  785.                         SendValidationEvent(Res.Sch_AttrGroupDoubleRedefine, attributeGroup);
  786.                     }
  787.                     else {
  788.                         AddToTable(redefine.AttributeGroups, attributeGroup.QualifiedName, attributeGroup);
  789.                         XmlSchemaAttributeGroup originalAttrGroup = (XmlSchemaAttributeGroup)schemaToUpdate.AttributeGroups[attributeGroup.QualifiedName];
  790.                         XmlSchema parentSchema = GetParentSchema(originalAttrGroup);
  791.                         if (originalAttrGroup == null || (parentSchema != originalSchema && !includesOfRedefine.Contains(parentSchema))) {
  792.                             SendValidationEvent(Res.Sch_ComponentRedefineNotFound, "<attributeGroup>", attributeGroup.QualifiedName.ToString(), attributeGroup);
  793.                         }
  794.                         else {
  795.                             attributeGroup.Redefined = originalAttrGroup;
  796.                             schemaToUpdate.AttributeGroups.Insert(attributeGroup.QualifiedName, attributeGroup);
  797.                             CheckRefinedAttributeGroup(attributeGroup);
  798.                         }
  799.                     }
  800.                 }
  801.                 else if (item is XmlSchemaComplexType) {
  802.                     XmlSchemaComplexType complexType = (XmlSchemaComplexType)item;
  803.                     PreprocessComplexType(complexType, false);
  804.                     complexType.QualifiedName.SetNamespace(targetNS);
  805.                     //Since PreprocessComplexType will use this.targetNamespace and that will be that of the root schema's
  806.                     if (redefine.SchemaTypes[complexType.QualifiedName] != null) {
  807.                         SendValidationEvent(Res.Sch_ComplexTypeDoubleRedefine, complexType);
  808.                     }
  809.                     else {
  810.                         AddToTable(redefine.SchemaTypes, complexType.QualifiedName, complexType);
  811.                         XmlSchemaType originalType = (XmlSchemaType)schemaToUpdate.SchemaTypes[complexType.QualifiedName];
  812.                         XmlSchema parentSchema = GetParentSchema(originalType);
  813.                         if (originalType == null || (parentSchema != originalSchema && !includesOfRedefine.Contains(parentSchema))) {
  814.                             SendValidationEvent(Res.Sch_ComponentRedefineNotFound, "<complexType>", complexType.QualifiedName.ToString(), complexType);
  815.                         }
  816.                         else if (originalType is XmlSchemaComplexType) {
  817.                             complexType.Redefined = originalType;
  818.                             schemaToUpdate.SchemaTypes.Insert(complexType.QualifiedName, complexType);
  819.                             CheckRefinedComplexType(complexType);
  820.                         }
  821.                         else {
  822.                             SendValidationEvent(Res.Sch_SimpleToComplexTypeRedefine, complexType);
  823.                         }
  824.                     }
  825.                 }
  826.                 else if (item is XmlSchemaSimpleType) {
  827.                     XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType)item;
  828.                     PreprocessSimpleType(simpleType, false);
  829.                     simpleType.QualifiedName.SetNamespace(targetNS);
  830.                     //Since PreprocessSimpleType will use this.targetNamespace and that will be that of the root schema's
  831.                     if (redefine.SchemaTypes[simpleType.QualifiedName] != null) {
  832.                         SendValidationEvent(Res.Sch_SimpleTypeDoubleRedefine, simpleType);
  833.                     }
  834.                     else {
  835.                         AddToTable(redefine.SchemaTypes, simpleType.QualifiedName, simpleType);
  836.                         XmlSchemaType originalType = (XmlSchemaType)schemaToUpdate.SchemaTypes[simpleType.QualifiedName];
  837.                         XmlSchema parentSchema = GetParentSchema(originalType);
  838.                         if (originalType == null || (parentSchema != originalSchema && !includesOfRedefine.Contains(parentSchema))) {
  839.                             SendValidationEvent(Res.Sch_ComponentRedefineNotFound, "<simpleType>", simpleType.QualifiedName.ToString(), simpleType);
  840.                         }
  841.                         else if (originalType is XmlSchemaSimpleType) {
  842.                             simpleType.Redefined = originalType;
  843.                             schemaToUpdate.SchemaTypes.Insert(simpleType.QualifiedName, simpleType);
  844.                             CheckRefinedSimpleType(simpleType);
  845.                         }
  846.                         else {
  847.                             SendValidationEvent(Res.Sch_ComplexToSimpleTypeRedefine, simpleType);
  848.                         }
  849.                     }
  850.                 }
  851.             }
  852.         }
  853.        
  854.         private void GetIncludedSet(XmlSchema schema, ArrayList includesList)
  855.         {
  856.             if (includesList.Contains(schema)) {
  857.                 return;
  858.             }
  859.             includesList.Add(schema);
  860.             foreach (XmlSchemaExternal external in schema.Includes) {
  861.                 if (external.Compositor == Compositor.Include || external.Compositor == Compositor.Redefine) {
  862.                     if (external.Schema != null) {
  863.                         GetIncludedSet(external.Schema, includesList);
  864.                     }
  865.                 }
  866.             }
  867.         }
  868.        
  869.         static internal XmlSchema GetParentSchema(XmlSchemaObject currentSchemaObject)
  870.         {
  871.             XmlSchema parentSchema = null;
  872.             Debug.Assert((currentSchemaObject as XmlSchema) == null);
  873.             //The current object should not be schema
  874.             while (parentSchema == null && currentSchemaObject != null) {
  875.                 currentSchemaObject = currentSchemaObject.Parent;
  876.                 parentSchema = currentSchemaObject as XmlSchema;
  877.             }
  878.             return parentSchema;
  879.         }
  880.        
  881.         private void SetSchemaDefaults(XmlSchema schema)
  882.         {
  883.             if (schema.BlockDefault == XmlSchemaDerivationMethod.All) {
  884.                 this.blockDefault = XmlSchemaDerivationMethod.All;
  885.             }
  886.             else if (schema.BlockDefault == XmlSchemaDerivationMethod.None) {
  887.                 this.blockDefault = XmlSchemaDerivationMethod.Empty;
  888.             }
  889.             else {
  890.                 if ((schema.BlockDefault & ~schemaBlockDefaultAllowed) != 0) {
  891.                     SendValidationEvent(Res.Sch_InvalidBlockDefaultValue, schema);
  892.                 }
  893.                 this.blockDefault = schema.BlockDefault & schemaBlockDefaultAllowed;
  894.             }
  895.             if (schema.FinalDefault == XmlSchemaDerivationMethod.All) {
  896.                 this.finalDefault = XmlSchemaDerivationMethod.All;
  897.             }
  898.             else if (schema.FinalDefault == XmlSchemaDerivationMethod.None) {
  899.                 this.finalDefault = XmlSchemaDerivationMethod.Empty;
  900.             }
  901.             else {
  902.                 if ((schema.FinalDefault & ~schemaFinalDefaultAllowed) != 0) {
  903.                     SendValidationEvent(Res.Sch_InvalidFinalDefaultValue, schema);
  904.                 }
  905.                 this.finalDefault = schema.FinalDefault & schemaFinalDefaultAllowed;
  906.             }
  907.             this.elementFormDefault = schema.ElementFormDefault;
  908.             if (this.elementFormDefault == XmlSchemaForm.None) {
  909.                 this.elementFormDefault = XmlSchemaForm.Unqualified;
  910.             }
  911.             this.attributeFormDefault = schema.AttributeFormDefault;
  912.             if (this.attributeFormDefault == XmlSchemaForm.None) {
  913.                 this.attributeFormDefault = XmlSchemaForm.Unqualified;
  914.             }
  915.         }
  916.        
  917.         private int CountGroupSelfReference(XmlSchemaObjectCollection items, XmlQualifiedName name, XmlSchemaGroup redefined)
  918.         {
  919.             int count = 0;
  920.             foreach (XmlSchemaParticle particle in items) {
  921.                 if (particle is XmlSchemaGroupRef) {
  922.                     XmlSchemaGroupRef groupRef = (XmlSchemaGroupRef)particle;
  923.                     if (groupRef.RefName == name) {
  924.                         groupRef.Redefined = redefined;
  925.                         if (groupRef.MinOccurs != decimal.One || groupRef.MaxOccurs != decimal.One) {
  926.                             SendValidationEvent(Res.Sch_MinMaxGroupRedefine, groupRef);
  927.                         }
  928.                         count++;
  929.                     }
  930.                 }
  931.                 else if (particle is XmlSchemaGroupBase) {
  932.                     count += CountGroupSelfReference(((XmlSchemaGroupBase)particle).Items, name, redefined);
  933.                 }
  934.                 if (count > 1) {
  935.                     break;
  936.                 }
  937.             }
  938.             return count;
  939.            
  940.         }
  941.        
  942.         private void CheckRefinedGroup(XmlSchemaGroup group)
  943.         {
  944.             int count = 0;
  945.             if (group.Particle != null) {
  946.                 count = CountGroupSelfReference(group.Particle.Items, group.QualifiedName, group.Redefined);
  947.             }
  948.             if (count > 1) {
  949.                 SendValidationEvent(Res.Sch_MultipleGroupSelfRef, group);
  950.             }
  951.             group.SelfReferenceCount = count;
  952.         }
  953.        
  954.         private void CheckRefinedAttributeGroup(XmlSchemaAttributeGroup attributeGroup)
  955.         {
  956.             int count = 0;
  957.             foreach (object obj in attributeGroup.Attributes) {
  958.                 if (obj is XmlSchemaAttributeGroupRef && ((XmlSchemaAttributeGroupRef)obj).RefName == attributeGroup.QualifiedName) {
  959.                     count++;
  960.                 }
  961.             }
  962.             if (count > 1) {
  963.                 SendValidationEvent(Res.Sch_MultipleAttrGroupSelfRef, attributeGroup);
  964.             }
  965.             attributeGroup.SelfReferenceCount = count;
  966.         }
  967.        
  968.         private void CheckRefinedSimpleType(XmlSchemaSimpleType stype)
  969.         {
  970.             if (stype.Content != null && stype.Content is XmlSchemaSimpleTypeRestriction) {
  971.                 XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction)stype.Content;
  972.                 if (restriction.BaseTypeName == stype.QualifiedName) {
  973.                     return;
  974.                 }
  975.             }
  976.             SendValidationEvent(Res.Sch_InvalidTypeRedefine, stype);
  977.         }
  978.        
  979.         private void CheckRefinedComplexType(XmlSchemaComplexType ctype)
  980.         {
  981.             if (ctype.ContentModel != null) {
  982.                 XmlQualifiedName baseName;
  983.                 if (ctype.ContentModel is XmlSchemaComplexContent) {
  984.                     XmlSchemaComplexContent content = (XmlSchemaComplexContent)ctype.ContentModel;
  985.                     if (content.Content is XmlSchemaComplexContentRestriction) {
  986.                         baseName = ((XmlSchemaComplexContentRestriction)content.Content).BaseTypeName;
  987.                     }
  988.                     else {
  989.                         baseName = ((XmlSchemaComplexContentExtension)content.Content).BaseTypeName;
  990.                     }
  991.                 }
  992.                 else {
  993.                     XmlSchemaSimpleContent content = (XmlSchemaSimpleContent)ctype.ContentModel;
  994.                     if (content.Content is XmlSchemaSimpleContentRestriction) {
  995.                         baseName = ((XmlSchemaSimpleContentRestriction)content.Content).BaseTypeName;
  996.                     }
  997.                     else {
  998.                         baseName = ((XmlSchemaSimpleContentExtension)content.Content).BaseTypeName;
  999.                     }
  1000.                 }
  1001.                 if (baseName == ctype.QualifiedName) {
  1002.                     return;
  1003.                 }
  1004.             }
  1005.             SendValidationEvent(Res.Sch_InvalidTypeRedefine, ctype);
  1006.         }
  1007.        
  1008.         private void PreprocessAttribute(XmlSchemaAttribute attribute)
  1009.         {
  1010.             if (attribute.Name != null) {
  1011.                 ValidateNameAttribute(attribute);
  1012.                 attribute.SetQualifiedName(new XmlQualifiedName(attribute.Name, this.targetNamespace));
  1013.             }
  1014.             else {
  1015.                 SendValidationEvent(Res.Sch_MissRequiredAttribute, "name", attribute);
  1016.             }
  1017.             if (attribute.Use != XmlSchemaUse.None) {
  1018.                 SendValidationEvent(Res.Sch_ForbiddenAttribute, "use", attribute);
  1019.             }
  1020.             if (attribute.Form != XmlSchemaForm.None) {
  1021.                 SendValidationEvent(Res.Sch_ForbiddenAttribute, "form", attribute);
  1022.             }
  1023.             PreprocessAttributeContent(attribute);
  1024.             ValidateIdAttribute(attribute);
  1025.         }
  1026.        
  1027.         private void PreprocessLocalAttribute(XmlSchemaAttribute attribute)
  1028.         {
  1029.             if (attribute.Name != null) {
  1030.                 // name
  1031.                 ValidateNameAttribute(attribute);
  1032.                 PreprocessAttributeContent(attribute);
  1033.                 attribute.SetQualifiedName(new XmlQualifiedName(attribute.Name, (attribute.Form == XmlSchemaForm.Qualified || (attribute.Form == XmlSchemaForm.None && this.attributeFormDefault == XmlSchemaForm.Qualified)) ? this.targetNamespace : null));
  1034.             }
  1035.             else {
  1036.                 // ref
  1037.                 PreprocessAnnotation(attribute);
  1038.                 //set parent of annotation child of ref
  1039.                 if (attribute.RefName.IsEmpty) {
  1040.                     SendValidationEvent(Res.Sch_AttributeNameRef, "???", attribute);
  1041.                 }
  1042.                 else {
  1043.                     ValidateQNameAttribute(attribute, "ref", attribute.RefName);
  1044.                 }
  1045.                 if (!attribute.SchemaTypeName.IsEmpty || attribute.SchemaType != null || attribute.Form != XmlSchemaForm.None)/*||
  1046.                     attribute.DefaultValue != null ||
  1047.                     attribute.FixedValue != null*/ {
  1048.                     SendValidationEvent(Res.Sch_InvalidAttributeRef, attribute);
  1049.                 }
  1050.                 attribute.SetQualifiedName(attribute.RefName);
  1051.             }
  1052.             ValidateIdAttribute(attribute);
  1053.         }
  1054.        
  1055.         private void PreprocessAttributeContent(XmlSchemaAttribute attribute)
  1056.         {
  1057.             PreprocessAnnotation(attribute);
  1058.            
  1059.             if (Ref.Equal(currentSchema.TargetNamespace, NsXsi)) {
  1060.                 SendValidationEvent(Res.Sch_TargetNamespaceXsi, attribute);
  1061.             }
  1062.            
  1063.             if (!attribute.RefName.IsEmpty) {
  1064.                 SendValidationEvent(Res.Sch_ForbiddenAttribute, "ref", attribute);
  1065.             }
  1066.             if (attribute.DefaultValue != null && attribute.FixedValue != null) {
  1067.                 SendValidationEvent(Res.Sch_DefaultFixedAttributes, attribute);
  1068.             }
  1069.             if (attribute.DefaultValue != null && attribute.Use != XmlSchemaUse.Optional && attribute.Use != XmlSchemaUse.None) {
  1070.                 SendValidationEvent(Res.Sch_OptionalDefaultAttribute, attribute);
  1071.             }
  1072.             if (attribute.Name == Xmlns) {
  1073.                 SendValidationEvent(Res.Sch_XmlNsAttribute, attribute);
  1074.             }
  1075.             if (attribute.SchemaType != null) {
  1076.                 SetParent(attribute.SchemaType, attribute);
  1077.                 if (!attribute.SchemaTypeName.IsEmpty) {
  1078.                     SendValidationEvent(Res.Sch_TypeMutualExclusive, attribute);
  1079.                 }
  1080.                 PreprocessSimpleType(attribute.SchemaType, true);
  1081.             }
  1082.             if (!attribute.SchemaTypeName.IsEmpty) {
  1083.                 ValidateQNameAttribute(attribute, "type", attribute.SchemaTypeName);
  1084.             }
  1085.         }
  1086.        
  1087.         private void PreprocessAttributeGroup(XmlSchemaAttributeGroup attributeGroup)
  1088.         {
  1089.             if (attributeGroup.Name != null) {
  1090.                 ValidateNameAttribute(attributeGroup);
  1091.                 attributeGroup.SetQualifiedName(new XmlQualifiedName(attributeGroup.Name, this.targetNamespace));
  1092.             }
  1093.             else {
  1094.                 SendValidationEvent(Res.Sch_MissRequiredAttribute, "name", attributeGroup);
  1095.             }
  1096.             PreprocessAttributes(attributeGroup.Attributes, attributeGroup.AnyAttribute, attributeGroup);
  1097.             PreprocessAnnotation(attributeGroup);
  1098.             ValidateIdAttribute(attributeGroup);
  1099.         }
  1100.        
  1101.         private void PreprocessElement(XmlSchemaElement element)
  1102.         {
  1103.             if (element.Name != null) {
  1104.                 ValidateNameAttribute(element);
  1105.                 element.SetQualifiedName(new XmlQualifiedName(element.Name, this.targetNamespace));
  1106.             }
  1107.             else {
  1108.                 SendValidationEvent(Res.Sch_MissRequiredAttribute, "name", element);
  1109.             }
  1110.             PreprocessElementContent(element);
  1111.            
  1112.             if (element.Final == XmlSchemaDerivationMethod.All) {
  1113.                 element.SetFinalResolved(XmlSchemaDerivationMethod.All);
  1114.             }
  1115.             else if (element.Final == XmlSchemaDerivationMethod.None) {
  1116.                 if (this.finalDefault == XmlSchemaDerivationMethod.All) {
  1117.                     element.SetFinalResolved(XmlSchemaDerivationMethod.All);
  1118.                 }
  1119.                 else {
  1120.                     element.SetFinalResolved(this.finalDefault & elementFinalAllowed);
  1121.                 }
  1122.             }
  1123.             else {
  1124.                 if ((element.Final & ~elementFinalAllowed) != 0) {
  1125.                     SendValidationEvent(Res.Sch_InvalidElementFinalValue, element);
  1126.                 }
  1127.                 element.SetFinalResolved(element.Final & elementFinalAllowed);
  1128.             }
  1129.             if (element.Form != XmlSchemaForm.None) {
  1130.                 SendValidationEvent(Res.Sch_ForbiddenAttribute, "form", element);
  1131.             }
  1132.             if (element.MinOccursString != null) {
  1133.                 SendValidationEvent(Res.Sch_ForbiddenAttribute, "minOccurs", element);
  1134.             }
  1135.             if (element.MaxOccursString != null) {
  1136.                 SendValidationEvent(Res.Sch_ForbiddenAttribute, "maxOccurs", element);
  1137.             }
  1138.             if (!element.SubstitutionGroup.IsEmpty) {
  1139.                 ValidateQNameAttribute(element, "type", element.SubstitutionGroup);
  1140.             }
  1141.             ValidateIdAttribute(element);
  1142.         }
  1143.        
  1144.         private void PreprocessLocalElement(XmlSchemaElement element)
  1145.         {
  1146.             if (element.Name != null) {
  1147.                 // name
  1148.                 ValidateNameAttribute(element);
  1149.                 PreprocessElementContent(element);
  1150.                 element.SetQualifiedName(new XmlQualifiedName(element.Name, (element.Form == XmlSchemaForm.Qualified || (element.Form == XmlSchemaForm.None && this.elementFormDefault == XmlSchemaForm.Qualified)) ? this.targetNamespace : null));
  1151.             }
  1152.             else {
  1153.                 // ref
  1154.                 PreprocessAnnotation(element);
  1155.                 //Check annotation child for ref and set parent
  1156.                 if (element.RefName.IsEmpty) {
  1157.                     SendValidationEvent(Res.Sch_ElementNameRef, element);
  1158.                 }
  1159.                 else {
  1160.                     ValidateQNameAttribute(element, "ref", element.RefName);
  1161.                 }
  1162.                 if (!element.SchemaTypeName.IsEmpty || element.HasAbstractAttribute || element.Block != XmlSchemaDerivationMethod.None || element.SchemaType != null || element.HasConstraints || element.DefaultValue != null || element.Form != XmlSchemaForm.None || element.FixedValue != null || element.HasNillableAttribute) {
  1163.                     SendValidationEvent(Res.Sch_InvalidElementRef, element);
  1164.                 }
  1165.                 if (element.DefaultValue != null && element.FixedValue != null) {
  1166.                     SendValidationEvent(Res.Sch_DefaultFixedAttributes, element);
  1167.                 }
  1168.                 element.SetQualifiedName(element.RefName);
  1169.             }
  1170.             if (element.MinOccurs > element.MaxOccurs) {
  1171.                 element.MinOccurs = decimal.Zero;
  1172.                 SendValidationEvent(Res.Sch_MinGtMax, element);
  1173.             }
  1174.             if (element.HasAbstractAttribute) {
  1175.                 SendValidationEvent(Res.Sch_ForbiddenAttribute, "abstract", element);
  1176.             }
  1177.             if (element.Final != XmlSchemaDerivationMethod.None) {
  1178.                 SendValidationEvent(Res.Sch_ForbiddenAttribute, "final", element);
  1179.             }
  1180.             if (!element.SubstitutionGroup.IsEmpty) {
  1181.                 SendValidationEvent(Res.Sch_ForbiddenAttribute, "substitutionGroup", element);
  1182.             }
  1183.             ValidateIdAttribute(element);
  1184.         }
  1185.        
  1186.         private void PreprocessElementContent(XmlSchemaElement element)
  1187.         {
  1188.             PreprocessAnnotation(element);
  1189.             //Set parent for Annotation child of element
  1190.             if (!element.RefName.IsEmpty) {
  1191.                 SendValidationEvent(Res.Sch_ForbiddenAttribute, "ref", element);
  1192.             }
  1193.             if (element.Block == XmlSchemaDerivationMethod.All) {
  1194.                 element.SetBlockResolved(XmlSchemaDerivationMethod.All);
  1195.             }
  1196.             else if (element.Block == XmlSchemaDerivationMethod.None) {
  1197.                 if (this.blockDefault == XmlSchemaDerivationMethod.All) {
  1198.                     element.SetBlockResolved(XmlSchemaDerivationMethod.All);
  1199.                 }
  1200.                 else {
  1201.                     element.SetBlockResolved(this.blockDefault & elementBlockAllowed);
  1202.                 }
  1203.             }
  1204.             else {
  1205.                 if ((element.Block & ~elementBlockAllowed) != 0) {
  1206.                     SendValidationEvent(Res.Sch_InvalidElementBlockValue, element);
  1207.                 }
  1208.                 element.SetBlockResolved(element.Block & elementBlockAllowed);
  1209.             }
  1210.             if (element.SchemaType != null) {
  1211.                 SetParent(element.SchemaType, element);
  1212.                 //Set parent for simple / complex type child of element
  1213.                 if (!element.SchemaTypeName.IsEmpty) {
  1214.                     SendValidationEvent(Res.Sch_TypeMutualExclusive, element);
  1215.                 }
  1216.                 if (element.SchemaType is XmlSchemaComplexType) {
  1217.                     PreprocessComplexType((XmlSchemaComplexType)element.SchemaType, true);
  1218.                 }
  1219.                 else {
  1220.                     PreprocessSimpleType((XmlSchemaSimpleType)element.SchemaType, true);
  1221.                 }
  1222.             }
  1223.             if (!element.SchemaTypeName.IsEmpty) {
  1224.                 ValidateQNameAttribute(element, "type", element.SchemaTypeName);
  1225.             }
  1226.             if (element.DefaultValue != null && element.FixedValue != null) {
  1227.                 SendValidationEvent(Res.Sch_DefaultFixedAttributes, element);
  1228.             }
  1229.             foreach (XmlSchemaIdentityConstraint identityConstraint in element.Constraints) {
  1230.                 SetParent(identityConstraint, element);
  1231.                 PreprocessIdentityConstraint(identityConstraint);
  1232.             }
  1233.         }
  1234.        
  1235.         private void PreprocessIdentityConstraint(XmlSchemaIdentityConstraint constraint)
  1236.         {
  1237.             bool valid = true;
  1238.             PreprocessAnnotation(constraint);
  1239.             //Set parent of annotation child of key/keyref/unique
  1240.             if (constraint.Name != null) {
  1241.                 ValidateNameAttribute(constraint);
  1242.                 constraint.SetQualifiedName(new XmlQualifiedName(constraint.Name, this.targetNamespace));
  1243.             }
  1244.             else {
  1245.                 SendValidationEvent(Res.Sch_MissRequiredAttribute, "name", constraint);
  1246.                 valid = false;
  1247.             }
  1248.            
  1249.             if (rootSchema.IdentityConstraints[constraint.QualifiedName] != null) {
  1250.                 SendValidationEvent(Res.Sch_DupIdentityConstraint, constraint.QualifiedName.ToString(), constraint);
  1251.                 valid = false;
  1252.             }
  1253.             else {
  1254.                 rootSchema.IdentityConstraints.Add(constraint.QualifiedName, constraint);
  1255.             }
  1256.            
  1257.             if (constraint.Selector == null) {
  1258.                 SendValidationEvent(Res.Sch_IdConstraintNoSelector, constraint);
  1259.                 valid = false;
  1260.             }
  1261.             if (constraint.Fields.Count == 0) {
  1262.                 SendValidationEvent(Res.Sch_IdConstraintNoFields, constraint);
  1263.                 valid = false;
  1264.             }
  1265.             if (constraint is XmlSchemaKeyref) {
  1266.                 XmlSchemaKeyref keyref = (XmlSchemaKeyref)constraint;
  1267.                 if (keyref.Refer.IsEmpty) {
  1268.                     SendValidationEvent(Res.Sch_IdConstraintNoRefer, constraint);
  1269.                     valid = false;
  1270.                 }
  1271.                 else {
  1272.                     ValidateQNameAttribute(keyref, "refer", keyref.Refer);
  1273.                 }
  1274.             }
  1275.             if (valid) {
  1276.                 ValidateIdAttribute(constraint);
  1277.                 ValidateIdAttribute(constraint.Selector);
  1278.                 SetParent(constraint.Selector, constraint);
  1279.                 foreach (XmlSchemaXPath field in constraint.Fields) {
  1280.                     SetParent(field, constraint);
  1281.                     ValidateIdAttribute(field);
  1282.                 }
  1283.             }
  1284.         }
  1285.        
  1286.         private void PreprocessSimpleType(XmlSchemaSimpleType simpleType, bool local)
  1287.         {
  1288.             if (local) {
  1289.                 if (simpleType.Name != null) {
  1290.                     SendValidationEvent(Res.Sch_ForbiddenAttribute, "name", simpleType);
  1291.                 }
  1292.             }
  1293.             else {
  1294.                 if (simpleType.Name != null) {
  1295.                     ValidateNameAttribute(simpleType);
  1296.                     simpleType.SetQualifiedName(new XmlQualifiedName(simpleType.Name, this.targetNamespace));
  1297.                 }
  1298.                 else {
  1299.                     SendValidationEvent(Res.Sch_MissRequiredAttribute, "name", simpleType);
  1300.                 }
  1301.                
  1302.                 if (simpleType.Final == XmlSchemaDerivationMethod.All) {
  1303.                     simpleType.SetFinalResolved(XmlSchemaDerivationMethod.All);
  1304.                 }
  1305.                 else if (simpleType.Final == XmlSchemaDerivationMethod.None) {
  1306.                     if (this.finalDefault == XmlSchemaDerivationMethod.All) {
  1307.                         simpleType.SetFinalResolved(XmlSchemaDerivationMethod.All);
  1308.                     }
  1309.                     else {
  1310.                         simpleType.SetFinalResolved(this.finalDefault & simpleTypeFinalAllowed);
  1311.                     }
  1312.                 }
  1313.                 else {
  1314.                     if ((simpleType.Final & ~simpleTypeFinalAllowed) != 0) {
  1315.                         SendValidationEvent(Res.Sch_InvalidSimpleTypeFinalValue, simpleType);
  1316.                     }
  1317.                     simpleType.SetFinalResolved(simpleType.Final & simpleTypeFinalAllowed);
  1318.                 }
  1319.             }
  1320.            
  1321.             if (simpleType.Content == null) {
  1322.                 SendValidationEvent(Res.Sch_NoSimpleTypeContent, simpleType);
  1323.             }
  1324.             else if (simpleType.Content is XmlSchemaSimpleTypeRestriction) {
  1325.                 XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction)simpleType.Content;
  1326.                 //SetParent
  1327.                 SetParent(restriction, simpleType);
  1328.                 foreach (XmlSchemaObject facetObj in restriction.Facets) {
  1329.                     SetParent(facetObj, restriction);
  1330.                 }
  1331.                
  1332.                 if (restriction.BaseType != null) {
  1333.                     if (!restriction.BaseTypeName.IsEmpty) {
  1334.                         SendValidationEvent(Res.Sch_SimpleTypeRestRefBase, restriction);
  1335.                     }
  1336.                     PreprocessSimpleType(restriction.BaseType, true);
  1337.                 }
  1338.                 else {
  1339.                     if (restriction.BaseTypeName.IsEmpty) {
  1340.                         SendValidationEvent(Res.Sch_SimpleTypeRestRefBaseNone, restriction);
  1341.                     }
  1342.                     else {
  1343.                         ValidateQNameAttribute(restriction, "base", restriction.BaseTypeName);
  1344.                     }
  1345.                 }
  1346.                 PreprocessAnnotation(restriction);
  1347.                 //set parent of annotation child of simple type restriction
  1348.                 ValidateIdAttribute(restriction);
  1349.             }
  1350.             else if (simpleType.Content is XmlSchemaSimpleTypeList) {
  1351.                 XmlSchemaSimpleTypeList list = (XmlSchemaSimpleTypeList)simpleType.Content;
  1352.                 SetParent(list, simpleType);
  1353.                
  1354.                 if (list.ItemType != null) {
  1355.                     if (!list.ItemTypeName.IsEmpty) {
  1356.                         SendValidationEvent(Res.Sch_SimpleTypeListRefBase, list);
  1357.                     }
  1358.                     SetParent(list.ItemType, list);
  1359.                     PreprocessSimpleType(list.ItemType, true);
  1360.                 }
  1361.                 else {
  1362.                     if (list.ItemTypeName.IsEmpty) {
  1363.                         SendValidationEvent(Res.Sch_SimpleTypeListRefBaseNone, list);
  1364.                     }
  1365.                     else {
  1366.                         ValidateQNameAttribute(list, "itemType", list.ItemTypeName);
  1367.                     }
  1368.                 }
  1369.                 PreprocessAnnotation(list);
  1370.                 //set parent of annotation child of simple type list
  1371.                 ValidateIdAttribute(list);
  1372.             }
  1373.             else {
  1374.                 // union
  1375.                 XmlSchemaSimpleTypeUnion union1 = (XmlSchemaSimpleTypeUnion)simpleType.Content;
  1376.                 SetParent(union1, simpleType);
  1377.                
  1378.                 int baseTypeCount = union1.BaseTypes.Count;
  1379.                 if (union1.MemberTypes != null) {
  1380.                     baseTypeCount += union1.MemberTypes.Length;
  1381.                     foreach (XmlQualifiedName qname in union1.MemberTypes) {
  1382.                         ValidateQNameAttribute(union1, "memberTypes", qname);
  1383.                     }
  1384.                 }
  1385.                 if (baseTypeCount == 0) {
  1386.                     SendValidationEvent(Res.Sch_SimpleTypeUnionNoBase, union1);
  1387.                 }
  1388.                 foreach (XmlSchemaSimpleType type in union1.BaseTypes) {
  1389.                     SetParent(type, union1);
  1390.                     PreprocessSimpleType(type, true);
  1391.                 }
  1392.                 PreprocessAnnotation(union1);
  1393.                 //set parent of annotation child of simple type union
  1394.                 ValidateIdAttribute(union1);
  1395.             }
  1396.             ValidateIdAttribute(simpleType);
  1397.         }
  1398.        
  1399.         private void PreprocessComplexType(XmlSchemaComplexType complexType, bool local)
  1400.         {
  1401.             if (local) {
  1402.                 if (complexType.Name != null) {
  1403.                     SendValidationEvent(Res.Sch_ForbiddenAttribute, "name", complexType);
  1404.                 }
  1405.             }
  1406.             else {
  1407.                 if (complexType.Name != null) {
  1408.                     ValidateNameAttribute(complexType);
  1409.                     complexType.SetQualifiedName(new XmlQualifiedName(complexType.Name, this.targetNamespace));
  1410.                 }
  1411.                 else {
  1412.                     SendValidationEvent(Res.Sch_MissRequiredAttribute, "name", complexType);
  1413.                 }
  1414.                 if (complexType.Block == XmlSchemaDerivationMethod.All) {
  1415.                     complexType.SetBlockResolved(XmlSchemaDerivationMethod.All);
  1416.                 }
  1417.                 else if (complexType.Block == XmlSchemaDerivationMethod.None) {
  1418.                     complexType.SetBlockResolved(this.blockDefault & complexTypeBlockAllowed);
  1419.                 }
  1420.                 else {
  1421.                     if ((complexType.Block & ~complexTypeBlockAllowed) != 0) {
  1422.                         SendValidationEvent(Res.Sch_InvalidComplexTypeBlockValue, complexType);
  1423.                     }
  1424.                     complexType.SetBlockResolved(complexType.Block & complexTypeBlockAllowed);
  1425.                 }
  1426.                 if (complexType.Final == XmlSchemaDerivationMethod.All) {
  1427.                     complexType.SetFinalResolved(XmlSchemaDerivationMethod.All);
  1428.                 }
  1429.                 else if (complexType.Final == XmlSchemaDerivationMethod.None) {
  1430.                     if (this.finalDefault == XmlSchemaDerivationMethod.All) {
  1431.                         complexType.SetFinalResolved(XmlSchemaDerivationMethod.All);
  1432.                     }
  1433.                     else {
  1434.                         complexType.SetFinalResolved(this.finalDefault & complexTypeFinalAllowed);
  1435.                     }
  1436.                 }
  1437.                 else {
  1438.                     if ((complexType.Final & ~complexTypeFinalAllowed) != 0) {
  1439.                         SendValidationEvent(Res.Sch_InvalidComplexTypeFinalValue, complexType);
  1440.                     }
  1441.                     complexType.SetFinalResolved(complexType.Final & complexTypeFinalAllowed);
  1442.                 }
  1443.                
  1444.             }
  1445.            
  1446.             if (complexType.ContentModel != null) {
  1447.                 SetParent(complexType.ContentModel, complexType);
  1448.                 //SimpleContent / complexCotent
  1449.                 PreprocessAnnotation(complexType.ContentModel);
  1450.                
  1451.                 if (complexType.Particle != null || complexType.Attributes != null) {
  1452.                     // this is illigal
  1453.                 }
  1454.                 if (complexType.ContentModel is XmlSchemaSimpleContent) {
  1455.                     XmlSchemaSimpleContent content = (XmlSchemaSimpleContent)complexType.ContentModel;
  1456.                     if (content.Content == null) {
  1457.                         if (complexType.QualifiedName == XmlQualifiedName.Empty) {
  1458.                             SendValidationEvent(Res.Sch_NoRestOrExt, complexType);
  1459.                         }
  1460.                         else {
  1461.                             SendValidationEvent(Res.Sch_NoRestOrExtQName, complexType.QualifiedName.Name, complexType.QualifiedName.Namespace, complexType);
  1462.                         }
  1463.                     }
  1464.                     else {
  1465.                         SetParent(content.Content, content);
  1466.                         //simplecontent extension / restriction
  1467.                         PreprocessAnnotation(content.Content);
  1468.                         //annotation child of simple extension / restriction
  1469.                         if (content.Content is XmlSchemaSimpleContentExtension) {
  1470.                             XmlSchemaSimpleContentExtension contentExtension = (XmlSchemaSimpleContentExtension)content.Content;
  1471.                             if (contentExtension.BaseTypeName.IsEmpty) {
  1472.                                 SendValidationEvent(Res.Sch_MissAttribute, "base", contentExtension);
  1473.                             }
  1474.                             else {
  1475.                                 ValidateQNameAttribute(contentExtension, "base", contentExtension.BaseTypeName);
  1476.                             }
  1477.                             PreprocessAttributes(contentExtension.Attributes, contentExtension.AnyAttribute, contentExtension);
  1478.                             ValidateIdAttribute(contentExtension);
  1479.                         }
  1480.                         else {
  1481.                             //XmlSchemaSimpleContentRestriction
  1482.                             XmlSchemaSimpleContentRestriction contentRestriction = (XmlSchemaSimpleContentRestriction)content.Content;
  1483.                             if (contentRestriction.BaseTypeName.IsEmpty) {
  1484.                                 SendValidationEvent(Res.Sch_MissAttribute, "base", contentRestriction);
  1485.                             }
  1486.                             else {
  1487.                                 ValidateQNameAttribute(contentRestriction, "base", contentRestriction.BaseTypeName);
  1488.                             }
  1489.                             if (contentRestriction.BaseType != null) {
  1490.                                 SetParent(contentRestriction.BaseType, contentRestriction);
  1491.                                 PreprocessSimpleType(contentRestriction.BaseType, true);
  1492.                             }
  1493.                             PreprocessAttributes(contentRestriction.Attributes, contentRestriction.AnyAttribute, contentRestriction);
  1494.                             ValidateIdAttribute(contentRestriction);
  1495.                         }
  1496.                     }
  1497.                     ValidateIdAttribute(content);
  1498.                 }
  1499.                 else {
  1500.                     // XmlSchemaComplexContent
  1501.                     XmlSchemaComplexContent content = (XmlSchemaComplexContent)complexType.ContentModel;
  1502.                     if (content.Content == null) {
  1503.                         if (complexType.QualifiedName == XmlQualifiedName.Empty) {
  1504.                             SendValidationEvent(Res.Sch_NoRestOrExt, complexType);
  1505.                         }
  1506.                         else {
  1507.                             SendValidationEvent(Res.Sch_NoRestOrExtQName, complexType.QualifiedName.Name, complexType.QualifiedName.Namespace, complexType);
  1508.                         }
  1509.                     }
  1510.                     else {
  1511.                         if (!content.HasMixedAttribute && complexType.IsMixed) {
  1512.                             content.IsMixed = true;
  1513.                             // fixup
  1514.                         }
  1515.                         SetParent(content.Content, content);
  1516.                         //complexcontent extension / restriction
  1517.                         PreprocessAnnotation(content.Content);
  1518.                         //Annotation child of extension / restriction
  1519.                         if (content.Content is XmlSchemaComplexContentExtension) {
  1520.                             XmlSchemaComplexContentExtension contentExtension = (XmlSchemaComplexContentExtension)content.Content;
  1521.                             if (contentExtension.BaseTypeName.IsEmpty) {
  1522.                                 SendValidationEvent(Res.Sch_MissAttribute, "base", contentExtension);
  1523.                             }
  1524.                             else {
  1525.                                 ValidateQNameAttribute(contentExtension, "base", contentExtension.BaseTypeName);
  1526.                             }
  1527.                             if (contentExtension.Particle != null) {
  1528.                                 SetParent(contentExtension.Particle, contentExtension);
  1529.                                 //Group / all / choice / sequence
  1530.                                 PreprocessParticle(contentExtension.Particle);
  1531.                             }
  1532.                             PreprocessAttributes(contentExtension.Attributes, contentExtension.AnyAttribute, contentExtension);
  1533.                             ValidateIdAttribute(contentExtension);
  1534.                         }
  1535.                         else {
  1536.                             // XmlSchemaComplexContentRestriction
  1537.                             XmlSchemaComplexContentRestriction contentRestriction = (XmlSchemaComplexContentRestriction)content.Content;
  1538.                             if (contentRestriction.BaseTypeName.IsEmpty) {
  1539.                                 SendValidationEvent(Res.Sch_MissAttribute, "base", contentRestriction);
  1540.                             }
  1541.                             else {
  1542.                                 ValidateQNameAttribute(contentRestriction, "base", contentRestriction.BaseTypeName);
  1543.                             }
  1544.                             if (contentRestriction.Particle != null) {
  1545.                                 SetParent(contentRestriction.Particle, contentRestriction);
  1546.                                 //Group / all / choice / sequence
  1547.                                 PreprocessParticle(contentRestriction.Particle);
  1548.                             }
  1549.                             PreprocessAttributes(contentRestriction.Attributes, contentRestriction.AnyAttribute, contentRestriction);
  1550.                             ValidateIdAttribute(contentRestriction);
  1551.                         }
  1552.                         ValidateIdAttribute(content);
  1553.                     }
  1554.                 }
  1555.             }
  1556.             else {
  1557.                 if (complexType.Particle != null) {
  1558.                     SetParent(complexType.Particle, complexType);
  1559.                     PreprocessParticle(complexType.Particle);
  1560.                 }
  1561.                 PreprocessAttributes(complexType.Attributes, complexType.AnyAttribute, complexType);
  1562.             }
  1563.             ValidateIdAttribute(complexType);
  1564.         }
  1565.        
  1566.         private void PreprocessGroup(XmlSchemaGroup group)
  1567.         {
  1568.             if (group.Name != null) {
  1569.                 ValidateNameAttribute(group);
  1570.                 group.SetQualifiedName(new XmlQualifiedName(group.Name, this.targetNamespace));
  1571.             }
  1572.             else {
  1573.                 SendValidationEvent(Res.Sch_MissRequiredAttribute, "name", group);
  1574.             }
  1575.             if (group.Particle == null) {
  1576.                 SendValidationEvent(Res.Sch_NoGroupParticle, group);
  1577.                 return;
  1578.             }
  1579.             if (group.Particle.MinOccursString != null) {
  1580.                 SendValidationEvent(Res.Sch_ForbiddenAttribute, "minOccurs", group.Particle);
  1581.             }
  1582.             if (group.Particle.MaxOccursString != null) {
  1583.                 SendValidationEvent(Res.Sch_ForbiddenAttribute, "maxOccurs", group.Particle);
  1584.             }
  1585.            
  1586.             PreprocessParticle(group.Particle);
  1587.             PreprocessAnnotation(group);
  1588.             //Set parent of annotation child of group
  1589.             ValidateIdAttribute(group);
  1590.         }
  1591.        
  1592.         private void PreprocessNotation(XmlSchemaNotation notation)
  1593.         {
  1594.            
  1595.             if (notation.Name != null) {
  1596.                 ValidateNameAttribute(notation);
  1597.                 notation.QualifiedName = new XmlQualifiedName(notation.Name, this.targetNamespace);
  1598.             }
  1599.             else {
  1600.                 SendValidationEvent(Res.Sch_MissRequiredAttribute, "name", notation);
  1601.             }
  1602.             if (notation.Public == null && notation.System == null) {
  1603.                 SendValidationEvent(Res.Sch_MissingPublicSystemAttribute, notation);
  1604.             }
  1605.             else {
  1606.                 if (notation.Public != null) {
  1607.                     try {
  1608.                         XmlConvert.VerifyTOKEN(notation.Public);
  1609.                         // can throw
  1610.                     }
  1611.                     catch (XmlException eInner) {
  1612.                         SendValidationEvent(Res.Sch_InvalidPublicAttribute, new string[] {notation.Public}, eInner, notation);
  1613.                     }
  1614.                 }
  1615.                 if (notation.System != null) {
  1616.                     ParseUri(notation.System, Res.Sch_InvalidSystemAttribute, notation);
  1617.                 }
  1618.             }
  1619.             PreprocessAnnotation(notation);
  1620.             //Set parent of annotation child of notation
  1621.             ValidateIdAttribute(notation);
  1622.         }
  1623.        
  1624.        
  1625.         private void PreprocessParticle(XmlSchemaParticle particle)
  1626.         {
  1627.             if (particle is XmlSchemaAll) {
  1628.                 if (particle.MinOccurs != decimal.Zero && particle.MinOccurs != decimal.One) {
  1629.                     particle.MinOccurs = decimal.One;
  1630.                     SendValidationEvent(Res.Sch_InvalidAllMin, particle);
  1631.                 }
  1632.                 if (particle.MaxOccurs != decimal.One) {
  1633.                     particle.MaxOccurs = decimal.One;
  1634.                     SendValidationEvent(Res.Sch_InvalidAllMax, particle);
  1635.                 }
  1636.                 foreach (XmlSchemaElement element in ((XmlSchemaAll)particle).Items) {
  1637.                     if (element.MaxOccurs != decimal.Zero && element.MaxOccurs != decimal.One) {
  1638.                         element.MaxOccurs = decimal.One;
  1639.                         SendValidationEvent(Res.Sch_InvalidAllElementMax, element);
  1640.                     }
  1641.                     SetParent(element, particle);
  1642.                     PreprocessLocalElement(element);
  1643.                 }
  1644.             }
  1645.             else {
  1646.                 if (particle.MinOccurs > particle.MaxOccurs) {
  1647.                     particle.MinOccurs = particle.MaxOccurs;
  1648.                     SendValidationEvent(Res.Sch_MinGtMax, particle);
  1649.                 }
  1650.                 if (particle is XmlSchemaChoice) {
  1651.                     foreach (XmlSchemaObject item in ((XmlSchemaChoice)particle).Items) {
  1652.                         SetParent(item, particle);
  1653.                         if (item is XmlSchemaElement) {
  1654.                             PreprocessLocalElement((XmlSchemaElement)item);
  1655.                         }
  1656.                         else {
  1657.                             PreprocessParticle((XmlSchemaParticle)item);
  1658.                         }
  1659.                     }
  1660.                 }
  1661.                 else if (particle is XmlSchemaSequence) {
  1662.                     foreach (XmlSchemaObject item in ((XmlSchemaSequence)particle).Items) {
  1663.                         SetParent(item, particle);
  1664.                         if (item is XmlSchemaElement) {
  1665.                             PreprocessLocalElement((XmlSchemaElement)item);
  1666.                         }
  1667.                         else {
  1668.                             PreprocessParticle((XmlSchemaParticle)item);
  1669.                         }
  1670.                     }
  1671.                 }
  1672.                 else if (particle is XmlSchemaGroupRef) {
  1673.                     XmlSchemaGroupRef groupRef = (XmlSchemaGroupRef)particle;
  1674.                     if (groupRef.RefName.IsEmpty) {
  1675.                         SendValidationEvent(Res.Sch_MissAttribute, "ref", groupRef);
  1676.                     }
  1677.                     else {
  1678.                         ValidateQNameAttribute(groupRef, "ref", groupRef.RefName);
  1679.                     }
  1680.                 }
  1681.                 else if (particle is XmlSchemaAny) {
  1682.                     try {
  1683.                         ((XmlSchemaAny)particle).BuildNamespaceList(this.targetNamespace);
  1684.                     }
  1685.                     catch (FormatException fe) {
  1686.                         SendValidationEvent(Res.Sch_InvalidAnyDetailed, new string[] {fe.Message}, fe, particle);
  1687.                     }
  1688.                 }
  1689.             }
  1690.             PreprocessAnnotation(particle);
  1691.             //set parent of annotation child of group / all/ choice / sequence
  1692.             ValidateIdAttribute(particle);
  1693.         }
  1694.        
  1695.         private void PreprocessAttributes(XmlSchemaObjectCollection attributes, XmlSchemaAnyAttribute anyAttribute, XmlSchemaObject parent)
  1696.         {
  1697.             foreach (XmlSchemaAnnotated obj in attributes) {
  1698.                 SetParent(obj, parent);
  1699.                 if (obj is XmlSchemaAttribute) {
  1700.                     PreprocessLocalAttribute((XmlSchemaAttribute)obj);
  1701.                 }
  1702.                 else {
  1703.                     // XmlSchemaAttributeGroupRef
  1704.                     XmlSchemaAttributeGroupRef attributeGroupRef = (XmlSchemaAttributeGroupRef)obj;
  1705.                     if (attributeGroupRef.RefName.IsEmpty) {
  1706.                         SendValidationEvent(Res.Sch_MissAttribute, "ref", attributeGroupRef);
  1707.                     }
  1708.                     else {
  1709.                         ValidateQNameAttribute(attributeGroupRef, "ref", attributeGroupRef.RefName);
  1710.                     }
  1711.                     PreprocessAnnotation(obj);
  1712.                     //set parent of annotation child of attributeGroupRef
  1713.                     ValidateIdAttribute(obj);
  1714.                 }
  1715.             }
  1716.             if (anyAttribute != null) {
  1717.                 try {
  1718.                     SetParent(anyAttribute, parent);
  1719.                     PreprocessAnnotation(anyAttribute);
  1720.                     //set parent of annotation child of any attribute
  1721.                     anyAttribute.BuildNamespaceList(this.targetNamespace);
  1722.                 }
  1723.                 catch (FormatException fe) {
  1724.                     SendValidationEvent(Res.Sch_InvalidAnyDetailed, new string[] {fe.Message}, fe, anyAttribute);
  1725.                 }
  1726.                 ValidateIdAttribute(anyAttribute);
  1727.             }
  1728.         }
  1729.        
  1730.         private void ValidateIdAttribute(XmlSchemaObject xso)
  1731.         {
  1732.             if (xso.IdAttribute != null) {
  1733.                 try {
  1734.                     xso.IdAttribute = NameTable.Add(XmlConvert.VerifyNCName(xso.IdAttribute));
  1735.                 }
  1736.                 catch (XmlException ex) {
  1737.                     SendValidationEvent(Res.Sch_InvalidIdAttribute, new string[] {ex.Message}, ex, xso);
  1738.                     return;
  1739.                 }
  1740.                 catch (ArgumentNullException) {
  1741.                     SendValidationEvent(Res.Sch_InvalidIdAttribute, Res.GetString(Res.Sch_NullValue), xso);
  1742.                     return;
  1743.                 }
  1744.                 try {
  1745.                     currentSchema.Ids.Add(xso.IdAttribute, xso);
  1746.                 }
  1747.                 catch (ArgumentException) {
  1748.                     SendValidationEvent(Res.Sch_DupIdAttribute, xso);
  1749.                 }
  1750.             }
  1751.         }
  1752.        
  1753.         private void ValidateNameAttribute(XmlSchemaObject xso)
  1754.         {
  1755.             string name = xso.NameAttribute;
  1756.             if (name == null || name.Length == 0) {
  1757.                 SendValidationEvent(Res.Sch_InvalidNameAttributeEx, null, Res.GetString(Res.Sch_NullValue), xso);
  1758.             }
  1759.             //Normalize whitespace since NCName has whitespace facet="collapse"
  1760.             name = XmlComplianceUtil.NonCDataNormalize(name);
  1761.             int len = ValidateNames.ParseNCName(name, 0);
  1762.             if (len != name.Length) {
  1763.                 // If the string is not a valid NCName, then throw or return false
  1764.                 string innerStr = Res.GetString(Res.Xml_BadNameCharWithPos, XmlException.BuildCharExceptionStr(name[len])[0], XmlException.BuildCharExceptionStr(name[len])[1], len);
  1765.                 SendValidationEvent(Res.Sch_InvalidNameAttributeEx, name, innerStr, xso);
  1766.             }
  1767.             else {
  1768.                 xso.NameAttribute = NameTable.Add(name);
  1769.             }
  1770.         }
  1771.        
  1772.         private void ValidateQNameAttribute(XmlSchemaObject xso, string attributeName, XmlQualifiedName value)
  1773.         {
  1774.             try {
  1775.                 value.Verify();
  1776.                 value.Atomize(NameTable);
  1777.                 if (currentSchema.IsChameleon && value.Namespace.Length == 0) {
  1778.                     value.SetNamespace(currentSchema.TargetNamespace);
  1779.                     //chameleon schemas are clones that have correct targetNamespace set
  1780.                 }
  1781.                 if (referenceNamespaces[value.Namespace] == null) {
  1782.                     SendValidationEvent(Res.Sch_UnrefNS, value.Namespace, xso, XmlSeverityType.Warning);
  1783.                 }
  1784.             }
  1785.             catch (FormatException fx) {
  1786.                 SendValidationEvent(Res.Sch_InvalidAttribute, new string[] {attributeName, fx.Message}, fx, xso);
  1787.             }
  1788.             catch (XmlException ex) {
  1789.                 SendValidationEvent(Res.Sch_InvalidAttribute, new string[] {attributeName, ex.Message}, ex, xso);
  1790.             }
  1791.         }
  1792.        
  1793.         private Uri ResolveSchemaLocationUri(XmlSchema enclosingSchema, string location)
  1794.         {
  1795.             if (location.Length == 0) {
  1796.                 return null;
  1797.             }
  1798.             return xmlResolver.ResolveUri(enclosingSchema.BaseUri, location);
  1799.         }
  1800.        
  1801.         private object GetSchemaEntity(Uri ruri)
  1802.         {
  1803.             return xmlResolver.GetEntity(ruri, null, null);
  1804.         }
  1805.        
  1806.         private XmlSchema GetChameleonSchema(string targetNamespace, XmlSchema schema)
  1807.         {
  1808.             ChameleonKey cKey = new ChameleonKey(targetNamespace, schema.BaseUri);
  1809.             XmlSchema chameleonSchema = (XmlSchema)chameleonSchemas[cKey];
  1810.             //Need not clone if a schema for that namespace already exists
  1811.             if (chameleonSchema == null) {
  1812.                 chameleonSchema = schema.DeepClone();
  1813.                 //It is ok that we dont lock the clone since no one else has access to it yet
  1814.                 chameleonSchema.IsChameleon = true;
  1815.                 chameleonSchema.TargetNamespace = targetNamespace;
  1816.                 chameleonSchemas.Add(cKey, chameleonSchema);
  1817.                
  1818.                 //Handle the original schema that was added to lockList before cloning occurred
  1819.                 schema.IsProcessing = false;
  1820.                 //Since we cloned it for the chameleon
  1821.             }
  1822.             return chameleonSchema;
  1823.         }
  1824.        
  1825.         private void SetParent(XmlSchemaObject child, XmlSchemaObject parent)
  1826.         {
  1827.             child.Parent = parent;
  1828.         }
  1829.        
  1830.         private void PreprocessAnnotation(XmlSchemaObject schemaObject)
  1831.         {
  1832.             XmlSchemaAnnotation annotation;
  1833.             if (schemaObject is XmlSchemaAnnotated) {
  1834.                 XmlSchemaAnnotated annotated = schemaObject as XmlSchemaAnnotated;
  1835.                 annotation = annotated.Annotation;
  1836.                 if (annotation != null) {
  1837.                     PreprocessAnnotation(annotation);
  1838.                     annotation.Parent = schemaObject;
  1839.                 }
  1840.             }
  1841.         }
  1842.        
  1843.         private void PreprocessAnnotation(XmlSchemaAnnotation annotation)
  1844.         {
  1845.             ValidateIdAttribute(annotation);
  1846.             foreach (XmlSchemaObject obj in annotation.Items) {
  1847.                 obj.Parent = annotation;
  1848.                 //Can be documentation or appInfo
  1849.             }
  1850.         }
  1851.     }
  1852.    
  1853. }
  1854. // namespace System.Xml

Developer Fusion