The Labs \ Source Viewer \ SSCLI \ System.Xml.Serialization \ XmlSchemas

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlSchemas.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">ElenaK</owner>
  15. //------------------------------------------------------------------------------
  16. namespace System.Xml.Serialization
  17. {
  18.    
  19.     using System.Collections;
  20.     using System.Collections.Generic;
  21.     using System.IO;
  22.     using System;
  23.     using System.Globalization;
  24.     using System.ComponentModel;
  25.     using System.Xml.Serialization;
  26.     using System.Xml.Schema;
  27.     using System.Diagnostics;
  28.     using System.Threading;
  29.     using System.Security.Permissions;
  30.     using System.Security.Policy;
  31.     using System.Security;
  32.     using System.Net;
  33.    
  34.     /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas"]/*' />
  35.     /// <internalonly/>
  36.     /// <devdoc>
  37.     /// <para>[To be supplied.]</para>
  38.     /// </devdoc>
  39.     public class XmlSchemas : CollectionBase, IEnumerable<XmlSchema>
  40.     {
  41.         XmlSchemaSet schemaSet;
  42.         Hashtable references;
  43.         SchemaObjectCache cache;
  44.         // cached schema top-level items
  45.         bool shareTypes;
  46.         Hashtable mergedSchemas;
  47.         internal Hashtable delayedSchemas = new Hashtable();
  48.         bool isCompiled = false;
  49.         static XmlSchema xsd;
  50.         static XmlSchema xml;
  51.        
  52.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.this"]/*' />
  53.         /// <devdoc>
  54.         /// <para>[To be supplied.]</para>
  55.         /// </devdoc>
  56.         public XmlSchema this[int index]
  57.         {
  58.             get { return (XmlSchema)List[index]; }
  59.             set { List[index] = value; }
  60.         }
  61.        
  62.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.this1"]/*' />
  63.         /// <devdoc>
  64.         /// <para>[To be supplied.]</para>
  65.         /// </devdoc>
  66.         public XmlSchema this[string ns]
  67.         {
  68.             get {
  69.                 IList values = (IList)SchemaSet.Schemas(ns);
  70.                 if (values.Count == 0)
  71.                     return null;
  72.                 if (values.Count == 1)
  73.                     return (XmlSchema)values[0];
  74.                
  75.                 throw new InvalidOperationException(Res.GetString(Res.XmlSchemaDuplicateNamespace, ns));
  76.             }
  77.         }
  78.        
  79.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.GetSchemas"]/*' />
  80.         /// <devdoc>
  81.         /// <para>[To be supplied.]</para>
  82.         /// </devdoc>
  83.         public IList GetSchemas(string ns)
  84.         {
  85.             return (IList)SchemaSet.Schemas(ns);
  86.         }
  87.        
  88.         internal SchemaObjectCache Cache {
  89.             get {
  90.                 if (cache == null)
  91.                     cache = new SchemaObjectCache();
  92.                 return cache;
  93.             }
  94.         }
  95.        
  96.         internal Hashtable MergedSchemas {
  97.             get {
  98.                 if (mergedSchemas == null)
  99.                     mergedSchemas = new Hashtable();
  100.                 return mergedSchemas;
  101.             }
  102.         }
  103.        
  104.         internal Hashtable References {
  105.             get {
  106.                 if (references == null)
  107.                     references = new Hashtable();
  108.                 return references;
  109.             }
  110.         }
  111.        
  112.         internal XmlSchemaSet SchemaSet {
  113.             get {
  114.                 if (schemaSet == null) {
  115.                     schemaSet = new XmlSchemaSet();
  116.                     schemaSet.XmlResolver = null;
  117.                     schemaSet.ValidationEventHandler += new ValidationEventHandler(IgnoreCompileErrors);
  118.                 }
  119.                 return schemaSet;
  120.             }
  121.         }
  122.         internal int Add(XmlSchema schema, bool delay)
  123.         {
  124.             if (delay) {
  125.                 if (delayedSchemas[schema] == null)
  126.                     delayedSchemas.Add(schema, schema);
  127.                 return -1;
  128.             }
  129.             else {
  130.                 return Add(schema);
  131.             }
  132.         }
  133.        
  134.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.Add"]/*' />
  135.         /// <devdoc>
  136.         /// <para>[To be supplied.]</para>
  137.         /// </devdoc>
  138.         public int Add(XmlSchema schema)
  139.         {
  140.             if (List.Contains(schema))
  141.                 return List.IndexOf(schema);
  142.             return List.Add(schema);
  143.         }
  144.        
  145.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.Add"]/*' />
  146.         /// <devdoc>
  147.         /// <para>[To be supplied.]</para>
  148.         /// </devdoc>
  149.         public int Add(XmlSchema schema, Uri baseUri)
  150.         {
  151.             if (List.Contains(schema))
  152.                 return List.IndexOf(schema);
  153.             if (baseUri != null)
  154.                 schema.BaseUri = baseUri;
  155.             return List.Add(schema);
  156.         }
  157.        
  158.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.Add1"]/*' />
  159.         /// <devdoc>
  160.         /// <para>[To be supplied.]</para>
  161.         /// </devdoc>
  162.         public void Add(XmlSchemas schemas)
  163.         {
  164.             foreach (XmlSchema schema in schemas) {
  165.                 Add(schema);
  166.             }
  167.         }
  168.        
  169.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.AddReference"]/*' />
  170.         /// <devdoc>
  171.         /// <para>[To be supplied.]</para>
  172.         /// </devdoc>
  173.         public void AddReference(XmlSchema schema)
  174.         {
  175.             References[schema] = schema;
  176.         }
  177.        
  178.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.Insert"]/*' />
  179.         /// <devdoc>
  180.         /// <para>[To be supplied.]</para>
  181.         /// </devdoc>
  182.         public void Insert(int index, XmlSchema schema)
  183.         {
  184.             List.Insert(index, schema);
  185.         }
  186.        
  187.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.IndexOf"]/*' />
  188.         /// <devdoc>
  189.         /// <para>[To be supplied.]</para>
  190.         /// </devdoc>
  191.         public int IndexOf(XmlSchema schema)
  192.         {
  193.             return List.IndexOf(schema);
  194.         }
  195.        
  196.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.Contains"]/*' />
  197.         /// <devdoc>
  198.         /// <para>[To be supplied.]</para>
  199.         /// </devdoc>
  200.         public bool Contains(XmlSchema schema)
  201.         {
  202.             return List.Contains(schema);
  203.         }
  204.        
  205.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.Contains1"]/*' />
  206.         /// <devdoc>
  207.         /// <para>[To be supplied.]</para>
  208.         /// </devdoc>
  209.         public bool Contains(string targetNamespace)
  210.         {
  211.             return SchemaSet.Contains(targetNamespace);
  212.         }
  213.        
  214.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.Remove"]/*' />
  215.         /// <devdoc>
  216.         /// <para>[To be supplied.]</para>
  217.         /// </devdoc>
  218.         public void Remove(XmlSchema schema)
  219.         {
  220.             List.Remove(schema);
  221.         }
  222.        
  223.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.CopyTo"]/*' />
  224.         /// <devdoc>
  225.         /// <para>[To be supplied.]</para>
  226.         /// </devdoc>
  227.         public void CopyTo(XmlSchema[] array, int index)
  228.         {
  229.             List.CopyTo(array, index);
  230.         }
  231.        
  232.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.OnInsert"]/*' />
  233.         /// <devdoc>
  234.         /// <para>[To be supplied.]</para>
  235.         /// </devdoc>
  236.         protected override void OnInsert(int index, object value)
  237.         {
  238.             AddName((XmlSchema)value);
  239.         }
  240.        
  241.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.OnRemove"]/*' />
  242.         /// <devdoc>
  243.         /// <para>[To be supplied.]</para>
  244.         /// </devdoc>
  245.         protected override void OnRemove(int index, object value)
  246.         {
  247.             RemoveName((XmlSchema)value);
  248.         }
  249.        
  250.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.OnClear"]/*' />
  251.         /// <devdoc>
  252.         /// <para>[To be supplied.]</para>
  253.         /// </devdoc>
  254.         protected override void OnClear()
  255.         {
  256.             schemaSet = null;
  257.         }
  258.        
  259.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.OnSet"]/*' />
  260.         /// <devdoc>
  261.         /// <para>[To be supplied.]</para>
  262.         /// </devdoc>
  263.         protected override void OnSet(int index, object oldValue, object newValue)
  264.         {
  265.             RemoveName((XmlSchema)oldValue);
  266.             AddName((XmlSchema)newValue);
  267.         }
  268.        
  269.         void AddName(XmlSchema schema)
  270.         {
  271.             if (isCompiled)
  272.                 throw new InvalidOperationException(Res.GetString(Res.XmlSchemaCompiled));
  273.             if (SchemaSet.Contains(schema))
  274.                 SchemaSet.Reprocess(schema);
  275.             else {
  276.                 Prepare(schema);
  277.                 SchemaSet.Add(schema);
  278.             }
  279.         }
  280.        
  281.         void Prepare(XmlSchema schema)
  282.         {
  283.             // need to remove illegal <import> externals;
  284.             ArrayList removes = new ArrayList();
  285.             string ns = schema.TargetNamespace;
  286.             foreach (XmlSchemaExternal external in schema.Includes) {
  287.                 if (external is XmlSchemaImport) {
  288.                     if (ns == ((XmlSchemaImport)external).Namespace) {
  289.                         removes.Add(external);
  290.                     }
  291.                 }
  292.             }
  293.             foreach (XmlSchemaObject o in removes) {
  294.                 schema.Includes.Remove(o);
  295.             }
  296.         }
  297.        
  298.         void RemoveName(XmlSchema schema)
  299.         {
  300.             SchemaSet.Remove(schema);
  301.         }
  302.        
  303.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.Find"]/*' />
  304.         /// <devdoc>
  305.         /// <para>[To be supplied.]</para>
  306.         /// </devdoc>
  307.         public object Find(XmlQualifiedName name, Type type)
  308.         {
  309.             return Find(name, type, true);
  310.         }
  311.         internal object Find(XmlQualifiedName name, Type type, bool checkCache)
  312.         {
  313.             if (!IsCompiled) {
  314.                 foreach (XmlSchema schema in List) {
  315.                     Preprocess(schema);
  316.                 }
  317.             }
  318.             IList values = (IList)SchemaSet.Schemas(name.Namespace);
  319.             if (values == null)
  320.                 return null;
  321.            
  322.             foreach (XmlSchema schema in values) {
  323.                 Preprocess(schema);
  324.                
  325.                 XmlSchemaObject ret = null;
  326.                 if (typeof(XmlSchemaType).IsAssignableFrom(type)) {
  327.                     ret = schema.SchemaTypes[name];
  328.                     if (ret == null || !type.IsAssignableFrom(ret.GetType())) {
  329.                         continue;
  330.                     }
  331.                 }
  332.                 else if (type == typeof(XmlSchemaGroup)) {
  333.                     ret = schema.Groups[name];
  334.                 }
  335.                 else if (type == typeof(XmlSchemaAttributeGroup)) {
  336.                     ret = schema.AttributeGroups[name];
  337.                 }
  338.                 else if (type == typeof(XmlSchemaElement)) {
  339.                     ret = schema.Elements[name];
  340.                 }
  341.                 else if (type == typeof(XmlSchemaAttribute)) {
  342.                     ret = schema.Attributes[name];
  343.                 }
  344.                 else if (type == typeof(XmlSchemaNotation)) {
  345.                     ret = schema.Notations[name];
  346.                 }
  347.                 #if DEBUG
  348.                 else {
  349.                     // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
  350.                     throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "XmlSchemas.Find: Invalid object type " + type.FullName));
  351.                 }
  352.                 #endif
  353.                
  354.                 if (ret != null && shareTypes && checkCache && !IsReference(ret))
  355.                     ret = Cache.AddItem(ret, name, this);
  356.                 if (ret != null) {
  357.                     return ret;
  358.                 }
  359.             }
  360.             return null;
  361.         }
  362.        
  363.         IEnumerator<XmlSchema> IEnumerable<XmlSchema>.GetEnumerator()
  364.         {
  365.             return new XmlSchemaEnumerator(this);
  366.         }
  367.        
  368.         static internal void Preprocess(XmlSchema schema)
  369.         {
  370.             if (!schema.IsPreprocessed) {
  371.                 try {
  372.                     XmlNameTable nameTable = new System.Xml.NameTable();
  373.                     Preprocessor prep = new Preprocessor(nameTable, new SchemaNames(nameTable), null);
  374.                     prep.SchemaLocations = new Hashtable();
  375.                     prep.Execute(schema, schema.TargetNamespace, false);
  376.                 }
  377.                 catch (XmlSchemaException e) {
  378.                     throw CreateValidationException(e, e.Message);
  379.                 }
  380.             }
  381.         }
  382.        
  383.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.IsDataSet"]/*' />
  384.         /// <devdoc>
  385.         /// <para>[To be supplied.]</para>
  386.         /// </devdoc>
  387.         public static bool IsDataSet(XmlSchema schema)
  388.         {
  389.             foreach (XmlSchemaObject o in schema.Items) {
  390.                 if (o is XmlSchemaElement) {
  391.                     XmlSchemaElement e = (XmlSchemaElement)o;
  392.                     if (e.UnhandledAttributes != null) {
  393.                         foreach (XmlAttribute a in e.UnhandledAttributes) {
  394.                             if (a.LocalName == "IsDataSet" && a.NamespaceURI == "urn:schemas-microsoft-com:xml-msdata") {
  395.                                 // currently the msdata:IsDataSet uses its own format for the boolean values
  396.                                 if (a.Value == "True" || a.Value == "true" || a.Value == "1")
  397.                                     return true;
  398.                             }
  399.                         }
  400.                     }
  401.                 }
  402.             }
  403.             return false;
  404.         }
  405.        
  406.         void Merge(XmlSchema schema)
  407.         {
  408.             if (MergedSchemas[schema] != null)
  409.                 return;
  410.             IList originals = (IList)SchemaSet.Schemas(schema.TargetNamespace);
  411.             if (originals != null && originals.Count > 0) {
  412.                 MergedSchemas.Add(schema, schema);
  413.                 Merge(originals, schema);
  414.             }
  415.             else {
  416.                 Add(schema);
  417.                 MergedSchemas.Add(schema, schema);
  418.             }
  419.         }
  420.        
  421.         void AddImport(IList schemas, string ns)
  422.         {
  423.             foreach (XmlSchema s in schemas) {
  424.                 bool add = true;
  425.                 foreach (XmlSchemaExternal external in s.Includes) {
  426.                     if (external is XmlSchemaImport && ((XmlSchemaImport)external).Namespace == ns) {
  427.                         add = false;
  428.                         break;
  429.                     }
  430.                 }
  431.                 if (add) {
  432.                     XmlSchemaImport import = new XmlSchemaImport();
  433.                     import.Namespace = ns;
  434.                     s.Includes.Add(import);
  435.                 }
  436.             }
  437.         }
  438.        
  439.         void Merge(IList originals, XmlSchema schema)
  440.         {
  441.             foreach (XmlSchema s in originals) {
  442.                 if (schema == s) {
  443.                     return;
  444.                 }
  445.             }
  446.            
  447.             foreach (XmlSchemaExternal external in schema.Includes) {
  448.                 if (external is XmlSchemaImport) {
  449.                     external.SchemaLocation = null;
  450.                     if (external.Schema != null) {
  451.                         Merge(external.Schema);
  452.                     }
  453.                     else {
  454.                         AddImport(originals, ((XmlSchemaImport)external).Namespace);
  455.                     }
  456.                 }
  457.                 else {
  458.                     if (external.Schema == null) {
  459.                         // we do not process includes or redefines by the schemaLocation
  460.                         if (external.SchemaLocation != null) {
  461.                             throw new InvalidOperationException(Res.GetString(Res.XmlSchemaIncludeLocation, this.GetType().Name, external.SchemaLocation));
  462.                         }
  463.                     }
  464.                     else {
  465.                         external.SchemaLocation = null;
  466.                         Merge(originals, external.Schema);
  467.                     }
  468.                 }
  469.             }
  470.            
  471.             // bring all included items to the parent schema;
  472.             bool[] matchedItems = new bool[schema.Items.Count];
  473.             int count = 0;
  474.             for (int i = 0; i < schema.Items.Count; i++) {
  475.                 XmlSchemaObject o = schema.Items[i];
  476.                 XmlSchemaObject dest = Find(o, originals);
  477.                 if (dest != null) {
  478.                     if (!Cache.Match(dest, o, shareTypes)) {
  479.                         Debug.WriteLineIf(DiagnosticsSwitches.XmlSerialization.TraceVerbose, "XmlSerialization::Failed to Merge " + MergeFailedMessage(o, dest, schema.TargetNamespace) + "' Plase Compare hash:\r\n" + Cache.looks[dest] + "\r\n" + Cache.looks[o]);
  480.                         throw new InvalidOperationException(MergeFailedMessage(o, dest, schema.TargetNamespace));
  481.                     }
  482.                     matchedItems[i] = true;
  483.                     count++;
  484.                 }
  485.             }
  486.             if (count != schema.Items.Count) {
  487.                 XmlSchema destination = (XmlSchema)originals[0];
  488.                 for (int i = 0; i < schema.Items.Count; i++) {
  489.                     if (!matchedItems[i]) {
  490.                         destination.Items.Add(schema.Items[i]);
  491.                     }
  492.                 }
  493.                 destination.IsPreprocessed = false;
  494.                 Preprocess(destination);
  495.             }
  496.         }
  497.        
  498.         static string ItemName(XmlSchemaObject o)
  499.         {
  500.             if (o is XmlSchemaNotation) {
  501.                 return ((XmlSchemaNotation)o).Name;
  502.             }
  503.             else if (o is XmlSchemaGroup) {
  504.                 return ((XmlSchemaGroup)o).Name;
  505.             }
  506.             else if (o is XmlSchemaElement) {
  507.                 return ((XmlSchemaElement)o).Name;
  508.             }
  509.             else if (o is XmlSchemaType) {
  510.                 return ((XmlSchemaType)o).Name;
  511.             }
  512.             else if (o is XmlSchemaAttributeGroup) {
  513.                 return ((XmlSchemaAttributeGroup)o).Name;
  514.             }
  515.             else if (o is XmlSchemaAttribute) {
  516.                 return ((XmlSchemaAttribute)o).Name;
  517.             }
  518.             return null;
  519.         }
  520.        
  521.         static internal XmlQualifiedName GetParentName(XmlSchemaObject item)
  522.         {
  523.             while (item.Parent != null) {
  524.                 if (item.Parent is XmlSchemaType) {
  525.                     XmlSchemaType type = (XmlSchemaType)item.Parent;
  526.                     if (type.Name != null && type.Name.Length != 0) {
  527.                         return type.QualifiedName;
  528.                     }
  529.                 }
  530.                 item = item.Parent;
  531.             }
  532.             return XmlQualifiedName.Empty;
  533.         }
  534.        
  535.         static string GetSchemaItem(XmlSchemaObject o, string ns, string details)
  536.         {
  537.             if (o == null) {
  538.                 return null;
  539.             }
  540.             while (o.Parent != null && !(o.Parent is XmlSchema)) {
  541.                 o = o.Parent;
  542.             }
  543.             if (ns == null || ns.Length == 0) {
  544.                 XmlSchemaObject tmp = o;
  545.                 while (tmp.Parent != null) {
  546.                     tmp = tmp.Parent;
  547.                 }
  548.                 if (tmp is XmlSchema) {
  549.                     ns = ((XmlSchema)tmp).TargetNamespace;
  550.                 }
  551.             }
  552.             string item = null;
  553.             if (o is XmlSchemaNotation) {
  554.                 item = Res.GetString(Res.XmlSchemaNamedItem, ns, "notation", ((XmlSchemaNotation)o).Name, details);
  555.             }
  556.             else if (o is XmlSchemaGroup) {
  557.                 item = Res.GetString(Res.XmlSchemaNamedItem, ns, "group", ((XmlSchemaGroup)o).Name, details);
  558.             }
  559.             else if (o is XmlSchemaElement) {
  560.                 XmlSchemaElement e = ((XmlSchemaElement)o);
  561.                 if (e.Name == null || e.Name.Length == 0) {
  562.                     XmlQualifiedName parentName = XmlSchemas.GetParentName(o);
  563.                     // Element reference '{0}' declared in schema type '{1}' from namespace '{2}'
  564.                     item = Res.GetString(Res.XmlSchemaElementReference, e.RefName.ToString(), parentName.Name, parentName.Namespace);
  565.                 }
  566.                 else {
  567.                     item = Res.GetString(Res.XmlSchemaNamedItem, ns, "element", e.Name, details);
  568.                 }
  569.             }
  570.             else if (o is XmlSchemaType) {
  571.                 item = Res.GetString(Res.XmlSchemaNamedItem, ns, o.GetType() == typeof(XmlSchemaSimpleType) ? "simpleType" : "complexType", ((XmlSchemaType)o).Name, null);
  572.             }
  573.             else if (o is XmlSchemaAttributeGroup) {
  574.                 item = Res.GetString(Res.XmlSchemaNamedItem, ns, "attributeGroup", ((XmlSchemaAttributeGroup)o).Name, details);
  575.             }
  576.             else if (o is XmlSchemaAttribute) {
  577.                 XmlSchemaAttribute a = ((XmlSchemaAttribute)o);
  578.                 if (a.Name == null || a.Name.Length == 0) {
  579.                     XmlQualifiedName parentName = XmlSchemas.GetParentName(o);
  580.                     // Attribure reference '{0}' declared in schema type '{1}' from namespace '{2}'
  581.                     return Res.GetString(Res.XmlSchemaAttributeReference, a.RefName.ToString(), parentName.Name, parentName.Namespace);
  582.                 }
  583.                 else {
  584.                     item = Res.GetString(Res.XmlSchemaNamedItem, ns, "attribute", a.Name, details);
  585.                 }
  586.                
  587.             }
  588.             else if (o is XmlSchemaContent) {
  589.                 XmlQualifiedName parentName = XmlSchemas.GetParentName(o);
  590.                 // Check content definition of schema type '{0}' from namespace '{1}'. {2}
  591.                 item = Res.GetString(Res.XmlSchemaContentDef, parentName.Name, parentName.Namespace, null);
  592.             }
  593.             else if (o is XmlSchemaExternal) {
  594.                 string itemType = o is XmlSchemaImport ? "import" : o is XmlSchemaInclude ? "include" : o is XmlSchemaRedefine ? "redefine" : o.GetType().Name;
  595.                 item = Res.GetString(Res.XmlSchemaItem, ns, itemType, details);
  596.             }
  597.             else if (o is XmlSchema) {
  598.                 item = Res.GetString(Res.XmlSchema, ns, details);
  599.             }
  600.             else {
  601.                 item = Res.GetString(Res.XmlSchemaNamedItem, ns, o.GetType().Name, null, details);
  602.             }
  603.            
  604.             return item;
  605.         }
  606.        
  607.         static string Dump(XmlSchemaObject o)
  608.         {
  609.             XmlWriterSettings settings = new XmlWriterSettings();
  610.             settings.OmitXmlDeclaration = true;
  611.             settings.Indent = true;
  612.             XmlSerializer s = new XmlSerializer(o.GetType());
  613.             StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
  614.             XmlWriter xmlWriter = XmlWriter.Create(sw, settings);
  615.             XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
  616.             ns.Add("xs", XmlSchema.Namespace);
  617.             s.Serialize(xmlWriter, o, ns);
  618.             return sw.ToString();
  619.         }
  620.         static string MergeFailedMessage(XmlSchemaObject src, XmlSchemaObject dest, string ns)
  621.         {
  622.             string err = Res.GetString(Res.XmlSerializableMergeItem, ns, GetSchemaItem(src, ns, null));
  623.             err += "\r\n" + Dump(src);
  624.             err += "\r\n" + Dump(dest);
  625.             return err;
  626.         }
  627.        
  628.         internal XmlSchemaObject Find(XmlSchemaObject o, IList originals)
  629.         {
  630.             string name = ItemName(o);
  631.             if (name == null)
  632.                 return null;
  633.            
  634.             Type type = o.GetType();
  635.            
  636.             foreach (XmlSchema s in originals) {
  637.                 foreach (XmlSchemaObject item in s.Items) {
  638.                     if (item.GetType() == type && name == ItemName(item)) {
  639.                         return item;
  640.                     }
  641.                 }
  642.             }
  643.             return null;
  644.         }
  645.        
  646.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.IsCompiled"]/*' />
  647.         public bool IsCompiled {
  648.             get { return isCompiled; }
  649.         }
  650.        
  651.         /// <include file='doc\XmlSchemas.uex' path='docs/doc[@for="XmlSchemas.Compile"]/*' />
  652.         public void Compile(ValidationEventHandler handler, bool fullCompile)
  653.         {
  654.             if (isCompiled)
  655.                 return;
  656.            
  657.             foreach (XmlSchema s in delayedSchemas.Values)
  658.                 Merge(s);
  659.             delayedSchemas.Clear();
  660.            
  661.             if (fullCompile) {
  662.                 schemaSet = new XmlSchemaSet();
  663.                 schemaSet.XmlResolver = null;
  664.                 schemaSet.ValidationEventHandler += handler;
  665.                
  666.                 foreach (XmlSchema s in References.Values)
  667.                     schemaSet.Add(s);
  668.                 int schemaCount = schemaSet.Count;
  669.                
  670.                 foreach (XmlSchema s in List) {
  671.                     if (!SchemaSet.Contains(s)) {
  672.                         schemaSet.Add(s);
  673.                         schemaCount++;
  674.                     }
  675.                 }
  676.                
  677.                 if (!SchemaSet.Contains(XmlSchema.Namespace)) {
  678.                     AddReference(XsdSchema);
  679.                     schemaSet.Add(XsdSchema);
  680.                     schemaCount++;
  681.                 }
  682.                
  683.                 if (!SchemaSet.Contains(XmlReservedNs.NsXml)) {
  684.                     AddReference(XmlSchema);
  685.                     schemaSet.Add(XmlSchema);
  686.                     schemaCount++;
  687.                 }
  688.                 schemaSet.Compile();
  689.                 schemaSet.ValidationEventHandler -= handler;
  690.                 isCompiled = schemaSet.IsCompiled && schemaCount == schemaSet.Count;
  691.             }
  692.             else {
  693.                 try {
  694.                     XmlNameTable nameTable = new System.Xml.NameTable();
  695.                     Preprocessor prep = new Preprocessor(nameTable, new SchemaNames(nameTable), null);
  696.                     prep.XmlResolver = null;
  697.                     prep.SchemaLocations = new Hashtable();
  698.                     prep.ChameleonSchemas = new Hashtable();
  699.                     foreach (XmlSchema schema in SchemaSet.Schemas()) {
  700.                         prep.Execute(schema, schema.TargetNamespace, true);
  701.                     }
  702.                 }
  703.                 catch (XmlSchemaException e) {
  704.                     throw CreateValidationException(e, e.Message);
  705.                 }
  706.             }
  707.         }
  708.        
  709.         static internal Exception CreateValidationException(XmlSchemaException exception, string message)
  710.         {
  711.             XmlSchemaObject source = exception.SourceSchemaObject;
  712.             if (exception.LineNumber == 0 && exception.LinePosition == 0) {
  713.                 throw new InvalidOperationException(GetSchemaItem(source, null, message), exception);
  714.             }
  715.             else {
  716.                 string ns = null;
  717.                 if (source != null) {
  718.                     while (source.Parent != null) {
  719.                         source = source.Parent;
  720.                     }
  721.                     if (source is XmlSchema) {
  722.                         ns = ((XmlSchema)source).TargetNamespace;
  723.                     }
  724.                 }
  725.                 throw new InvalidOperationException(Res.GetString(Res.XmlSchemaSyntaxErrorDetails, ns, message, exception.LineNumber, exception.LinePosition), exception);
  726.             }
  727.         }
  728.        
  729.         static internal void IgnoreCompileErrors(object sender, ValidationEventArgs args)
  730.         {
  731.             return;
  732.         }
  733.        
  734.         static internal XmlSchema XsdSchema {
  735.             get {
  736.                 if (xsd == null) {
  737.                     xsd = CreateFakeXsdSchema(XmlSchema.Namespace, "schema");
  738.                 }
  739.                 return xsd;
  740.             }
  741.         }
  742.        
  743.         static internal XmlSchema XmlSchema {
  744.             get {
  745.                 if (xml == null) {
  746.                     xml = XmlSchema.Read(new StringReader(xmlSchema), null);
  747.                 }
  748.                 return xml;
  749.             }
  750.         }
  751.        
  752.         private static XmlSchema CreateFakeXsdSchema(string ns, string name)
  753.         {
  754.             /* Create fake xsd schema to fool the XmlSchema.Compiler
  755.                 <xsd:schema targetNamespace="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  756.                   <xsd:element name="schema">
  757.                     <xsd:complexType />
  758.                   </xsd:element>
  759.                 </xsd:schema>
  760.             */           
  761. XmlSchema schema = new XmlSchema();
  762.             schema.TargetNamespace = ns;
  763.             XmlSchemaElement element = new XmlSchemaElement();
  764.             element.Name = name;
  765.             XmlSchemaComplexType type = new XmlSchemaComplexType();
  766.             element.SchemaType = type;
  767.             schema.Items.Add(element);
  768.             return schema;
  769.         }
  770.        
  771.         internal void SetCache(SchemaObjectCache cache, bool shareTypes)
  772.         {
  773.             this.shareTypes = shareTypes;
  774.             this.cache = cache;
  775.             if (shareTypes) {
  776.                 cache.GenerateSchemaGraph(this);
  777.             }
  778.         }
  779.        
  780.         internal bool IsReference(XmlSchemaObject type)
  781.         {
  782.             XmlSchemaObject parent = type;
  783.             while (parent.Parent != null) {
  784.                 parent = parent.Parent;
  785.             }
  786.             return References.Contains(parent);
  787.         }
  788.        
  789.         internal const string xmlSchema = "<?xml version='1.0' encoding='UTF-8' ?> \r\n<xs:schema targetNamespace='http://www.w3.org/XML/1998/namespace' xmlns:xs='http://www.w3.org/2001/XMLSchema' xml:lang='en'>\r\n <xs:attribute name='lang' type='xs:language'/>\r\n <xs:attribute name='space'>\r\n <xs:simpleType>\r\n <xs:restriction base='xs:NCName'>\r\n <xs:enumeration value='default'/>\r\n <xs:enumeration value='preserve'/>\r\n </xs:restriction>\r\n </xs:simpleType>\r\n </xs:attribute>\r\n <xs:attribute name='base' type='xs:anyURI'/>\r\n <xs:attribute name='id' type='xs:ID' />\r\n <xs:attributeGroup name='specialAttrs'>\r\n <xs:attribute ref='xml:base'/>\r\n <xs:attribute ref='xml:lang'/>\r\n <xs:attribute ref='xml:space'/>\r\n </xs:attributeGroup>\r\n</xs:schema>";
  790.     }
  791.    
  792.     public class XmlSchemaEnumerator : IEnumerator<XmlSchema>, System.Collections.IEnumerator
  793.     {
  794.         private XmlSchemas list;
  795.         private int idx, end;
  796.        
  797.         public XmlSchemaEnumerator(XmlSchemas list)
  798.         {
  799.             this.list = list;
  800.             this.idx = -1;
  801.             this.end = list.Count - 1;
  802.         }
  803.        
  804.         public void Dispose()
  805.         {
  806.         }
  807.        
  808.         public bool MoveNext()
  809.         {
  810.             if (this.idx >= this.end)
  811.                 return false;
  812.            
  813.             this.idx++;
  814.             return true;
  815.         }
  816.        
  817.         public XmlSchema Current {
  818.             get { return this.list[this.idx]; }
  819.         }
  820.        
  821.         object System.Collections.IEnumerator.Current {
  822.             get { return this.list[this.idx]; }
  823.         }
  824.        
  825.         void System.Collections.IEnumerator.Reset()
  826.         {
  827.             this.idx = -1;
  828.         }
  829.     }
  830. }

Developer Fusion