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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlSchemaCollection.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;
  20.     using System.Threading;
  21.     using System.Collections;
  22.     using System.Xml.Schema;
  23.    
  24.    
  25.     /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection"]/*' />
  26.     /// <devdoc>
  27.     /// <para>The XmlSchemaCollection contains a set of namespace URI's.
  28.     /// Each namespace also have an associated private data cache
  29.     /// corresponding to the XML-Data Schema or W3C XML Schema.
  30.     /// The XmlSchemaCollection will able to load XSD and XDR schemas,
  31.     /// and compile them into an internal "cooked schema representation".
  32.     /// The Validate method then uses this internal representation for
  33.     /// efficient runtime validation of any given subtree.</para>
  34.     /// </devdoc>
  35.     [Obsolete("Use System.Xml.Schema.XmlSchemaSet for schema compilation and validation. http://go.microsoft.com/fwlink/?linkid=14202")]
  36.     public sealed class XmlSchemaCollection : ICollection
  37.     {
  38.         private Hashtable collection;
  39.         private XmlNameTable nameTable;
  40.         private SchemaNames schemaNames;
  41.         private ReaderWriterLock wLock;
  42.         private int timeout = Timeout.Infinite;
  43.         private bool isThreadSafe = true;
  44.         private ValidationEventHandler validationEventHandler = null;
  45.         private XmlResolver xmlResolver = null;
  46.        
  47.        
  48.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.XmlSchemaCollection"]/*' />
  49.         /// <devdoc>
  50.         /// <para>Construct a new empty schema collection.</para>
  51.         /// </devdoc>
  52.         public XmlSchemaCollection() : this(new NameTable())
  53.         {
  54.         }
  55.        
  56.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.XmlSchemaCollection1"]/*' />
  57.         /// <devdoc>
  58.         /// <para>Construct a new empty schema collection with associated XmlNameTable.
  59.         /// The XmlNameTable is used when loading schemas</para>
  60.         /// </devdoc>
  61.         public XmlSchemaCollection(XmlNameTable nametable)
  62.         {
  63.             if (nametable == null) {
  64.                 throw new ArgumentNullException("nametable");
  65.             }
  66.             nameTable = nametable;
  67.             collection = Hashtable.Synchronized(new Hashtable());
  68.             xmlResolver = new XmlUrlResolver();
  69.             isThreadSafe = true;
  70.             if (isThreadSafe) {
  71.                 wLock = new ReaderWriterLock();
  72.             }
  73.         }
  74.        
  75.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.Count"]/*' />
  76.         /// <devdoc>
  77.         /// <para>Returns the number of namespaces defined in this collection
  78.         /// (whether or not there is an actual schema associated with those namespaces or not).</para>
  79.         /// </devdoc>
  80.         public int Count {
  81.             get { return collection.Count; }
  82.         }
  83.        
  84.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.NameTable"]/*' />
  85.         /// <devdoc>
  86.         /// <para>The default XmlNameTable used by the XmlSchemaCollection when loading new schemas.</para>
  87.         /// </devdoc>
  88.         public XmlNameTable NameTable {
  89.             get { return nameTable; }
  90.         }
  91.        
  92.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.ValidationEventHandler"]/*' />
  93.         public event ValidationEventHandler ValidationEventHandler {
  94.             add { validationEventHandler += value; }
  95.             remove { validationEventHandler -= value; }
  96.         }
  97.        
  98.         internal XmlResolver XmlResolver {
  99.             set { xmlResolver = value; }
  100.         }
  101.        
  102.        
  103.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.Add"]/*' />
  104.         /// <devdoc>
  105.         /// <para>Add the schema located by the given URL into the schema collection.
  106.         /// If the given schema references other namespaces, the schemas for those other
  107.         /// namespaces are NOT automatically loaded.</para>
  108.         /// </devdoc>
  109.         public XmlSchema Add(string ns, string uri)
  110.         {
  111.             if (uri == null || uri.Length == 0)
  112.                 throw new ArgumentNullException("uri");
  113.             XmlTextReader reader = new XmlTextReader(uri, nameTable);
  114.             reader.XmlResolver = xmlResolver;
  115.            
  116.             XmlSchema schema = null;
  117.             try {
  118.                 schema = Add(ns, reader, xmlResolver);
  119.                 while (reader.Read())
  120.                     ;
  121.                 // wellformness check
  122.             }
  123.             finally {
  124.                 reader.Close();
  125.             }
  126.             return schema;
  127.         }
  128.        
  129.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.Add4"]/*' />
  130.         public XmlSchema Add(string ns, XmlReader reader)
  131.         {
  132.             return Add(ns, reader, xmlResolver);
  133.         }
  134.        
  135.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.Add1"]/*' />
  136.         /// <devdoc>
  137.         /// <para>Add the given schema into the schema collection.
  138.         /// If the given schema references other namespaces, the schemas for those
  139.         /// other namespaces are NOT automatically loaded.</para>
  140.         /// </devdoc>
  141.         public XmlSchema Add(string ns, XmlReader reader, XmlResolver resolver)
  142.         {
  143.             if (reader == null)
  144.                 throw new ArgumentNullException("reader");
  145.             XmlNameTable readerNameTable = reader.NameTable;
  146.             SchemaInfo schemaInfo = new SchemaInfo();
  147.            
  148.             Parser parser = new Parser(SchemaType.None, readerNameTable, GetSchemaNames(readerNameTable), validationEventHandler);
  149.             parser.XmlResolver = resolver;
  150.             SchemaType schemaType;
  151.             try {
  152.                 schemaType = parser.Parse(reader, ns);
  153.             }
  154.             catch (XmlSchemaException e) {
  155.                 SendValidationEvent(e);
  156.                 return null;
  157.             }
  158.            
  159.             if (schemaType == SchemaType.XSD) {
  160.                 schemaInfo.SchemaType = SchemaType.XSD;
  161.                 return Add(ns, schemaInfo, parser.XmlSchema, true, resolver);
  162.             }
  163.             else {
  164.                 SchemaInfo xdrSchema = parser.XdrSchema;
  165.                 return Add(ns, parser.XdrSchema, null, true, resolver);
  166.             }
  167.         }
  168.        
  169.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.Add2"]/*' />
  170.         /// <devdoc>
  171.         /// <para>[To be supplied.]</para>
  172.         /// </devdoc>
  173.         public XmlSchema Add(XmlSchema schema)
  174.         {
  175.             return Add(schema, xmlResolver);
  176.         }
  177.        
  178.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.Add5"]/*' />
  179.         public XmlSchema Add(XmlSchema schema, XmlResolver resolver)
  180.         {
  181.             if (schema == null)
  182.                 throw new ArgumentNullException("schema");
  183.            
  184.             SchemaInfo schemaInfo = new SchemaInfo();
  185.             schemaInfo.SchemaType = SchemaType.XSD;
  186.             return Add(schema.TargetNamespace, schemaInfo, schema, true, resolver);
  187.         }
  188.        
  189.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.Add3"]/*' />
  190.         /// <devdoc>
  191.         /// <para>Adds all the namespaces defined in the given collection
  192.         /// (including their associated schemas) to this collection.</para>
  193.         /// </devdoc>
  194.         public void Add(XmlSchemaCollection schema)
  195.         {
  196.             if (schema == null)
  197.                 throw new ArgumentNullException("schema");
  198.             if (this == schema)
  199.                 return;
  200.             IDictionaryEnumerator enumerator = schema.collection.GetEnumerator();
  201.             while (enumerator.MoveNext()) {
  202.                 XmlSchemaCollectionNode node = (XmlSchemaCollectionNode)enumerator.Value;
  203.                 Add(node.NamespaceURI, node);
  204.             }
  205.         }
  206.        
  207.        
  208.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.this"]/*' />
  209.         /// <devdoc>
  210.         /// <para>Looks up the schema by it's associated namespace URI</para>
  211.         /// </devdoc>
  212.         public XmlSchema this[string ns]
  213.         {
  214.             get {
  215.                 XmlSchemaCollectionNode node = (XmlSchemaCollectionNode)collection[(ns != null) ? ns : string.Empty];
  216.                 return (node != null) ? node.Schema : null;
  217.             }
  218.         }
  219.        
  220.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.Contains"]/*' />
  221.         /// <devdoc>
  222.         /// <para>[To be supplied.]</para>
  223.         /// </devdoc>
  224.         public bool Contains(XmlSchema schema)
  225.         {
  226.             if (schema == null) {
  227.                 throw new ArgumentNullException("schema");
  228.             }
  229.             return this[schema.TargetNamespace] != null;
  230.         }
  231.        
  232.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.Contains1"]/*' />
  233.         public bool Contains(string ns)
  234.         {
  235.             return collection[(ns != null) ? ns : string.Empty] != null;
  236.         }
  237.        
  238.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.IEnumerable.GetEnumerator"]/*' />
  239.         /// <internalonly/>
  240.         /// <devdoc>
  241.         /// Get a IEnumerator of the XmlSchemaCollection.
  242.         /// </devdoc>
  243.         IEnumerator IEnumerable.GetEnumerator()
  244.         {
  245.             return new XmlSchemaCollectionEnumerator(collection);
  246.         }
  247.        
  248.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.GetEnumerator"]/*' />
  249.         public XmlSchemaCollectionEnumerator GetEnumerator()
  250.         {
  251.             return new XmlSchemaCollectionEnumerator(collection);
  252.         }
  253.        
  254.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.ICollection.CopyTo"]/*' />
  255.         /// <internalonly/>
  256.         void ICollection.CopyTo(Array array, int index)
  257.         {
  258.             if (array == null)
  259.                 throw new ArgumentNullException("array");
  260.             if (index < 0)
  261.                 throw new ArgumentOutOfRangeException("index");
  262.             for (XmlSchemaCollectionEnumerator e = this.GetEnumerator(); e.MoveNext();) {
  263.                 if (index == array.Length && array.IsFixedSize) {
  264.                     throw new ArgumentOutOfRangeException("index");
  265.                 }
  266.                 array.SetValue(e.Current, index++);
  267.             }
  268.         }
  269.        
  270.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.CopyTo"]/*' />
  271.         /// <devdoc>
  272.         /// <para>[To be supplied.]</para>
  273.         /// </devdoc>
  274.         public void CopyTo(XmlSchema[] array, int index)
  275.         {
  276.             if (array == null)
  277.                 throw new ArgumentNullException("array");
  278.             if (index < 0)
  279.                 throw new ArgumentOutOfRangeException("index");
  280.             for (XmlSchemaCollectionEnumerator e = this.GetEnumerator(); e.MoveNext();) {
  281.                 XmlSchema schema = e.Current;
  282.                 if (schema != null) {
  283.                     if (index == array.Length) {
  284.                         throw new ArgumentOutOfRangeException("index");
  285.                     }
  286.                     array[index++] = e.Current;
  287.                 }
  288.             }
  289.         }
  290.        
  291.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.ICollection.IsSynchronized"]/*' />
  292.         /// <internalonly/>
  293.         bool ICollection.IsSynchronized {
  294.             get { return true; }
  295.         }
  296.        
  297.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.ICollection.SyncRoot"]/*' />
  298.         /// <internalonly/>
  299.         object ICollection.SyncRoot {
  300.             get { return this; }
  301.         }
  302.        
  303.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollection.ICollection.Count"]/*' />
  304.         /// <internalonly/>
  305.         int ICollection.Count {
  306.             get { return collection.Count; }
  307.         }
  308.        
  309.         internal SchemaInfo GetSchemaInfo(string ns)
  310.         {
  311.             XmlSchemaCollectionNode node = (XmlSchemaCollectionNode)collection[(ns != null) ? ns : string.Empty];
  312.             return (node != null) ? node.SchemaInfo : null;
  313.         }
  314.        
  315.         internal SchemaNames GetSchemaNames(XmlNameTable nt)
  316.         {
  317.             if (nameTable != nt) {
  318.                 return new SchemaNames(nt);
  319.             }
  320.             else {
  321.                 if (schemaNames == null) {
  322.                     schemaNames = new SchemaNames(nameTable);
  323.                 }
  324.                 return schemaNames;
  325.             }
  326.         }
  327.        
  328.         internal XmlSchema Add(string ns, SchemaInfo schemaInfo, XmlSchema schema, bool compile)
  329.         {
  330.             return Add(ns, schemaInfo, schema, compile, xmlResolver);
  331.         }
  332.        
  333.         private XmlSchema Add(string ns, SchemaInfo schemaInfo, XmlSchema schema, bool compile, XmlResolver resolver)
  334.         {
  335.             int errorCount = 0;
  336.             if (schema != null) {
  337.                 if (schema.ErrorCount == 0 && compile) {
  338.                     if (!schema.CompileSchema(this, resolver, schemaInfo, ns, validationEventHandler, nameTable, true)) {
  339.                         errorCount = 1;
  340.                     }
  341.                     ns = schema.TargetNamespace == null ? string.Empty : schema.TargetNamespace;
  342.                 }
  343.                 errorCount += schema.ErrorCount;
  344.             }
  345.             else {
  346.                 errorCount += schemaInfo.ErrorCount;
  347.                 //ns = ns == null? string.Empty : NameTable.Add(ns);
  348.                 ns = NameTable.Add(ns);
  349.                 //Added without checking for ns == null, since XDR cannot have null namespace
  350.             }
  351.             if (errorCount == 0) {
  352.                 XmlSchemaCollectionNode node = new XmlSchemaCollectionNode();
  353.                 node.NamespaceURI = ns;
  354.                 node.SchemaInfo = schemaInfo;
  355.                 node.Schema = schema;
  356.                 Add(ns, node);
  357.                 return schema;
  358.             }
  359.             return null;
  360.         }
  361.        
  362.         private void Add(string ns, XmlSchemaCollectionNode node)
  363.         {
  364.             if (isThreadSafe)
  365.                 wLock.AcquireWriterLock(timeout);
  366.             try {
  367.                 if (collection[ns] != null)
  368.                     collection.Remove(ns);
  369.                 collection.Add(ns, node);
  370.             }
  371.             finally {
  372.                 if (isThreadSafe)
  373.                     wLock.ReleaseWriterLock();
  374.             }
  375.         }
  376.        
  377.         private void SendValidationEvent(XmlSchemaException e)
  378.         {
  379.             if (validationEventHandler != null) {
  380.                 validationEventHandler(this, new ValidationEventArgs(e));
  381.             }
  382.             else {
  383.                 throw e;
  384.             }
  385.         }
  386.        
  387.         internal ValidationEventHandler EventHandler {
  388.             get { return validationEventHandler; }
  389.             set { validationEventHandler = value; }
  390.         }
  391.     }
  392.    
  393.    
  394.     internal sealed class XmlSchemaCollectionNode
  395.     {
  396.         private string namespaceUri;
  397.         private SchemaInfo schemaInfo;
  398.         private XmlSchema schema;
  399.        
  400.         internal string NamespaceURI {
  401.             get { return namespaceUri; }
  402.             set { namespaceUri = value; }
  403.         }
  404.        
  405.         internal SchemaInfo SchemaInfo {
  406.             get { return schemaInfo; }
  407.             set { schemaInfo = value; }
  408.         }
  409.        
  410.         internal XmlSchema Schema {
  411.             get { return schema; }
  412.             set { schema = value; }
  413.         }
  414.     }
  415.    
  416.    
  417.     /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollectionEnumerator"]/*' />
  418.     /// <devdoc>
  419.     /// <para>[To be supplied.]</para>
  420.     /// </devdoc>
  421.     public sealed class XmlSchemaCollectionEnumerator : IEnumerator
  422.     {
  423.         private IDictionaryEnumerator enumerator;
  424.        
  425.         internal XmlSchemaCollectionEnumerator(Hashtable collection)
  426.         {
  427.             enumerator = collection.GetEnumerator();
  428.         }
  429.        
  430.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollectionEnumerator.IEnumerator.Reset"]/*' />
  431.         /// <internalonly/>
  432.         void IEnumerator.Reset()
  433.         {
  434.             enumerator.Reset();
  435.         }
  436.        
  437.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollectionEnumerator.IEnumerator.MoveNext"]/*' />
  438.         /// <internalonly/>
  439.         bool IEnumerator.MoveNext()
  440.         {
  441.             return enumerator.MoveNext();
  442.         }
  443.        
  444.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollectionEnumerator.MoveNext"]/*' />
  445.         /// <devdoc>
  446.         /// <para>[To be supplied.]</para>
  447.         /// </devdoc>
  448.         public bool MoveNext()
  449.         {
  450.             return enumerator.MoveNext();
  451.         }
  452.        
  453.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollectionEnumerator.IEnumerator.Current"]/*' />
  454.         /// <internalonly/>
  455.         object IEnumerator.Current {
  456.             get { return this.Current; }
  457.         }
  458.        
  459.         /// <include file='doc\XmlSchemaCollection.uex' path='docs/doc[@for="XmlSchemaCollectionEnumerator.Current"]/*' />
  460.         /// <devdoc>
  461.         /// <para>[To be supplied.]</para>
  462.         /// </devdoc>
  463.         public XmlSchema Current {
  464.             get {
  465.                 XmlSchemaCollectionNode n = (XmlSchemaCollectionNode)enumerator.Value;
  466.                 if (n != null)
  467.                     return n.Schema;
  468.                 else
  469.                     return null;
  470.             }
  471.         }
  472.        
  473.         internal XmlSchemaCollectionNode CurrentNode {
  474.             get {
  475.                 XmlSchemaCollectionNode n = (XmlSchemaCollectionNode)enumerator.Value;
  476.                 return n;
  477.             }
  478.         }
  479.     }
  480. }

Developer Fusion