1 //------------------------------------------------------------------------------
2 // <copyright file="XmlSchema.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
8 namespace System
.Xml
.Schema
{
10 public class XmlSchema
: XmlSchemaObject
12 //Empty XmlSchema class to enable backward compatibility of interface method IXmlSerializable.GetSchema()
13 //Add private ctor to prevent constructing of this class
18 using System
.Collections
;
19 using System
.ComponentModel
;
20 using System
.Xml
.Serialization
;
21 using System
.Threading
;
22 using System
.Diagnostics
;
24 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema"]/*' />
26 /// <para>[To be supplied.]</para>
28 [XmlRoot("schema", Namespace
=XmlSchema
.Namespace
)]
29 public class XmlSchema
: XmlSchemaObject
{
31 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Namespace"]/*' />
33 /// <para>[To be supplied.]</para>
35 public const string Namespace
= XmlReservedNs
.NsXs
;
36 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.InstanceNamespace"]/*' />
38 /// <para>[To be supplied.]</para>
40 public const string InstanceNamespace
= XmlReservedNs
.NsXsi
;
42 XmlSchemaForm attributeFormDefault
= XmlSchemaForm
.None
;
43 XmlSchemaForm elementFormDefault
= XmlSchemaForm
.None
;
44 XmlSchemaDerivationMethod blockDefault
= XmlSchemaDerivationMethod
.None
;
45 XmlSchemaDerivationMethod finalDefault
= XmlSchemaDerivationMethod
.None
;
48 XmlSchemaObjectCollection includes
= new XmlSchemaObjectCollection();
49 XmlSchemaObjectCollection items
= new XmlSchemaObjectCollection();
51 XmlAttribute
[] moreAttributes
;
54 bool isCompiled
= false;
55 bool isCompiledBySet
= false;
56 bool isPreprocessed
= false;
57 bool isRedefined
= false;
59 XmlSchemaObjectTable attributes
;
60 XmlSchemaObjectTable attributeGroups
= new XmlSchemaObjectTable();
61 XmlSchemaObjectTable elements
= new XmlSchemaObjectTable();
62 XmlSchemaObjectTable types
= new XmlSchemaObjectTable();
63 XmlSchemaObjectTable groups
= new XmlSchemaObjectTable();
64 XmlSchemaObjectTable notations
= new XmlSchemaObjectTable();
65 XmlSchemaObjectTable identityConstraints
= new XmlSchemaObjectTable();
67 static int globalIdCounter
= -1;
68 ArrayList importedSchemas
;
69 ArrayList importedNamespaces
;
71 int schemaId
= -1; //Not added to a set
74 Hashtable ids
= new Hashtable();
76 XmlNameTable nameTable
;
78 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.XmlSchema"]/*' />
80 /// <para>[To be supplied.]</para>
84 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Read"]/*' />
86 /// <para>[To be supplied.]</para>
88 public static XmlSchema
Read(TextReader reader
, ValidationEventHandler validationEventHandler
) {
89 return Read(new XmlTextReader(reader
), validationEventHandler
);
92 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Read1"]/*' />
94 /// <para>[To be supplied.]</para>
96 public static XmlSchema
Read(Stream stream
, ValidationEventHandler validationEventHandler
) {
97 return Read(new XmlTextReader(stream
), validationEventHandler
);
100 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Read2"]/*' />
102 /// <para>[To be supplied.]</para>
104 public static XmlSchema
Read(XmlReader reader
, ValidationEventHandler validationEventHandler
) {
105 XmlNameTable nameTable
= reader
.NameTable
;
106 Parser parser
= new Parser(SchemaType
.XSD
, nameTable
, new SchemaNames(nameTable
), validationEventHandler
);
108 parser
.Parse(reader
, null);
110 catch(XmlSchemaException e
) {
111 if (validationEventHandler
!= null) {
112 validationEventHandler(null, new ValidationEventArgs(e
));
119 return parser
.XmlSchema
;
122 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Write"]/*' />
124 /// <para>[To be supplied.]</para>
126 public void Write(Stream stream
) {
130 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Write1"]/*' />
132 /// <para>[To be supplied.]</para>
134 public void Write(Stream stream
, XmlNamespaceManager namespaceManager
) {
135 XmlTextWriter xmlWriter
= new XmlTextWriter(stream
, null);
136 xmlWriter
.Formatting
= Formatting
.Indented
;
137 Write(xmlWriter
, namespaceManager
);
140 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Write2"]/*' />
142 /// <para>[To be supplied.]</para>
144 public void Write(TextWriter writer
) {
148 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Write3"]/*' />
150 /// <para>[To be supplied.]</para>
152 public void Write(TextWriter writer
, XmlNamespaceManager namespaceManager
) {
153 XmlTextWriter xmlWriter
= new XmlTextWriter(writer
);
154 xmlWriter
.Formatting
= Formatting
.Indented
;
155 Write(xmlWriter
, namespaceManager
);
158 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Write4"]/*' />
160 /// <para>[To be supplied.]</para>
162 public void Write(XmlWriter writer
) {
166 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Write5"]/*' />
168 /// <para>[To be supplied.]</para>
170 public void Write(XmlWriter writer
, XmlNamespaceManager namespaceManager
) {
171 XmlSerializer serializer
= new XmlSerializer(typeof(XmlSchema
));
172 XmlSerializerNamespaces ns
;
174 if (namespaceManager
!= null) {
175 ns
= new XmlSerializerNamespaces();
176 bool ignoreXS
= false;
177 if (this.Namespaces
!= null) { //User may have set both nsManager and Namespaces property on the XmlSchema object
178 ignoreXS
= this.Namespaces
.Namespaces
["xs"] != null || this.Namespaces
.Namespaces
.ContainsValue(XmlReservedNs
.NsXs
);
181 if (!ignoreXS
&& namespaceManager
.LookupPrefix(XmlReservedNs
.NsXs
) == null &&
182 namespaceManager
.LookupNamespace("xs") == null ) {
183 ns
.Add("xs", XmlReservedNs
.NsXs
);
185 foreach(string prefix
in namespaceManager
) {
186 if (prefix
!= "xml" && prefix
!= "xmlns") {
187 ns
.Add(prefix
, namespaceManager
.LookupNamespace(prefix
));
191 } else if (this.Namespaces
!= null && this.Namespaces
.Count
> 0) {
192 Hashtable serializerNS
= this.Namespaces
.Namespaces
;
193 if (serializerNS
["xs"] == null && !serializerNS
.ContainsValue(XmlReservedNs
.NsXs
)) { //Prefix xs not defined AND schema namespace not already mapped to a prefix
194 serializerNS
.Add("xs", XmlReservedNs
.NsXs
);
196 ns
= this.Namespaces
;
199 ns
= new XmlSerializerNamespaces();
200 ns
.Add("xs", XmlSchema
.Namespace
);
201 if (targetNs
!= null && targetNs
.Length
!= 0) {
202 ns
.Add("tns", targetNs
);
205 serializer
.Serialize(writer
, this, ns
);
208 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Compile"]/*' />
210 /// <para>[To be supplied.]</para>
212 [Obsolete("Use System.Xml.Schema.XmlSchemaSet for schema compilation and validation. http://go.microsoft.com/fwlink/?linkid=14202")]
213 public void Compile(ValidationEventHandler validationEventHandler
) {
214 SchemaInfo sInfo
= new SchemaInfo();
215 sInfo
.SchemaType
= SchemaType
.XSD
;
216 CompileSchema(null, System
.Xml
.XmlConfiguration
.XmlReaderSection
.CreateDefaultResolver(), sInfo
, null, validationEventHandler
, NameTable
, false);
219 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Compileq"]/*' />
221 /// <para>[To be supplied.]</para>
223 [Obsolete("Use System.Xml.Schema.XmlSchemaSet for schema compilation and validation. http://go.microsoft.com/fwlink/?linkid=14202")]
224 public void Compile(ValidationEventHandler validationEventHandler
, XmlResolver resolver
) {
225 SchemaInfo sInfo
= new SchemaInfo();
226 sInfo
.SchemaType
= SchemaType
.XSD
;
227 CompileSchema(null, resolver
, sInfo
, null, validationEventHandler
, NameTable
, false);
230 #pragma warning disable 618
231 internal bool CompileSchema(XmlSchemaCollection xsc
, XmlResolver resolver
, SchemaInfo schemaInfo
, string ns
, ValidationEventHandler validationEventHandler
, XmlNameTable nameTable
, bool CompileContentModel
) {
233 //Need to lock here to prevent multi-threading problems when same schema is added to set and compiled
236 SchemaCollectionPreprocessor prep
= new SchemaCollectionPreprocessor(nameTable
, null, validationEventHandler
);
237 prep
.XmlResolver
= resolver
;
238 if (!prep
.Execute(this, ns
, true, xsc
)) {
243 SchemaCollectionCompiler compiler
= new SchemaCollectionCompiler(nameTable
, validationEventHandler
);
244 isCompiled
= compiler
.Execute(this, schemaInfo
, CompileContentModel
);
245 this.SetIsCompiled(isCompiled
);
250 #pragma warning restore 618
252 internal void CompileSchemaInSet(XmlNameTable nameTable
, ValidationEventHandler eventHandler
, XmlSchemaCompilationSettings compilationSettings
) {
253 Debug
.Assert(this.isPreprocessed
);
254 Compiler setCompiler
= new Compiler(nameTable
, eventHandler
, null, compilationSettings
);
255 setCompiler
.Prepare(this, true);
256 this.isCompiledBySet
= setCompiler
.Compile();
259 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.AttributeFormDefault"]/*' />
261 /// <para>[To be supplied.]</para>
263 [XmlAttribute("attributeFormDefault"), DefaultValue(XmlSchemaForm
.None
)]
264 public XmlSchemaForm AttributeFormDefault
{
265 get { return attributeFormDefault; }
266 set { attributeFormDefault = value; }
269 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.BlockDefault"]/*' />
271 /// <para>[To be supplied.]</para>
273 [XmlAttribute("blockDefault"), DefaultValue(XmlSchemaDerivationMethod
.None
)]
274 public XmlSchemaDerivationMethod BlockDefault
{
275 get { return blockDefault; }
276 set { blockDefault = value; }
279 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.FinalDefault"]/*' />
281 /// <para>[To be supplied.]</para>
283 [XmlAttribute("finalDefault"), DefaultValue(XmlSchemaDerivationMethod
.None
)]
284 public XmlSchemaDerivationMethod FinalDefault
{
285 get { return finalDefault; }
286 set { finalDefault = value; }
289 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.ElementFormDefault"]/*' />
291 /// <para>[To be supplied.]</para>
293 [XmlAttribute("elementFormDefault"), DefaultValue(XmlSchemaForm
.None
)]
294 public XmlSchemaForm ElementFormDefault
{
295 get { return elementFormDefault; }
296 set { elementFormDefault = value; }
299 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.TargetNamespace"]/*' />
301 /// <para>[To be supplied.]</para>
303 [XmlAttribute("targetNamespace", DataType
="anyURI")]
304 public string TargetNamespace
{
305 get { return targetNs; }
306 set { targetNs = value; }
309 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Version"]/*' />
311 /// <para>[To be supplied.]</para>
313 [XmlAttribute("version", DataType
="token")]
314 public string Version
{
315 get { return version; }
316 set { version = value; }
319 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Includes"]/*' />
321 /// <para>[To be supplied.]</para>
323 [XmlElement("include", typeof(XmlSchemaInclude
)),
324 XmlElement("import", typeof(XmlSchemaImport
)),
325 XmlElement("redefine", typeof(XmlSchemaRedefine
))]
326 public XmlSchemaObjectCollection Includes
{
327 get { return includes; }
330 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Items"]/*' />
332 /// <para>[To be supplied.]</para>
334 [XmlElement("annotation", typeof(XmlSchemaAnnotation
)),
335 XmlElement("attribute", typeof(XmlSchemaAttribute
)),
336 XmlElement("attributeGroup", typeof(XmlSchemaAttributeGroup
)),
337 XmlElement("complexType", typeof(XmlSchemaComplexType
)),
338 XmlElement("simpleType", typeof(XmlSchemaSimpleType
)),
339 XmlElement("element", typeof(XmlSchemaElement
)),
340 XmlElement("group", typeof(XmlSchemaGroup
)),
341 XmlElement("notation", typeof(XmlSchemaNotation
))]
342 public XmlSchemaObjectCollection Items
{
343 get { return items; }
347 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.IsCompiled"]/*' />
349 /// <para>[To be supplied.]</para>
352 public bool IsCompiled
{
354 return isCompiled
|| isCompiledBySet
;
359 internal bool IsCompiledBySet
{
360 get { return isCompiledBySet; }
361 set { isCompiledBySet = value; }
365 internal bool IsPreprocessed
{
366 get { return isPreprocessed; }
367 set { isPreprocessed = value; }
371 internal bool IsRedefined
{
372 get { return isRedefined; }
373 set { isRedefined = value; }
376 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Attributes"]/*' />
378 /// <para>[To be supplied.]</para>
381 public XmlSchemaObjectTable Attributes
{
383 if (attributes
== null) {
384 attributes
= new XmlSchemaObjectTable();
390 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.AttributeGroups"]/*' />
392 /// <para>[To be supplied.]</para>
395 public XmlSchemaObjectTable AttributeGroups
{
397 if (attributeGroups
== null) {
398 attributeGroups
= new XmlSchemaObjectTable();
400 return attributeGroups
;
404 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.SchemaTypes"]/*' />
406 /// <para>[To be supplied.]</para>
409 public XmlSchemaObjectTable SchemaTypes
{
412 types
= new XmlSchemaObjectTable();
418 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Elements"]/*' />
420 /// <para>[To be supplied.]</para>
423 public XmlSchemaObjectTable Elements
{
425 if (elements
== null) {
426 elements
= new XmlSchemaObjectTable();
432 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Id"]/*' />
434 /// <para>[To be supplied.]</para>
436 [XmlAttribute("id", DataType
="ID")]
442 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.UnhandledAttributes"]/*' />
444 /// <para>[To be supplied.]</para>
447 public XmlAttribute
[] UnhandledAttributes
{
448 get { return moreAttributes; }
449 set { moreAttributes = value; }
452 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Groups"]/*' />
454 /// <para>[To be supplied.]</para>
457 public XmlSchemaObjectTable Groups
{
458 get { return groups; }
461 /// <include file='doc\XmlSchema.uex' path='docs/doc[@for="XmlSchema.Notations"]/*' />
463 /// <para>[To be supplied.]</para>
466 public XmlSchemaObjectTable Notations
{
467 get { return notations; }
471 internal XmlSchemaObjectTable IdentityConstraints
{
472 get { return identityConstraints; }
476 internal Uri BaseUri
{
477 get { return baseUri; }
484 // Please be careful with this property. Since it lazy initialized and its value depends on a global state
485 // if it gets called on multiple schemas in a different order the schemas will end up with different IDs
486 // Unfortunately the IDs are used to sort the schemas in the schema set and thus changing the IDs might change
487 // the order which would be a breaking change!!
488 // Simply put if you are planning to add or remove a call to this getter you need to be extra carefull
489 // or better don't do it at all.
490 internal int SchemaId
{
492 if (schemaId
== -1) {
493 schemaId
= Interlocked
.Increment(ref globalIdCounter
);
500 internal bool IsChameleon
{
501 get { return isChameleon; }
502 set { isChameleon = value; }
506 internal Hashtable Ids
{
511 internal XmlDocument Document
{
512 get { if (document == null) document = new XmlDocument(); return document; }
516 internal int ErrorCount
{
517 get { return errorCount; }
518 set { errorCount = value; }
521 internal new XmlSchema
Clone() {
522 XmlSchema that
= new XmlSchema();
523 that
.attributeFormDefault
= this.attributeFormDefault
;
524 that
.elementFormDefault
= this.elementFormDefault
;
525 that
.blockDefault
= this.blockDefault
;
526 that
.finalDefault
= this.finalDefault
;
527 that
.targetNs
= this.targetNs
;
528 that
.version
= this.version
;
529 that
.includes
= this.includes
;
531 that
.Namespaces
= this.Namespaces
;
532 that
.items
= this.items
;
533 that
.BaseUri
= this.BaseUri
;
535 SchemaCollectionCompiler
.Cleanup(that
);
539 internal XmlSchema
DeepClone() {
540 XmlSchema that
= new XmlSchema();
541 that
.attributeFormDefault
= this.attributeFormDefault
;
542 that
.elementFormDefault
= this.elementFormDefault
;
543 that
.blockDefault
= this.blockDefault
;
544 that
.finalDefault
= this.finalDefault
;
545 that
.targetNs
= this.targetNs
;
546 that
.version
= this.version
;
547 that
.isPreprocessed
= this.isPreprocessed
;
548 //that.IsProcessing = this.IsProcessing; //Not sure if this is needed
551 for (int i
= 0; i
< this.items
.Count
; ++i
) {
552 XmlSchemaObject newItem
;
554 XmlSchemaComplexType complexType
;
555 XmlSchemaElement element
;
556 XmlSchemaGroup
group;
558 if ((complexType
= items
[i
] as XmlSchemaComplexType
) != null) {
559 newItem
= complexType
.Clone(this);
561 else if ((element
= items
[i
] as XmlSchemaElement
) != null) {
562 newItem
= element
.Clone(this);
564 else if ((group = items
[i
] as XmlSchemaGroup
) != null) {
565 newItem
= group.Clone(this);
568 newItem
= items
[i
].Clone();
570 that
.Items
.Add(newItem
);
574 for (int i
= 0; i
< this.includes
.Count
; ++i
) {
575 XmlSchemaExternal newInclude
= (XmlSchemaExternal
)this.includes
[i
].Clone();
576 that
.Includes
.Add(newInclude
);
578 that
.Namespaces
= this.Namespaces
;
579 //that.includes = this.includes; //Need to verify this is OK for redefines
580 that
.BaseUri
= this.BaseUri
;
585 internal override string IdAttribute
{
590 internal void SetIsCompiled(bool isCompiled
) {
591 this.isCompiled
= isCompiled
;
594 internal override void SetUnhandledAttributes(XmlAttribute
[] moreAttributes
) {
595 this.moreAttributes
= moreAttributes
;
597 internal override void AddAnnotation(XmlSchemaAnnotation annotation
) {
598 items
.Add(annotation
);
601 internal XmlNameTable NameTable
{
602 get { if (nameTable == null) nameTable = new System.Xml.NameTable(); return nameTable; }
605 internal ArrayList ImportedSchemas
{
607 if (importedSchemas
== null) {
608 importedSchemas
= new ArrayList();
610 return importedSchemas
;
614 internal ArrayList ImportedNamespaces
{
616 if (importedNamespaces
== null) {
617 importedNamespaces
= new ArrayList();
619 return importedNamespaces
;
623 internal void GetExternalSchemasList(IList extList
, XmlSchema schema
) {
624 Debug
.Assert(extList
!= null && schema
!= null);
625 if (extList
.Contains(schema
)) {
629 for (int i
= 0; i
< schema
.Includes
.Count
; ++i
) {
630 XmlSchemaExternal ext
= (XmlSchemaExternal
)schema
.Includes
[i
];
631 if (ext
.Schema
!= null) {
632 GetExternalSchemasList(extList
, ext
.Schema
);
637 #if TRUST_COMPILE_STATE
638 internal void AddCompiledInfo(SchemaInfo schemaInfo
) {
639 XmlQualifiedName itemName
;
640 foreach (XmlSchemaElement element
in elements
.Values
) {
641 itemName
= element
.QualifiedName
;
642 schemaInfo
.TargetNamespaces
[itemName
.Namespace
] = true;
643 if (schemaInfo
.ElementDecls
[itemName
] == null) {
644 schemaInfo
.ElementDecls
.Add(itemName
, element
.ElementDecl
);
647 foreach (XmlSchemaAttribute attribute
in attributes
.Values
) {
648 itemName
= attribute
.QualifiedName
;
649 schemaInfo
.TargetNamespaces
[itemName
.Namespace
] = true;
650 if (schemaInfo
.ElementDecls
[itemName
] == null) {
651 schemaInfo
.AttributeDecls
.Add(itemName
, attribute
.AttDef
);
654 foreach (XmlSchemaType type
in types
.Values
) {
655 itemName
= type
.QualifiedName
;
656 schemaInfo
.TargetNamespaces
[itemName
.Namespace
] = true;
657 XmlSchemaComplexType complexType
= type
as XmlSchemaComplexType
;
658 if ((complexType
== null || type
!= XmlSchemaComplexType
.AnyType
) && schemaInfo
.ElementDeclsByType
[itemName
] == null) {
659 schemaInfo
.ElementDeclsByType
.Add(itemName
, type
.ElementDecl
);
662 foreach (XmlSchemaNotation notation
in notations
.Values
) {
663 itemName
= notation
.QualifiedName
;
664 schemaInfo
.TargetNamespaces
[itemName
.Namespace
] = true;
665 SchemaNotation no
= new SchemaNotation(itemName
);
666 no
.SystemLiteral
= notation
.System
;
667 no
.Pubid
= notation
.Public
;
668 if (schemaInfo
.Notations
[itemName
.Name
] == null) {
669 schemaInfo
.Notations
.Add(itemName
.Name
, no
);
673 #endif//TRUST_COMPILE_STATE