1 //------------------------------------------------------------------------------
2 // <copyright file="XmlSchemaSet.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
7 using System
.Diagnostics
;
8 using System
.Collections
;
9 using System
.Threading
;
10 using System
.Collections
.Generic
;
11 using System
.Runtime
.Versioning
;
13 namespace System
.Xml
.Schema
{
15 public class XmlSchemaSet
17 //Empty XmlSchemaSet class to enable backward compatibility of XmlSchemaProvideAttribute
18 //Add private ctor to prevent constructing of this class
22 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet"]/*' />
24 /// <para>The XmlSchemaSet contains a set of namespace URI's.
25 /// Each namespace also have an associated private data cache
26 /// corresponding to the XML-Data Schema or W3C XML Schema.
27 /// The XmlSchemaSet will able to load only XSD schemas,
28 /// and compile them into an internal "cooked schema representation".
29 /// The Validate method then uses this internal representation for
30 /// efficient runtime validation of any given subtree.</para>
32 public class XmlSchemaSet
{
33 XmlNameTable nameTable
;
34 SchemaNames schemaNames
;
35 SortedList schemas
; // List of source schemas
38 ValidationEventHandler internalEventHandler
;
39 ValidationEventHandler eventHandler
;
41 bool isCompiled
= false;
43 //Dictionary<Uri, XmlSchema> schemaLocations;
44 //Dictionary<ChameleonKey, XmlSchema> chameleonSchemas;
45 Hashtable schemaLocations
;
46 Hashtable chameleonSchemas
;
48 Hashtable targetNamespaces
;
51 //Cached Compiled Info
52 SchemaInfo cachedCompiledInfo
;
54 //Reader settings to parse schema
55 XmlReaderSettings readerSettings
;
56 XmlSchema schemaForSchema
; //Only one schema for schema per set
58 //Schema compilation settings
59 XmlSchemaCompilationSettings compilationSettings
;
61 internal XmlSchemaObjectTable elements
;
62 internal XmlSchemaObjectTable attributes
;
63 internal XmlSchemaObjectTable schemaTypes
;
64 internal XmlSchemaObjectTable substitutionGroups
;
65 private XmlSchemaObjectTable typeExtensions
;
68 private Object internalSyncObject
;
69 internal Object InternalSyncObject
{
71 if (internalSyncObject
== null) {
72 Object o
= new Object();
73 Interlocked
.CompareExchange
<Object
>(ref internalSyncObject
, o
, null);
75 return internalSyncObject
;
81 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.XmlSchemaSet"]/*' />
83 /// <para>Construct a new empty schema schemas.</para>
85 public XmlSchemaSet() : this(new NameTable()) {
88 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.XmlSchemaSet1"]/*' />
90 /// <para>Construct a new empty schema schemas with associated XmlNameTable.
91 /// The XmlNameTable is used when loading schemas</para>
93 public XmlSchemaSet(XmlNameTable nameTable
) {
94 if (nameTable
== null) {
95 throw new ArgumentNullException("nameTable");
97 this.nameTable
= nameTable
;
98 schemas
= new SortedList();
100 /*schemaLocations = new Dictionary<Uri, XmlSchema>();
101 chameleonSchemas = new Dictionary<ChameleonKey, XmlSchema>();*/
102 schemaLocations
= new Hashtable();
103 chameleonSchemas
= new Hashtable();
104 targetNamespaces
= new Hashtable();
105 internalEventHandler
= new ValidationEventHandler(InternalValidationCallback
);
106 eventHandler
= internalEventHandler
;
108 readerSettings
= new XmlReaderSettings();
110 // we don't have to check XmlReaderSettings.EnableLegacyXmlSettings() here because the following
111 // code will return same result either we are running on v4.5 or later
112 if (readerSettings
.GetXmlResolver() == null)
114 // The created resolver will be used in the schema validation only
115 readerSettings
.XmlResolver
= new XmlUrlResolver();
116 readerSettings
.IsXmlResolverSet
= false;
119 readerSettings
.NameTable
= nameTable
;
120 readerSettings
.DtdProcessing
= DtdProcessing
.Prohibit
;
122 compilationSettings
= new XmlSchemaCompilationSettings();
123 cachedCompiledInfo
= new SchemaInfo();
129 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.NameTable"]/*' />
131 /// <para>The default XmlNameTable used by the XmlSchemaSet when loading new schemas.</para>
133 public XmlNameTable NameTable
{
134 get { return nameTable;}
137 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.ValidationEventHandler"]/*' />
138 public event ValidationEventHandler ValidationEventHandler
{
140 eventHandler
-= internalEventHandler
;
141 eventHandler
+= value;
142 if (eventHandler
== null) {
143 eventHandler
= internalEventHandler
;
147 eventHandler
-= value;
148 if (eventHandler
== null) {
149 eventHandler
= internalEventHandler
;
154 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.IsCompiled"]/*' />
156 /// <para>IsCompiled is true when the schema set is in compiled state</para>
158 public bool IsCompiled
{
164 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.XmlResolver"]/*' />
168 public XmlResolver XmlResolver
{
170 readerSettings
.XmlResolver
= value;
174 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.CompilationSettings"]/*' />
178 public XmlSchemaCompilationSettings CompilationSettings
{
180 return compilationSettings
;
183 compilationSettings
= value;
187 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.Count"]/*' />
189 /// <para>Returns the count of schemas in the set</para>
193 return schemas
.Count
;
196 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.GlobalElements"]/*' />
200 public XmlSchemaObjectTable GlobalElements
{
202 if (elements
== null) {
203 elements
= new XmlSchemaObjectTable();
209 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.GlobalAttributes"]/*' />
213 public XmlSchemaObjectTable GlobalAttributes
{
215 if (attributes
== null) {
216 attributes
= new XmlSchemaObjectTable();
222 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.GlobalTypes"]/*' />
226 public XmlSchemaObjectTable GlobalTypes
{
228 if (schemaTypes
== null) {
229 schemaTypes
= new XmlSchemaObjectTable();
235 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.SubstitutionGroups"]/*' />
240 internal XmlSchemaObjectTable SubstitutionGroups
{
242 if (substitutionGroups
== null) {
243 substitutionGroups
= new XmlSchemaObjectTable();
245 return substitutionGroups
;
250 /// Table of all types extensions
252 internal Hashtable SchemaLocations
{
254 return schemaLocations
;
259 /// Table of all types extensions
261 internal XmlSchemaObjectTable TypeExtensions
{
263 if (typeExtensions
== null) {
264 typeExtensions
= new XmlSchemaObjectTable();
266 return typeExtensions
;
271 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.Add1"]/*' />
273 /// <para>Add the schema located by the given URL into the schema schemas.
274 /// If the given schema references other namespaces, the schemas for those other
275 /// namespaces are NOT automatically loaded.</para>
277 [ResourceConsumption(ResourceScope
.Machine
)]
278 [ResourceExposure(ResourceScope
.Machine
)]
279 public XmlSchema
Add(String targetNamespace
, String schemaUri
) {
280 if (schemaUri
== null || schemaUri
.Length
== 0) {
281 throw new ArgumentNullException("schemaUri");
283 if (targetNamespace
!= null) {
284 targetNamespace
= XmlComplianceUtil
.CDataNormalize(targetNamespace
);
286 XmlSchema schema
= null;
287 lock (InternalSyncObject
) {
288 //Check if schema from url has already been added
289 XmlResolver tempResolver
= readerSettings
.GetXmlResolver();
290 if ( tempResolver
== null ) {
291 tempResolver
= new XmlUrlResolver();
293 Uri tempSchemaUri
= tempResolver
.ResolveUri(null, schemaUri
);
294 if (IsSchemaLoaded(tempSchemaUri
, targetNamespace
, out schema
)) {
298 //Url already not processed; Load SOM from url
299 XmlReader reader
= XmlReader
.Create(schemaUri
, readerSettings
);
301 schema
= Add(targetNamespace
, ParseSchema(targetNamespace
, reader
)); //
302 while(reader
.Read());// wellformness check;
313 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.Add4"]/*' />
315 /// <para>Add the given schema into the schema schemas.
316 /// If the given schema references other namespaces, the schemas for those
317 /// other namespaces are NOT automatically loaded.</para>
319 public XmlSchema
Add(String targetNamespace
, XmlReader schemaDocument
) {
320 if (schemaDocument
== null) {
321 throw new ArgumentNullException("schemaDocument");
323 if (targetNamespace
!= null) {
324 targetNamespace
= XmlComplianceUtil
.CDataNormalize(targetNamespace
);
326 lock (InternalSyncObject
) {
327 XmlSchema schema
= null;
328 Uri schemaUri
= new Uri(schemaDocument
.BaseURI
, UriKind
.RelativeOrAbsolute
);
329 if (IsSchemaLoaded(schemaUri
, targetNamespace
, out schema
)) {
333 DtdProcessing dtdProcessing
= this.readerSettings
.DtdProcessing
;
334 SetDtdProcessing(schemaDocument
);
335 schema
= Add(targetNamespace
, ParseSchema(targetNamespace
, schemaDocument
));
336 this.readerSettings
.DtdProcessing
= dtdProcessing
; //reset dtdProcessing setting
343 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.Add5"]/*' />
345 /// <para>Adds all the namespaces defined in the given schemas
346 /// (including their associated schemas) to this schemas.</para>
348 public void Add(XmlSchemaSet schemas
) {
349 if (schemas
== null) {
350 throw new ArgumentNullException("schemas");
352 if (this == schemas
) {
355 bool thisLockObtained
= false;
356 bool schemasLockObtained
= false;
359 Monitor
.TryEnter(InternalSyncObject
, ref thisLockObtained
);
360 if (thisLockObtained
) {
361 Monitor
.TryEnter(schemas
.InternalSyncObject
, ref schemasLockObtained
);
362 if (schemasLockObtained
) {
366 Monitor
.Exit(InternalSyncObject
); //Give up this lock and try both again
367 thisLockObtained
= false;
368 Thread
.Yield(); //Let the thread that holds the lock run
374 XmlSchema currentSchema
;
376 if (schemas
.IsCompiled
) {
377 CopyFromCompiledSet(schemas
);
382 foreach(XmlSchema schema
in schemas
.SortedSchemas
.Values
) {
383 tns
= schema
.TargetNamespace
;
387 if (this.schemas
.ContainsKey(schema
.SchemaId
) || FindSchemaByNSAndUrl(schema
.BaseUri
, tns
, null) != null) { //Do not already existing url
390 currentSchema
= Add(schema
.TargetNamespace
, schema
);
391 if(currentSchema
== null) {
396 //Remove all from the set if even one schema in the passed in set is not preprocessed.
398 foreach(XmlSchema schema
in schemas
.SortedSchemas
.Values
) { //Remove all previously added schemas from the set
399 this.schemas
.Remove(schema
.SchemaId
); //Might remove schema that was already there and was not added thru this operation
400 schemaLocations
.Remove(schema
.BaseUri
);
405 finally { //release locks on sets
406 if (thisLockObtained
) {
407 Monitor
.Exit(InternalSyncObject
);
409 if (schemasLockObtained
) {
410 Monitor
.Exit(schemas
.InternalSyncObject
);
415 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.Add6"]/*' />
416 public XmlSchema
Add(XmlSchema schema
) {
417 if (schema
== null) {
418 throw new ArgumentNullException("schema");
420 lock (InternalSyncObject
) {
421 if (schemas
.ContainsKey(schema
.SchemaId
)) {
424 return Add(schema
.TargetNamespace
, schema
);
428 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.Remove"]/*' />
429 public XmlSchema
Remove(XmlSchema schema
) {
430 return Remove(schema
, true);
433 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.RemoveRecursive"]/*' />
434 public bool RemoveRecursive(XmlSchema schemaToRemove
) {
436 if (schemaToRemove
== null) {
437 throw new ArgumentNullException("schemaToRemove");
439 if (!schemas
.ContainsKey(schemaToRemove
.SchemaId
)) {
443 lock (InternalSyncObject
) { //Need to lock here so that remove cannot be called while the set is being compiled
444 if (schemas
.ContainsKey(schemaToRemove
.SchemaId
)) { //Need to check again
446 //Build disallowedNamespaces list
447 Hashtable disallowedNamespaces
= new Hashtable();
448 disallowedNamespaces
.Add(GetTargetNamespace(schemaToRemove
), schemaToRemove
);
450 for (int i
= 0; i
< schemaToRemove
.ImportedNamespaces
.Count
; i
++) {
451 importedNS
= (string)schemaToRemove
.ImportedNamespaces
[i
];
452 if (disallowedNamespaces
[importedNS
] == null) {
453 disallowedNamespaces
.Add(importedNS
, importedNS
);
457 //Removal list is all schemas imported by this schema directly or indirectly
458 //Need to check if other schemas in the set import schemaToRemove / any of its imports
459 ArrayList needToCheckSchemaList
= new ArrayList();
460 XmlSchema mainSchema
;
461 for (int i
=0; i
< schemas
.Count
; i
++) {
462 mainSchema
= (XmlSchema
)schemas
.GetByIndex(i
);
463 if (mainSchema
== schemaToRemove
||
464 schemaToRemove
.ImportedSchemas
.Contains(mainSchema
)) {
467 needToCheckSchemaList
.Add(mainSchema
);
471 for (int i
= 0; i
< needToCheckSchemaList
.Count
; i
++) { //Perf: Not using nested foreach here
472 mainSchema
= (XmlSchema
)needToCheckSchemaList
[i
];
474 if (mainSchema
.ImportedNamespaces
.Count
> 0) {
475 foreach(string tns
in disallowedNamespaces
.Keys
) {
476 if (mainSchema
.ImportedNamespaces
.Contains(tns
)) {
477 SendValidationEvent(new XmlSchemaException(Res
.Sch_SchemaNotRemoved
, string.Empty
), XmlSeverityType
.Warning
);
484 Remove(schemaToRemove
, true);
485 for (int i
= 0; i
< schemaToRemove
.ImportedSchemas
.Count
; ++i
) {
486 XmlSchema impSchema
= (XmlSchema
)schemaToRemove
.ImportedSchemas
[i
];
487 Remove(impSchema
, true);
495 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.Contains1"]/*' />
496 public bool Contains(String targetNamespace
) {
497 if (targetNamespace
== null) {
498 targetNamespace
= string.Empty
;
500 return targetNamespaces
[targetNamespace
] != null;
503 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.Contains2"]/*' />
504 public bool Contains(XmlSchema schema
) {
505 if (schema
== null) {
506 throw new ArgumentNullException("schema");
508 return schemas
.ContainsValue(schema
);
511 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.Compile"]/*' />
513 /// <para>[To be supplied.]</para>
515 public void Compile() {
519 if (schemas
.Count
== 0) {
520 ClearTables(); //Clear any previously present compiled state left by calling just Remove() on the set
521 cachedCompiledInfo
= new SchemaInfo();
526 lock (InternalSyncObject
) {
528 if (!isCompiled
) { //Locking before checking isCompiled to avoid problems with double locking
529 Compiler compiler
= new Compiler(nameTable
, eventHandler
, schemaForSchema
, compilationSettings
);
530 SchemaInfo newCompiledInfo
= new SchemaInfo();
532 if (!compileAll
) { //if we are not compiling everything again, Move the pre-compiled schemas to the compiler's tables
533 compiler
.ImportAllCompiledSchemas(this);
535 try { //First thing to do in the try block is to acquire locks since finally will try to release them.
536 //If we dont accuire the locks first, and an exception occurs in the code before the locking code, then Threading.SynchronizationLockException will be thrown
537 //when attempting to release it in the finally block
538 XmlSchema currentSchema
;
539 XmlSchema xmlNSSchema
= Preprocessor
.GetBuildInSchema();
540 for (schemaIndex
= 0; schemaIndex
< schemas
.Count
; schemaIndex
++) {
541 currentSchema
= (XmlSchema
)schemas
.GetByIndex(schemaIndex
);
543 //Lock schema to be compiled
544 #pragma warning disable 0618
546 Monitor
.Enter(currentSchema
);
547 #pragma warning restore 0618
548 if (!currentSchema
.IsPreprocessed
)
550 SendValidationEvent(new XmlSchemaException(Res
.Sch_SchemaNotPreprocessed
, string.Empty
), XmlSeverityType
.Error
);
554 if (currentSchema
.IsCompiledBySet
) {
558 else if ((object)currentSchema
== (object)xmlNSSchema
) { // prepare for xml namespace schema without cleanup
559 compiler
.Prepare(currentSchema
, false);
563 compiler
.Prepare(currentSchema
, true);
566 isCompiled
= compiler
.Execute(this, newCompiledInfo
);
569 newCompiledInfo
.Add(cachedCompiledInfo
, eventHandler
); //Add all the items from the old to the new compiled object
572 cachedCompiledInfo
= newCompiledInfo
; //Replace the compiled info in the set after successful compilation
576 //Release locks on all schemas
577 XmlSchema currentSchema
;
578 if (schemaIndex
== schemas
.Count
) {
581 for (int i
= schemaIndex
; i
>= 0; i
--) {
582 currentSchema
= (XmlSchema
)schemas
.GetByIndex(i
);
583 if (currentSchema
== Preprocessor
.GetBuildInSchema()) { //dont re-set compiled flags for xml namespace schema
584 Monitor
.Exit(currentSchema
);
587 currentSchema
.IsCompiledBySet
= isCompiled
;
588 Monitor
.Exit(currentSchema
);
596 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.Reprocess"]/*' />
598 /// <para>[To be supplied.]</para>
600 public XmlSchema
Reprocess(XmlSchema schema
) {
601 // Due to bug 644477 - this method is tightly coupled (THE CODE IS BASICALLY COPIED) to Remove, Add and AddSchemaToSet
602 // methods. If you change anything here *make sure* to update Remove/Add/AddSchemaToSet method(s) accordingly.
603 // The only difference is that we don't touch .schemas collection here to not break a code like this:
604 // foreach(XmlSchema s in schemaset.schemas) { schemaset.Reprocess(s); }
605 // This is by purpose.
606 if (schema
== null) {
607 throw new ArgumentNullException("schema");
609 if (!schemas
.ContainsKey(schema
.SchemaId
)) {
610 throw new ArgumentException(Res
.GetString(Res
.Sch_SchemaDoesNotExist
), "schema");
612 XmlSchema originalSchema
= schema
;
613 lock (InternalSyncObject
) { //Lock set so that set cannot be compiled in another thread
615 // This code is copied from method:
616 // Remove(XmlSchema schema, bool forceCompile)
617 // If you changed anything here go and change the same in Remove(XmlSchema schema, bool forceCompile) method
618 #region Copied from Remove(XmlSchema schema, bool forceCompile)
620 RemoveSchemaFromGlobalTables(schema
);
621 RemoveSchemaFromCaches(schema
);
622 if (schema
.BaseUri
!= null) {
623 schemaLocations
.Remove(schema
.BaseUri
);
625 string tns
= GetTargetNamespace(schema
);
626 if (Schemas(tns
).Count
== 0) { //This is the only schema for that namespace
627 targetNamespaces
.Remove(tns
);
630 compileAll
= true; //Force compilation of the whole set; This is when the set is not completely thread-safe
632 #endregion //Copied from Remove(XmlSchema schema, bool forceCompile)
635 // This code is copied from method:
636 // Add(string targetNamespace, XmlSchema schema)
637 // If you changed anything here go and change the same in Add(string targetNamespace, XmlSchema schema) method
638 #region Copied from Add(string targetNamespace, XmlSchema schema)
640 if (schema
.ErrorCount
!= 0) { //Schema with parsing errors cannot be loaded
641 return originalSchema
;
643 if (PreprocessSchema(ref schema
, schema
.TargetNamespace
)) { //No perf opt for already compiled schemas
645 // This code is copied from method:
646 // AddSchemaToSet(XmlSchema schema)
647 // If you changed anything here go and change the same in AddSchemaToSet(XmlSchema schema) method
648 #region Copied from AddSchemaToSet(XmlSchema schema)
650 //Add to targetNamespaces table
651 if (targetNamespaces
[tns
] == null) {
652 targetNamespaces
.Add(tns
, tns
);
654 if (schemaForSchema
== null && tns
== XmlReservedNs
.NsXs
&& schema
.SchemaTypes
[DatatypeImplementation
.QnAnyType
] != null) { //it has xs:anyType
655 schemaForSchema
= schema
;
657 for (int i
= 0; i
< schema
.ImportedSchemas
.Count
; ++i
) { //Once preprocessed external schemas property is set
658 XmlSchema s
= (XmlSchema
)schema
.ImportedSchemas
[i
];
659 if (!schemas
.ContainsKey(s
.SchemaId
)) {
660 schemas
.Add(s
.SchemaId
, s
);
662 tns
= GetTargetNamespace(s
);
663 if (targetNamespaces
[tns
] == null) {
664 targetNamespaces
.Add(tns
, tns
);
666 if (schemaForSchema
== null && tns
== XmlReservedNs
.NsXs
&& schema
.SchemaTypes
[DatatypeImplementation
.QnAnyType
] != null) { //it has xs:anyType
667 schemaForSchema
= schema
;
670 #endregion //Copied from AddSchemaToSet(XmlSchema schema)
673 #endregion // Copied from Add(string targetNamespace, XmlSchema schema)
675 return originalSchema
;
679 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.CopyTo"]/*' />
681 /// <para>[To be supplied.]</para>
683 public void CopyTo(XmlSchema
[] schemas
, int index
) {
685 throw new ArgumentNullException("schemas");
686 if (index
< 0 || index
> schemas
.Length
-1 )
687 throw new ArgumentOutOfRangeException("index");
688 this.schemas
.Values
.CopyTo(schemas
, index
);
691 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.Schemas1"]/*' />
693 /// <para>[To be supplied.]</para>
695 public ICollection
Schemas() {
696 return schemas
.Values
;
699 /// <include file='doc\XmlSchemaSet.uex' path='docs/doc[@for="XmlSchemaSet.Schemas1"]/*' />
701 /// <para>[To be supplied.]</para>
703 public ICollection
Schemas(String targetNamespace
) {
704 ArrayList tnsSchemas
= new ArrayList();
705 XmlSchema currentSchema
;
706 if (targetNamespace
== null) {
707 targetNamespace
= string.Empty
;
709 for (int i
=0; i
< schemas
.Count
; i
++) {
710 currentSchema
= (XmlSchema
)schemas
.GetByIndex(i
);
711 if (GetTargetNamespace(currentSchema
) == targetNamespace
) {
712 tnsSchemas
.Add(currentSchema
);
720 private XmlSchema
Add(string targetNamespace
, XmlSchema schema
) {
721 // Due to bug 644477 - this method is tightly coupled (THE CODE IS BASICALLY COPIED) to Reprocess
722 // method. If you change anything here *make sure* to update Reprocess method accordingly.
724 if (schema
== null || schema
.ErrorCount
!= 0) { //Schema with parsing errors cannot be loaded
728 // This code is copied to method:
729 // Reprocess(XmlSchema schema)
730 // If you changed anything here go and change the same in Reprocess(XmlSchema schema) method
731 if (PreprocessSchema(ref schema
, targetNamespace
)) { //No perf opt for already compiled schemas
732 AddSchemaToSet(schema
);
739 #if TRUST_COMPILE_STATE
740 private void AddCompiledSchema(XmlSchema schema
) {
741 if (schema
.IsCompiledBySet
) { //trust compiled state always if it is not a chameleon schema
743 SchemaInfo newCompiledInfo
= new SchemaInfo();
744 XmlSchemaObjectTable substitutionGroupsTable
= null;
745 if (!AddToCompiledInfo(schema
, newCompiledInfo
, ref substitutionGroupsTable
)) { //Error while adding main schema
748 foreach (XmlSchema impSchema
in schema
.ImportedSchemas
) {
749 if (!AddToCompiledInfo(impSchema
, newCompiledInfo
, ref substitutionGroupsTable
)) { //Error while adding imports
753 newCompiledInfo
.Add(cachedCompiledInfo
, eventHandler
); //Add existing compiled info
754 cachedCompiledInfo
= newCompiledInfo
;
755 if (substitutionGroupsTable
!= null) {
756 ProcessNewSubstitutionGroups(substitutionGroupsTable
, true);
758 if (schemas
.Count
== 0) { //If its the first compiled schema being added, then set doesnt need to be compiled
762 AddSchemaToSet(schema
);
767 private bool AddToCompiledInfo(XmlSchema schema
, SchemaInfo newCompiledInfo
, ref XmlSchemaObjectTable substTable
) {
768 //Add schema's compiled tables to the set
769 if (schema
.BaseUri
!= null && schemaLocations
[schema
.BaseUri
] == null) { //Update schemaLocations table
770 schemaLocations
.Add(schema
.BaseUri
, schema
);
773 foreach (XmlSchemaElement element
in schema
.Elements
.Values
) {
774 if(!AddToTable(elements
, element
.QualifiedName
, element
)) {
775 RemoveSchemaFromGlobalTables(schema
);
778 XmlQualifiedName head
= element
.SubstitutionGroup
;
780 if (substTable
== null) {
781 substTable
= new XmlSchemaObjectTable();
783 XmlSchemaSubstitutionGroup substitutionGroup
= (XmlSchemaSubstitutionGroup
)substTable
[head
];
784 if (substitutionGroup
== null) {
785 substitutionGroup
= new XmlSchemaSubstitutionGroup();
786 substitutionGroup
.Examplar
= head
;
787 substTable
.Add(head
, substitutionGroup
);
789 ArrayList members
= substitutionGroup
.Members
;
790 if (!members
.Contains(element
)) { //Members might contain element if the same schema is included and imported through different paths. Imp, hence will be added to set directly
791 members
.Add(element
);
795 foreach (XmlSchemaAttribute attribute
in schema
.Attributes
.Values
) {
796 if (!AddToTable(attributes
, attribute
.QualifiedName
, attribute
)) {
797 RemoveSchemaFromGlobalTables(schema
);
801 foreach (XmlSchemaType schemaType
in schema
.SchemaTypes
.Values
) {
802 if (!AddToTable(schemaTypes
, schemaType
.QualifiedName
, schemaType
)) {
803 RemoveSchemaFromGlobalTables(schema
);
807 schema
.AddCompiledInfo(newCompiledInfo
);
813 //For use by the validator when loading schemaLocations in the instance
814 internal void Add(String targetNamespace
, XmlReader reader
, Hashtable validatedNamespaces
) {
815 if (reader
== null) {
816 throw new ArgumentNullException("reader");
818 if (targetNamespace
== null) {
819 targetNamespace
= string.Empty
;
821 if (validatedNamespaces
[targetNamespace
] != null) {
822 if (FindSchemaByNSAndUrl(new Uri(reader
.BaseURI
, UriKind
.RelativeOrAbsolute
), targetNamespace
, null) != null) {
826 throw new XmlSchemaException(Res
.Sch_ComponentAlreadySeenForNS
, targetNamespace
);
830 //Not locking set as this will not be accessible outside the validator
832 if (IsSchemaLoaded(new Uri(reader
.BaseURI
, UriKind
.RelativeOrAbsolute
), targetNamespace
, out schema
)) {
835 else { //top-level schema not present for same url
836 schema
= ParseSchema(targetNamespace
, reader
);
838 //Store the previous locations
839 DictionaryEntry
[] oldLocations
= new DictionaryEntry
[schemaLocations
.Count
];
840 schemaLocations
.CopyTo(oldLocations
, 0);
843 Add(targetNamespace
, schema
);
844 if (schema
.ImportedSchemas
.Count
> 0) { //Check imports
846 for (int i
= 0; i
< schema
.ImportedSchemas
.Count
; ++i
) {
847 XmlSchema impSchema
= (XmlSchema
)schema
.ImportedSchemas
[i
];
848 tns
= impSchema
.TargetNamespace
;
852 if (validatedNamespaces
[tns
] != null && (FindSchemaByNSAndUrl(impSchema
.BaseUri
, tns
, oldLocations
) == null) ) {
853 RemoveRecursive(schema
);
854 throw new XmlSchemaException(Res
.Sch_ComponentAlreadySeenForNS
, tns
);
861 internal XmlSchema
FindSchemaByNSAndUrl(Uri schemaUri
, string ns
, DictionaryEntry
[] locationsTable
) {
862 if (schemaUri
== null || schemaUri
.OriginalString
.Length
== 0) {
865 XmlSchema schema
= null;
866 if (locationsTable
== null) {
867 schema
= (XmlSchema
)schemaLocations
[schemaUri
];
870 for (int i
= 0; i
< locationsTable
.Length
; i
++) {
871 if (schemaUri
.Equals(locationsTable
[i
].Key
)) {
872 schema
= (XmlSchema
)locationsTable
[i
].Value
;
877 if (schema
!= null) {
878 Debug
.Assert(ns
!= null);
879 string tns
= schema
.TargetNamespace
== null ? string.Empty
: schema
.TargetNamespace
;
883 else if (tns
== string.Empty
) { //There could be a chameleon for same ns
884 // It is OK to pass in the schema we have found so far, since it must have the schemaUri we're looking for
885 // (we found it that way above) and it must be the original chameleon schema (the one without target ns)
886 // as we don't add the chameleon copies into the locations tables above.
887 Debug
.Assert(schema
.BaseUri
.Equals(schemaUri
));
888 ChameleonKey cKey
= new ChameleonKey(ns
, schema
);
889 schema
= (XmlSchema
)chameleonSchemas
[cKey
]; //Need not clone if a schema for that namespace already exists
898 private void SetDtdProcessing(XmlReader reader
) {
899 if (reader
.Settings
!= null) {
900 this.readerSettings
.DtdProcessing
= reader
.Settings
.DtdProcessing
;
903 XmlTextReader v1Reader
= reader
as XmlTextReader
;
904 if (v1Reader
!= null) {
905 this.readerSettings
.DtdProcessing
= v1Reader
.DtdProcessing
;
910 private void AddSchemaToSet(XmlSchema schema
) {
911 // Due to bug 644477 - this method is tightly coupled (THE CODE IS BASICALLY COPIED) to Reprocess
912 // method. If you change anything here *make sure* to update Reprocess method accordingly.
914 schemas
.Add(schema
.SchemaId
, schema
);
915 //Add to targetNamespaces table
917 // This code is copied to method:
918 // Reprocess(XmlSchema schema)
919 // If you changed anything here go and change the same in Reprocess(XmlSchema schema) method
920 #region This code is copied to Reprocess(XmlSchema schema) method
922 string tns
= GetTargetNamespace(schema
);
923 if (targetNamespaces
[tns
] == null) {
924 targetNamespaces
.Add(tns
, tns
);
926 if (schemaForSchema
== null && tns
== XmlReservedNs
.NsXs
&& schema
.SchemaTypes
[DatatypeImplementation
.QnAnyType
] != null) { //it has xs:anyType
927 schemaForSchema
= schema
;
929 for (int i
= 0; i
< schema
.ImportedSchemas
.Count
; ++i
) { //Once preprocessed external schemas property is set
930 XmlSchema s
= (XmlSchema
)schema
.ImportedSchemas
[i
];
931 if (!schemas
.ContainsKey(s
.SchemaId
)) {
932 schemas
.Add(s
.SchemaId
, s
);
934 tns
= GetTargetNamespace(s
);
935 if (targetNamespaces
[tns
] == null) {
936 targetNamespaces
.Add(tns
, tns
);
938 if (schemaForSchema
== null && tns
== XmlReservedNs
.NsXs
&& schema
.SchemaTypes
[DatatypeImplementation
.QnAnyType
] != null) { //it has xs:anyType
939 schemaForSchema
= schema
;
943 #endregion // This code is copied to Reprocess(XmlSchema schema) method
946 private void ProcessNewSubstitutionGroups(XmlSchemaObjectTable substitutionGroupsTable
, bool resolve
) {
947 foreach(XmlSchemaSubstitutionGroup substGroup
in substitutionGroupsTable
.Values
) {
948 if (resolve
) { //Resolve substitutionGroups within this schema
949 ResolveSubstitutionGroup(substGroup
, substitutionGroupsTable
);
952 //Add or Merge new substitutionGroups with those that already exist in the set
953 XmlQualifiedName head
= substGroup
.Examplar
;
954 XmlSchemaSubstitutionGroup oldSubstGroup
= (XmlSchemaSubstitutionGroup
)substitutionGroups
[head
];
955 if (oldSubstGroup
!= null) {
956 for (int i
= 0; i
< substGroup
.Members
.Count
; ++i
) {
957 if (!oldSubstGroup
.Members
.Contains(substGroup
.Members
[i
])) {
958 oldSubstGroup
.Members
.Add(substGroup
.Members
[i
]);
963 AddToTable(substitutionGroups
, head
, substGroup
);
968 private void ResolveSubstitutionGroup(XmlSchemaSubstitutionGroup substitutionGroup
, XmlSchemaObjectTable substTable
) {
969 List
<XmlSchemaElement
> newMembers
= null;
970 XmlSchemaElement headElement
= (XmlSchemaElement
)elements
[substitutionGroup
.Examplar
];
971 if (substitutionGroup
.Members
.Contains(headElement
)) {// already checked
974 for (int i
= 0; i
< substitutionGroup
.Members
.Count
; ++i
) {
975 XmlSchemaElement element
= (XmlSchemaElement
)substitutionGroup
.Members
[i
];
977 //Chain to other head's that are members of this head's substGroup
978 XmlSchemaSubstitutionGroup g
= (XmlSchemaSubstitutionGroup
)substTable
[element
.QualifiedName
];
980 ResolveSubstitutionGroup(g
, substTable
);
981 for (int j
= 0; j
< g
.Members
.Count
; ++j
) {
982 XmlSchemaElement element1
= (XmlSchemaElement
)g
.Members
[j
];
983 if (element1
!= element
) { //Exclude the head
984 if (newMembers
== null) {
985 newMembers
= new List
<XmlSchemaElement
>();
987 newMembers
.Add(element1
);
992 if (newMembers
!= null) {
993 for (int i
= 0; i
< newMembers
.Count
; ++i
) {
994 substitutionGroup
.Members
.Add(newMembers
[i
]);
997 substitutionGroup
.Members
.Add(headElement
);
1000 internal XmlSchema
Remove(XmlSchema schema
, bool forceCompile
) {
1001 // Due to bug 644477 - this method is tightly coupled (THE CODE IS BASICALLY COPIED) to Reprocess
1002 // method. If you change anything here *make sure* to update Reprocess method accordingly.
1003 if (schema
== null) {
1004 throw new ArgumentNullException("schema");
1006 lock (InternalSyncObject
) { //Need to lock here so that remove cannot be called while the set is being compiled
1007 if (schemas
.ContainsKey(schema
.SchemaId
)) {
1009 // This code is copied to method:
1010 // Reprocess(XmlSchema schema)
1011 // If you changed anything here go and change the same in Reprocess(XmlSchema schema) method
1012 #region This code is copied to Reprocess(XmlSchema schema) method
1015 RemoveSchemaFromGlobalTables(schema
);
1016 RemoveSchemaFromCaches(schema
);
1018 schemas
.Remove(schema
.SchemaId
);
1019 if (schema
.BaseUri
!= null) {
1020 schemaLocations
.Remove(schema
.BaseUri
);
1022 string tns
= GetTargetNamespace(schema
);
1023 if (Schemas(tns
).Count
== 0) { //This is the only schema for that namespace
1024 targetNamespaces
.Remove(tns
);
1028 compileAll
= true; //Force compilation of the whole set; This is when the set is not completely thread-safe
1032 #endregion // This code is copied to Reprocess(XmlSchema schema) method
1038 private void ClearTables() {
1039 GlobalElements
.Clear();
1040 GlobalAttributes
.Clear();
1041 GlobalTypes
.Clear();
1042 SubstitutionGroups
.Clear();
1043 TypeExtensions
.Clear();
1046 internal bool PreprocessSchema(ref XmlSchema schema
, string targetNamespace
) {
1047 Preprocessor prep
= new Preprocessor(nameTable
, GetSchemaNames(nameTable
), eventHandler
, compilationSettings
);
1048 prep
.XmlResolver
= readerSettings
.GetXmlResolver_CheckConfig();
1049 prep
.ReaderSettings
= readerSettings
;
1050 prep
.SchemaLocations
= schemaLocations
;
1051 prep
.ChameleonSchemas
= chameleonSchemas
;
1052 bool hasErrors
= prep
.Execute(schema
, targetNamespace
, true);
1053 schema
= prep
.RootSchema
; //For any root level chameleon cloned
1057 internal XmlSchema
ParseSchema(string targetNamespace
, XmlReader reader
) {
1058 XmlNameTable readerNameTable
= reader
.NameTable
;
1059 SchemaNames schemaNames
= GetSchemaNames(readerNameTable
);
1060 Parser parser
= new Parser(SchemaType
.XSD
, readerNameTable
, schemaNames
, eventHandler
);
1061 parser
.XmlResolver
= readerSettings
.GetXmlResolver_CheckConfig();
1062 SchemaType schemaType
;
1064 schemaType
= parser
.Parse(reader
, targetNamespace
);
1066 catch(XmlSchemaException e
) {
1067 SendValidationEvent(e
, XmlSeverityType
.Error
);
1070 return parser
.XmlSchema
;
1073 internal void CopyFromCompiledSet(XmlSchemaSet otherSet
) {
1074 XmlSchema currentSchema
;
1075 SortedList copyFromList
= otherSet
.SortedSchemas
;
1076 bool setIsCompiled
= schemas
.Count
== 0 ? true : false;
1077 ArrayList existingSchemas
= new ArrayList();
1079 SchemaInfo newCompiledInfo
= new SchemaInfo();
1081 for(int i
=0; i
< copyFromList
.Count
; i
++) {
1082 currentSchema
= (XmlSchema
)copyFromList
.GetByIndex(i
);
1083 baseUri
= currentSchema
.BaseUri
;
1084 if (schemas
.ContainsKey(currentSchema
.SchemaId
) || (baseUri
!= null && baseUri
.OriginalString
.Length
!= 0 && schemaLocations
[baseUri
] != null)) {
1085 existingSchemas
.Add(currentSchema
);
1088 schemas
.Add(currentSchema
.SchemaId
, currentSchema
);
1089 if (baseUri
!= null && baseUri
.OriginalString
.Length
!= 0) {
1090 schemaLocations
.Add(baseUri
, currentSchema
);
1092 string tns
= GetTargetNamespace(currentSchema
);
1093 if (targetNamespaces
[tns
] == null) {
1094 targetNamespaces
.Add(tns
, tns
);
1099 foreach (XmlSchemaElement element
in otherSet
.GlobalElements
.Values
) {
1100 if(!AddToTable(elements
, element
.QualifiedName
, element
)) {
1104 foreach (XmlSchemaAttribute attribute
in otherSet
.GlobalAttributes
.Values
) {
1105 if (!AddToTable(attributes
, attribute
.QualifiedName
, attribute
)) {
1109 foreach (XmlSchemaType schemaType
in otherSet
.GlobalTypes
.Values
) {
1110 if (!AddToTable(schemaTypes
, schemaType
.QualifiedName
, schemaType
)) {
1115 ProcessNewSubstitutionGroups(otherSet
.SubstitutionGroups
, false);
1117 newCompiledInfo
.Add(cachedCompiledInfo
, eventHandler
); //Add all the items from the old to the new compiled object
1118 newCompiledInfo
.Add(otherSet
.CompiledInfo
,eventHandler
); //
1119 cachedCompiledInfo
= newCompiledInfo
; //Replace the compiled info in the set after successful compilation
1120 if (setIsCompiled
) {
1127 foreach (XmlSchema schemaToRemove
in copyFromList
.Values
) {
1128 if (!existingSchemas
.Contains(schemaToRemove
)) {
1129 Remove(schemaToRemove
, false);
1132 foreach (XmlSchemaElement elementToRemove
in otherSet
.GlobalElements
.Values
) {
1133 if(!existingSchemas
.Contains((XmlSchema
)elementToRemove
.Parent
)) {
1134 elements
.Remove(elementToRemove
.QualifiedName
);
1137 foreach (XmlSchemaAttribute attributeToRemove
in otherSet
.GlobalAttributes
.Values
) {
1138 if(!existingSchemas
.Contains((XmlSchema
)attributeToRemove
.Parent
)) {
1139 attributes
.Remove(attributeToRemove
.QualifiedName
);
1142 foreach (XmlSchemaType schemaTypeToRemove
in otherSet
.GlobalTypes
.Values
) {
1143 if(!existingSchemas
.Contains((XmlSchema
)schemaTypeToRemove
.Parent
)) {
1144 schemaTypes
.Remove(schemaTypeToRemove
.QualifiedName
);
1149 internal SchemaInfo CompiledInfo
{
1151 return cachedCompiledInfo
;
1155 internal XmlReaderSettings ReaderSettings
{
1157 return readerSettings
;
1161 internal XmlResolver
GetResolver() {
1162 return readerSettings
.GetXmlResolver_CheckConfig();
1165 internal ValidationEventHandler
GetEventHandler() {
1166 return eventHandler
;
1169 internal SchemaNames
GetSchemaNames(XmlNameTable nt
) {
1170 if (nameTable
!= nt
) {
1171 return new SchemaNames(nt
);
1174 if (schemaNames
== null) {
1175 schemaNames
= new SchemaNames( nameTable
);
1181 internal bool IsSchemaLoaded(Uri schemaUri
, string targetNamespace
, out XmlSchema schema
) {
1183 if (targetNamespace
== null) {
1184 targetNamespace
= string.Empty
;
1186 if (GetSchemaByUri(schemaUri
, out schema
)) {
1187 if (schemas
.ContainsKey(schema
.SchemaId
) && (targetNamespace
.Length
== 0 || targetNamespace
== schema
.TargetNamespace
)) { //schema is present in set
1190 else if (schema
.TargetNamespace
== null) { //If schema not in set or namespace doesnt match, then it might be a chameleon
1191 XmlSchema chameleonSchema
= FindSchemaByNSAndUrl(schemaUri
, targetNamespace
, null);
1192 if (chameleonSchema
!= null && schemas
.ContainsKey(chameleonSchema
.SchemaId
)) {
1193 schema
= chameleonSchema
;
1196 schema
= Add(targetNamespace
, schema
);
1199 else if (targetNamespace
.Length
!= 0 && targetNamespace
!= schema
.TargetNamespace
) {
1200 SendValidationEvent(new XmlSchemaException(Res
.Sch_MismatchTargetNamespaceEx
, new string[] { targetNamespace, schema.TargetNamespace }
), XmlSeverityType
.Error
);
1204 //If here, schema not present in set but in loc and might be added in loc through an earlier include
1205 //S.TNS != null && ( tns == null or tns == s.TNS)
1206 AddSchemaToSet(schema
);
1208 return true; //Schema Found
1213 internal bool GetSchemaByUri(Uri schemaUri
, out XmlSchema schema
) {
1215 if (schemaUri
== null || schemaUri
.OriginalString
.Length
== 0) {
1218 schema
= (XmlSchema
)schemaLocations
[schemaUri
];
1219 if (schema
!= null) {
1225 internal string GetTargetNamespace(XmlSchema schema
) {
1226 return schema
.TargetNamespace
== null ? string.Empty
: schema
.TargetNamespace
;
1230 internal SortedList SortedSchemas
{
1236 internal bool CompileAll
{
1243 private void RemoveSchemaFromCaches(XmlSchema schema
) {
1244 //Remove From ChameleonSchemas and schemaLocations cache
1245 List
<XmlSchema
> reprocessList
= new List
<XmlSchema
>();
1246 schema
.GetExternalSchemasList(reprocessList
, schema
);
1247 for (int i
= 0; i
< reprocessList
.Count
; ++i
) { //Remove schema from schemaLocations & chameleonSchemas tables
1248 if (reprocessList
[i
].BaseUri
!= null && reprocessList
[i
].BaseUri
.OriginalString
.Length
!= 0) {
1249 schemaLocations
.Remove(reprocessList
[i
].BaseUri
);
1251 //Remove from chameleon table
1252 ICollection chameleonKeys
= chameleonSchemas
.Keys
;
1253 ArrayList removalList
= new ArrayList();
1254 foreach(ChameleonKey cKey
in chameleonKeys
) {
1255 if (cKey
.chameleonLocation
.Equals(reprocessList
[i
].BaseUri
)) {
1256 // The key will have the originalSchema set to null if the location was not empty
1257 // otherwise we need to care about it as there may be more chameleon schemas without
1258 // a base URI and we want to remove only those which were created as a clone of the one
1260 if (cKey
.originalSchema
== null || Ref
.ReferenceEquals(cKey
.originalSchema
, reprocessList
[i
])) {
1261 removalList
.Add(cKey
);
1265 for (int j
= 0; j
< removalList
.Count
; ++j
) {
1266 chameleonSchemas
.Remove(removalList
[j
]);
1271 private void RemoveSchemaFromGlobalTables(XmlSchema schema
) {
1272 if (schemas
.Count
== 0) {
1276 foreach (XmlSchemaElement elementToRemove
in schema
.Elements
.Values
) {
1277 XmlSchemaElement elem
= (XmlSchemaElement
)elements
[elementToRemove
.QualifiedName
];
1278 if (elem
== elementToRemove
) {
1279 elements
.Remove(elementToRemove
.QualifiedName
);
1282 foreach (XmlSchemaAttribute attributeToRemove
in schema
.Attributes
.Values
) {
1283 XmlSchemaAttribute attr
= (XmlSchemaAttribute
)attributes
[attributeToRemove
.QualifiedName
];
1284 if (attr
== attributeToRemove
) {
1285 attributes
.Remove(attributeToRemove
.QualifiedName
);
1288 foreach (XmlSchemaType schemaTypeToRemove
in schema
.SchemaTypes
.Values
) {
1289 XmlSchemaType schemaType
= (XmlSchemaType
)schemaTypes
[schemaTypeToRemove
.QualifiedName
];
1290 if (schemaType
== schemaTypeToRemove
) {
1291 schemaTypes
.Remove(schemaTypeToRemove
.QualifiedName
);
1295 private bool AddToTable(XmlSchemaObjectTable table
, XmlQualifiedName qname
, XmlSchemaObject item
) {
1296 if (qname
.Name
.Length
== 0) {
1299 XmlSchemaObject existingObject
= (XmlSchemaObject
)table
[qname
];
1300 if (existingObject
!= null) {
1301 if (existingObject
== item
|| existingObject
.SourceUri
== item
.SourceUri
) {
1304 string code
= string.Empty
;
1305 if (item
is XmlSchemaComplexType
) {
1306 code
= Res
.Sch_DupComplexType
;
1308 else if (item
is XmlSchemaSimpleType
) {
1309 code
= Res
.Sch_DupSimpleType
;
1311 else if (item
is XmlSchemaElement
) {
1312 code
= Res
.Sch_DupGlobalElement
;
1314 else if (item
is XmlSchemaAttribute
) {
1315 if (qname
.Namespace
== XmlReservedNs
.NsXml
) {
1316 XmlSchema schemaForXmlNS
= Preprocessor
.GetBuildInSchema();
1317 XmlSchemaObject builtInAttribute
= schemaForXmlNS
.Attributes
[qname
];
1318 if (existingObject
== builtInAttribute
) { //replace built-in one
1319 table
.Insert(qname
, item
);
1322 else if (item
== builtInAttribute
) { //trying to overwrite customer's component with built-in, ignore built-in
1326 code
= Res
.Sch_DupGlobalAttribute
;
1328 SendValidationEvent(new XmlSchemaException(code
,qname
.ToString()), XmlSeverityType
.Error
);
1332 table
.Add(qname
, item
);
1337 private void VerifyTables() {
1338 if (elements
== null) {
1339 elements
= new XmlSchemaObjectTable();
1341 if (attributes
== null) {
1342 attributes
= new XmlSchemaObjectTable();
1344 if (schemaTypes
== null) {
1345 schemaTypes
= new XmlSchemaObjectTable();
1347 if (substitutionGroups
== null) {
1348 substitutionGroups
= new XmlSchemaObjectTable();
1352 private void InternalValidationCallback(object sender
, ValidationEventArgs e
) {
1353 if (e
.Severity
== XmlSeverityType
.Error
) {
1358 private void SendValidationEvent(XmlSchemaException e
, XmlSeverityType severity
) {
1359 if (eventHandler
!= null) {
1360 eventHandler(this, new ValidationEventArgs(e
, severity
));