Add MIT license to System.XML.DLL
[mono.git] / mcs / class / System.XML / System.Xml.Schema / XmlSchema.cs
1 //\r
2 // System.Xml.Schema.XmlSchema.cs\r
3 //\r
4 // Author:\r
5 //      Dwivedi, Ajay kumar  Adwiv@Yahoo.com\r
6 //      Atsushi Enomoto  ginga@kit.hi-ho.ne.jp\r
7 //\r
8
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29 using System;\r
30 using System.Collections;\r
31 using System.Xml;\r
32 using System.IO;\r
33 using System.Xml.Serialization;\r
34 using System.ComponentModel;\r
35 \r
36 namespace System.Xml.Schema\r
37 {\r
38         /// <summary>\r
39         /// Summary description for XmlSchema.\r
40         /// </summary>\r
41         [XmlRoot("schema",Namespace=XmlSchema.Namespace)]\r
42         public class XmlSchema : XmlSchemaObject\r
43         {\r
44                 //public constants\r
45                 public const string Namespace = "http://www.w3.org/2001/XMLSchema";\r
46                 public const string InstanceNamespace = "http://www.w3.org/2001/XMLSchema-instance";\r
47 \r
48                 //private fields\r
49                 private XmlSchemaForm attributeFormDefault ;\r
50                 private XmlSchemaObjectTable attributeGroups ;\r
51                 private XmlSchemaObjectTable attributes ;\r
52                 private XmlSchemaDerivationMethod blockDefault ;\r
53                 private XmlSchemaForm elementFormDefault ;\r
54                 private XmlSchemaObjectTable elements ;\r
55                 private XmlSchemaDerivationMethod finalDefault ;\r
56                 private XmlSchemaObjectTable groups ;\r
57                 private string id ;\r
58                 private XmlSchemaObjectCollection includes ;\r
59                 private XmlSchemaObjectCollection items ;\r
60                 private XmlSchemaObjectTable notations ;\r
61                 private XmlSchemaObjectTable schemaTypes ;\r
62                 private string targetNamespace ;\r
63                 private XmlAttribute[] unhandledAttributes ;\r
64                 private string version;\r
65                 private string language;\r
66 \r
67                 // other post schema compilation infoset\r
68                 private Hashtable idCollection;\r
69                 private XmlSchemaObjectTable namedIdentities;\r
70                 private XmlSchemaCollection schemas;\r
71 \r
72                 private XmlNameTable nameTable;\r
73 \r
74                 internal bool missedSubComponents;\r
75 \r
76                 // Only compilation-time use\r
77                 private XmlSchemaObjectCollection compilationItems;\r
78                 private Hashtable handledUris;\r
79 \r
80                 // Compiler specific things\r
81                 const string xmlname = "schema";\r
82 \r
83                 public XmlSchema()\r
84                 {\r
85                         attributeFormDefault= XmlSchemaForm.None;\r
86                         blockDefault            = XmlSchemaDerivationMethod.None;\r
87                         elementFormDefault      = XmlSchemaForm.None;\r
88                         finalDefault            = XmlSchemaDerivationMethod.None;\r
89                         includes                        = new XmlSchemaObjectCollection();\r
90                         isCompiled                      = false;\r
91                         items                           = new XmlSchemaObjectCollection();\r
92                         attributeGroups         = new XmlSchemaObjectTable();\r
93                         attributes                      = new XmlSchemaObjectTable();\r
94                         elements                        = new XmlSchemaObjectTable();\r
95                         groups                          = new XmlSchemaObjectTable();\r
96                         notations                       = new XmlSchemaObjectTable();\r
97                         schemaTypes                     = new XmlSchemaObjectTable();\r
98                         idCollection                    = new Hashtable ();\r
99                         namedIdentities                 = new XmlSchemaObjectTable();\r
100                 }\r
101 \r
102                 #region Properties\r
103 \r
104                 [DefaultValue(XmlSchemaForm.None)]\r
105                 [System.Xml.Serialization.XmlAttribute("attributeFormDefault")]\r
106                 public XmlSchemaForm AttributeFormDefault\r
107                 {\r
108                         get{ return attributeFormDefault; }\r
109                         set{ this.attributeFormDefault = value;}\r
110                 }\r
111 \r
112                 [DefaultValue(XmlSchemaDerivationMethod.None)]\r
113                 [System.Xml.Serialization.XmlAttribute("blockDefault")]\r
114                 public XmlSchemaDerivationMethod BlockDefault\r
115                 {\r
116                         get{ return blockDefault;}\r
117                         set{ blockDefault = value;}\r
118                 }\r
119 \r
120                 [DefaultValue(XmlSchemaDerivationMethod.None)]\r
121                 [System.Xml.Serialization.XmlAttribute("finalDefault")]\r
122                 public XmlSchemaDerivationMethod FinalDefault\r
123                 {\r
124                         get{ return finalDefault;}\r
125                         set{ finalDefault = value;}\r
126                 }\r
127 \r
128                 [DefaultValue(XmlSchemaForm.None)]\r
129                 [System.Xml.Serialization.XmlAttribute("elementFormDefault")]\r
130                 public XmlSchemaForm ElementFormDefault\r
131                 {\r
132                         get{ return elementFormDefault;}\r
133                         set{ elementFormDefault = value;}\r
134                 }\r
135 \r
136                 [System.Xml.Serialization.XmlAttribute("targetNamespace")]\r
137                 public string TargetNamespace\r
138                 {\r
139                         get{ return targetNamespace;}\r
140                         set{ targetNamespace = value;}\r
141                 }\r
142 \r
143                 [System.Xml.Serialization.XmlAttribute("version")]\r
144                 public string Version\r
145                 {\r
146                         get{ return version;}\r
147                         set{ version = value;}\r
148                 }\r
149 \r
150                 [XmlElement("include",typeof(XmlSchemaInclude),Namespace="http://www.w3.org/2001/XMLSchema")]\r
151                 [XmlElement("import",typeof(XmlSchemaImport),Namespace="http://www.w3.org/2001/XMLSchema")]\r
152                 [XmlElement("redefine",typeof(XmlSchemaRedefine),Namespace="http://www.w3.org/2001/XMLSchema")]\r
153                 public XmlSchemaObjectCollection Includes\r
154                 {\r
155                         get{ return includes;}\r
156                 }\r
157 \r
158                 [XmlElement("simpleType",typeof(XmlSchemaSimpleType),Namespace="http://www.w3.org/2001/XMLSchema")]\r
159                 [XmlElement("complexType",typeof(XmlSchemaComplexType),Namespace="http://www.w3.org/2001/XMLSchema")]\r
160                 [XmlElement("group",typeof(XmlSchemaGroup),Namespace="http://www.w3.org/2001/XMLSchema")]\r
161                         //Only Schema's attributeGroup has type XmlSchemaAttributeGroup.\r
162                         //Others (complextype, restrictions etc) must have XmlSchemaAttributeGroupRef\r
163                 [XmlElement("attributeGroup",typeof(XmlSchemaAttributeGroup),Namespace="http://www.w3.org/2001/XMLSchema")]\r
164                 [XmlElement("element",typeof(XmlSchemaElement),Namespace="http://www.w3.org/2001/XMLSchema")]\r
165                 [XmlElement("attribute",typeof(XmlSchemaAttribute),Namespace="http://www.w3.org/2001/XMLSchema")]\r
166                 [XmlElement("notation",typeof(XmlSchemaNotation),Namespace="http://www.w3.org/2001/XMLSchema")]\r
167                 [XmlElement("annotation",typeof(XmlSchemaAnnotation),Namespace="http://www.w3.org/2001/XMLSchema")]\r
168                 public XmlSchemaObjectCollection Items\r
169                 {\r
170                         get{ return items;}\r
171                 }\r
172 \r
173                 [XmlIgnore]\r
174                 public bool IsCompiled\r
175                 {\r
176                         get{ return this.CompilationId != Guid.Empty;}\r
177                 }\r
178 \r
179                 [XmlIgnore]\r
180                 public XmlSchemaObjectTable Attributes\r
181                 {\r
182                         get{ return attributes;}\r
183                 }\r
184 \r
185                 [XmlIgnore]\r
186                 public XmlSchemaObjectTable AttributeGroups\r
187                 {\r
188                         get{ return attributeGroups; }\r
189                 }\r
190 \r
191                 [XmlIgnore]\r
192                 public XmlSchemaObjectTable SchemaTypes\r
193                 {\r
194                         get{ return schemaTypes; }\r
195                 }\r
196 \r
197                 [XmlIgnore]\r
198                 public XmlSchemaObjectTable Elements\r
199                 {\r
200                         get{ return elements;}\r
201                 }\r
202 \r
203                 [System.Xml.Serialization.XmlAttribute("id")]\r
204                 public string Id\r
205                 {\r
206                         get{ return id;}\r
207                         set{ id = value;}\r
208                 }\r
209 \r
210                 [XmlAnyAttribute]\r
211                 public XmlAttribute[] UnhandledAttributes\r
212                 {\r
213                         get\r
214                         {\r
215                                 if(unhandledAttributeList != null)\r
216                                 {\r
217                                         unhandledAttributes = (XmlAttribute[]) unhandledAttributeList.ToArray(typeof(XmlAttribute));\r
218                                         unhandledAttributeList = null;\r
219                                 }\r
220                                 return unhandledAttributes;\r
221                         }\r
222                         set\r
223                         {\r
224                                 unhandledAttributes = value;\r
225                                 unhandledAttributeList = null;\r
226                         }\r
227                 }\r
228 \r
229                 [XmlIgnore]\r
230                 public XmlSchemaObjectTable Groups\r
231                 {\r
232                         get{ return groups;}\r
233                 }\r
234 \r
235                 [XmlIgnore]\r
236                 public XmlSchemaObjectTable Notations\r
237                 {\r
238                         get{ return notations;}\r
239                 }\r
240 \r
241                 internal Hashtable IDCollection\r
242                 {\r
243                         get { return idCollection; }\r
244                 }\r
245 \r
246                 internal XmlSchemaObjectTable NamedIdentities\r
247                 {\r
248                         get { return namedIdentities; }\r
249                 }\r
250 \r
251                 internal XmlSchemaCollection Schemas\r
252                 {\r
253                         get { return schemas; }\r
254                 }\r
255                 #endregion\r
256 \r
257                 #region Compile\r
258 \r
259                 // Methods\r
260                 /// <summary>\r
261                 /// This compile method does two things:\r
262                 /// 1. It compiles and fills the PSVI dataset\r
263                 /// 2. Validates the schema by calling Validate method.\r
264                 /// Every XmlSchemaObject has a Compile Method which gets called.\r
265                 /// </summary>\r
266                 /// <remarks>\r
267                 ///             1. blockDefault must be one of #all | List of (extension | restriction | substitution)\r
268                 ///             2. finalDefault must be one of (#all | List of (extension | restriction| union| list))\r
269                 ///             3. id must be of type ID\r
270                 ///             4. targetNamespace should be any uri\r
271                 ///             5. version should be a normalizedString\r
272                 ///             6. xml:lang should be a language\r
273                 /// </remarks>\r
274                 public void Compile (ValidationEventHandler handler)\r
275                 {\r
276                         Compile (handler, new XmlUrlResolver ());\r
277                 }\r
278 \r
279 #if NET_1_0\r
280                 internal void Compile (ValidationEventHandler handler, XmlResolver resolver)\r
281 #else\r
282                 public void Compile (ValidationEventHandler handler, XmlResolver resolver)\r
283 #endif\r
284                 {\r
285                         Compile (handler, new Stack (), this, null, resolver);\r
286                         isCompiled = true;\r
287                 }\r
288 \r
289                 internal void Compile (ValidationEventHandler handler, XmlSchemaCollection col, XmlResolver resolver)\r
290                 {\r
291                         Compile (handler, new Stack (), this, col, resolver);\r
292                 }\r
293 \r
294                 private void Compile (ValidationEventHandler handler, Stack schemaLocationStack, XmlSchema rootSchema, XmlSchemaCollection col, XmlResolver resolver)\r
295                 {\r
296                         if (rootSchema != this) {\r
297                                 CompilationId = rootSchema.CompilationId;\r
298                                 schemas = rootSchema.schemas;\r
299                         }\r
300                         else {\r
301                                 schemas = col;\r
302                                 if (schemas == null) {\r
303                                         schemas = new XmlSchemaCollection ();\r
304                                         schemas.SchemaSet.CompilationId = Guid.NewGuid ();\r
305                                 }\r
306                                 CompilationId = schemas.SchemaSet.CompilationId;\r
307                                 this.idCollection.Clear ();\r
308                         }\r
309                         schemas.Add (this);\r
310 \r
311                         attributeGroups.Clear ();\r
312                         attributes.Clear ();\r
313                         elements.Clear ();\r
314                         groups.Clear ();\r
315                         notations.Clear ();\r
316                         schemaTypes.Clear ();\r
317 \r
318                         //1. Union and List are not allowed in block default\r
319                         if(BlockDefault != XmlSchemaDerivationMethod.All)\r
320                         {\r
321                                 if((BlockDefault & XmlSchemaDerivationMethod.List)!=0 )\r
322                                         error(handler, "list is not allowed in blockDefault attribute");\r
323                                 if((BlockDefault & XmlSchemaDerivationMethod.Union)!=0 )\r
324                                         error(handler, "union is not allowed in blockDefault attribute");\r
325                         }\r
326 \r
327                         //2. Substitution is not allowed in finaldefault.\r
328                         if(FinalDefault != XmlSchemaDerivationMethod.All)\r
329                         {\r
330                                 if((FinalDefault & XmlSchemaDerivationMethod.Substitution)!=0 )\r
331                                         error(handler, "substitution is not allowed in finalDefault attribute");\r
332                         }\r
333 \r
334                         //3. id must be of type ID\r
335                         XmlSchemaUtil.CompileID(Id, this, this.IDCollection, handler);\r
336 \r
337                         //4. targetNamespace should be of type anyURI or absent\r
338                         if(TargetNamespace != null)\r
339                         {\r
340                                 if(!XmlSchemaUtil.CheckAnyUri(TargetNamespace))\r
341                                         error(handler, TargetNamespace+" is not a valid value for targetNamespace attribute of schema");\r
342                         }\r
343 \r
344                         //5. version should be of type normalizedString\r
345                         if(!XmlSchemaUtil.CheckNormalizedString(Version))\r
346                                 error(handler, Version + "is not a valid value for version attribute of schema");\r
347 \r
348                         //6. xml:lang must be a language\r
349 //                      if(!XmlSchemaUtil.CheckLanguage(Language))\r
350 //                              error(handler, Language + " is not a valid language");\r
351 \r
352                         // Compile the content of this schema\r
353 \r
354                         compilationItems = new XmlSchemaObjectCollection ();\r
355                         for (int i = 0; i < Items.Count; i++)\r
356                                 compilationItems.Add (Items [i]);\r
357                         if (this == rootSchema)\r
358                                 handledUris = new Hashtable ();\r
359 \r
360                         // First, we run into inclusion schemas to collect \r
361                         // compilation target items into compiledItems.\r
362                         for (int i = 0; i < Includes.Count; i++) {\r
363                                 XmlSchemaExternal ext = Includes [i] as XmlSchemaExternal;\r
364                                 if (ext != null) {\r
365                                         if (ext.SchemaLocation == null) \r
366                                                 continue;\r
367                                         Stream stream = null;\r
368                                         string url = null;\r
369                                         if (resolver != null) {\r
370                                                 url = GetResolvedUri (resolver, ext.SchemaLocation);\r
371                                                 if (schemaLocationStack.Contains (url)) {\r
372                                                         error(handler, "Nested inclusion was found: " + url);\r
373                                                         // must skip this inclusion\r
374                                                         continue;\r
375                                                 }\r
376                                                 if (rootSchema.handledUris.Contains (url))\r
377                                                         // This schema is already handled, so simply skip (otherwise, duplicate definition errrors occur.\r
378                                                         continue;\r
379                                                 rootSchema.handledUris.Add (url, url);\r
380                                                 try {\r
381                                                         stream = resolver.GetEntity (new Uri (url), null, typeof (Stream)) as Stream;\r
382                                                 } catch (Exception) {\r
383                                                 // LAMESPEC: This is not good way to handle errors, but since we cannot know what kind of XmlResolver will come, so there are no mean to avoid this ugly catch.\r
384                                                         warn (handler, "Could not resolve schema location URI: " + url);\r
385                                                         stream = null;\r
386                                                 }\r
387                                         }\r
388 \r
389                                         // Process redefinition children in advance.\r
390                                         XmlSchemaRedefine redefine = Includes [i] as XmlSchemaRedefine;\r
391                                         if (redefine != null) {\r
392                                                 for (int j = 0; j < redefine.Items.Count; j++) {\r
393                                                         XmlSchemaObject redefinedObj = redefine.Items [j];\r
394                                                         redefinedObj.isRedefinedComponent = true;\r
395                                                         redefinedObj.isRedefineChild = true;\r
396                                                         if (redefinedObj is XmlSchemaType ||\r
397                                                                 redefinedObj is XmlSchemaGroup ||\r
398                                                                 redefinedObj is XmlSchemaAttributeGroup)\r
399                                                                 compilationItems.Add (redefinedObj);\r
400                                                         else\r
401                                                                 error (handler, "Redefinition is only allowed to simpleType, complexType, group and attributeGroup.");\r
402                                                 }\r
403                                         }\r
404 \r
405                                         XmlSchema includedSchema = null;\r
406                                         if (stream == null) {\r
407                                                 // It is missing schema components.\r
408                                                 missedSubComponents = true;\r
409                                                 continue;\r
410                                         } else {\r
411                                                 schemaLocationStack.Push (url);\r
412                                                 XmlTextReader xtr = null;\r
413                                                 try {\r
414                                                         xtr = new XmlTextReader (url, stream, nameTable);\r
415                                                         includedSchema = XmlSchema.Read (xtr, handler);\r
416                                                 } finally {\r
417                                                         if (xtr != null)\r
418                                                                 xtr.Close ();\r
419                                                 }\r
420                                                 includedSchema.schemas = schemas;\r
421                                         }\r
422 \r
423                                         // Set - actual - target namespace for the included schema * before compilation*.\r
424                                         XmlSchemaImport import = ext as XmlSchemaImport;\r
425                                         if (import != null) {\r
426                                                 if (TargetNamespace == includedSchema.TargetNamespace) {\r
427                                                         error (handler, "Target namespace must be different from that of included schema.");\r
428                                                         continue;\r
429                                                 } else if (includedSchema.TargetNamespace != import.Namespace) {\r
430                                                         error (handler, "Attribute namespace and its importing schema's target namespace must be the same.");\r
431                                                         continue;\r
432                                                 }\r
433                                         } else {\r
434                                                 if (TargetNamespace == null && \r
435                                                         includedSchema.TargetNamespace != null) {\r
436                                                         error (handler, "Target namespace is required to include a schema which has its own target namespace");\r
437                                                         continue;\r
438                                                 }\r
439                                                 else if (TargetNamespace != null && \r
440                                                         includedSchema.TargetNamespace == null)\r
441                                                         includedSchema.TargetNamespace = TargetNamespace;\r
442                                         }\r
443 \r
444                                         // Compile included schema.\r
445                                         includedSchema.idCollection = this.IDCollection;\r
446                                         includedSchema.Compile (handler, schemaLocationStack, rootSchema, col, resolver);\r
447                                         schemaLocationStack.Pop ();\r
448 \r
449                                         if (import != null)\r
450                                                 rootSchema.schemas.Add (includedSchema);\r
451 \r
452                                         // Note that we use compiled items. Items\r
453                                         // may not exist in Items, since included\r
454                                         // schema also includes another schemas.\r
455                                         foreach (DictionaryEntry entry in includedSchema.Attributes)\r
456                                                 compilationItems.Add ((XmlSchemaObject) entry.Value);\r
457                                         foreach (DictionaryEntry entry in includedSchema.Elements)\r
458                                                 compilationItems.Add ((XmlSchemaObject) entry.Value);\r
459                                         foreach (DictionaryEntry entry in includedSchema.SchemaTypes)\r
460                                                 compilationItems.Add ((XmlSchemaObject) entry.Value);\r
461                                         foreach (DictionaryEntry entry in includedSchema.AttributeGroups)\r
462                                                 compilationItems.Add ((XmlSchemaObject) entry.Value);\r
463                                         foreach (DictionaryEntry entry in includedSchema.Groups)\r
464                                                 compilationItems.Add ((XmlSchemaObject) entry.Value);\r
465                                         foreach (DictionaryEntry entry in includedSchema.Notations)\r
466                                                 compilationItems.Add ((XmlSchemaObject) entry.Value);\r
467                                 }\r
468                                 else\r
469                                 {\r
470                                         error(handler,"Object of Type "+Includes [i].GetType().Name+" is not valid in Includes Property of XmlSchema");\r
471                                 }\r
472                         }\r
473 \r
474                         // Compilation phase.\r
475                         // At least each Compile() must gives unique (qualified) name for each component.\r
476                         // It also checks self-resolvable properties correct.\r
477                         // Post compilation schema information contribution is not required here.\r
478                         // It should be done by Validate().\r
479                         for (int i = 0; i < compilationItems.Count; i++) {\r
480                                 XmlSchemaObject obj = compilationItems [i];\r
481                                 if(obj is XmlSchemaAnnotation)\r
482                                 {\r
483                                         int numerr = ((XmlSchemaAnnotation)obj).Compile(handler, this);\r
484                                         errorCount += numerr;\r
485                                 }\r
486                                 else if(obj is XmlSchemaAttribute)\r
487                                 {\r
488                                         XmlSchemaAttribute attr = (XmlSchemaAttribute) obj;\r
489                                         attr.ParentIsSchema = true;\r
490                                         int numerr = attr.Compile(handler, this);\r
491                                         errorCount += numerr;\r
492                                         if(numerr == 0)\r
493                                         {\r
494                                                 if (!attr.IsComplied (this.CompilationId))\r
495                                                         schemas.SchemaSet.GlobalAttributes.Add (attr.QualifiedName, attr);\r
496                                                 XmlSchemaUtil.AddToTable (Attributes, attr, attr.QualifiedName, handler);\r
497                                         }\r
498                                 }\r
499                                 else if(obj is XmlSchemaAttributeGroup)\r
500                                 {\r
501                                         XmlSchemaAttributeGroup attrgrp = (XmlSchemaAttributeGroup) obj;\r
502                                         int numerr = attrgrp.Compile(handler, this);\r
503                                         errorCount += numerr;\r
504                                         if(numerr == 0)\r
505                                         {\r
506                                                 XmlSchemaUtil.AddToTable (AttributeGroups, attrgrp, attrgrp.QualifiedName, handler);\r
507                                         }\r
508                                 }\r
509                                 else if(obj is XmlSchemaComplexType)\r
510                                 {\r
511                                         XmlSchemaComplexType ctype = (XmlSchemaComplexType) obj;\r
512                                         ctype.ParentIsSchema = true;\r
513                                         int numerr = ctype.Compile(handler, this);\r
514                                         errorCount += numerr;\r
515                                         if(numerr == 0)\r
516                                         {\r
517                                                 if (!ctype.IsComplied (this.CompilationId))\r
518                                                         schemas.SchemaSet.GlobalTypes.Add (ctype.QualifiedName, ctype);\r
519                                                 XmlSchemaUtil.AddToTable (schemaTypes, ctype, ctype.QualifiedName, handler);\r
520                                         }\r
521                                 }\r
522                                 else if(obj is XmlSchemaSimpleType)\r
523                                 {\r
524                                         XmlSchemaSimpleType stype = (XmlSchemaSimpleType) obj;\r
525                                         stype.islocal = false; //This simple type is toplevel\r
526                                         int numerr = stype.Compile(handler, this);\r
527                                         errorCount += numerr;\r
528                                         if(numerr == 0)\r
529                                         {\r
530                                                 if (!stype.IsComplied (this.CompilationId))\r
531                                                         schemas.SchemaSet.GlobalTypes.Add (stype.QualifiedName, stype);\r
532                                                 XmlSchemaUtil.AddToTable (SchemaTypes, stype, stype.QualifiedName, handler);\r
533                                         }\r
534                                 }\r
535                                 else if(obj is XmlSchemaElement)\r
536                                 {\r
537                                         XmlSchemaElement elem = (XmlSchemaElement) obj;\r
538                                         elem.parentIsSchema = true;\r
539                                         int numerr = elem.Compile(handler, this);\r
540                                         errorCount += numerr;\r
541                                         if(numerr == 0)\r
542                                         {\r
543                                                 if (!elem.IsComplied (this.CompilationId))\r
544                                                         schemas.SchemaSet.GlobalElements.Add (elem.QualifiedName, elem);\r
545                                                 XmlSchemaUtil.AddToTable (Elements, elem, elem.QualifiedName, handler);\r
546                                         }\r
547                                 }\r
548                                 else if(obj is XmlSchemaGroup)\r
549                                 {\r
550                                         XmlSchemaGroup grp = (XmlSchemaGroup) obj;\r
551                                         int numerr = grp.Compile(handler, this);\r
552                                         errorCount += numerr;\r
553                                         if(numerr == 0)\r
554                                         {\r
555                                                 XmlSchemaUtil.AddToTable (Groups, grp, grp.QualifiedName, handler);\r
556                                         }\r
557                                 }\r
558                                 else if(obj is XmlSchemaNotation)\r
559                                 {\r
560                                         XmlSchemaNotation ntn = (XmlSchemaNotation) obj;\r
561                                         int numerr = ntn.Compile(handler, this);\r
562                                         errorCount += numerr;\r
563                                         if(numerr == 0)\r
564                                         {\r
565                                                 XmlSchemaUtil.AddToTable (Notations, ntn, ntn.QualifiedName, handler);\r
566                                         }\r
567                                 }\r
568                                 else\r
569                                 {\r
570                                         ValidationHandler.RaiseValidationEvent (\r
571                                                 handler, null,\r
572                                                 "Object of Type "+obj.GetType().Name+" is not valid in Item Property of Schema",\r
573                                                 null, this, null, XmlSeverityType.Error);\r
574                                 }\r
575                         }\r
576 \r
577                         if (rootSchema == this)\r
578                                 Validate(handler);\r
579                 }\r
580 \r
581                 private string GetResolvedUri (XmlResolver resolver, string relativeUri)\r
582                 {\r
583                         Uri baseUri = null;\r
584                         if (this.SourceUri != null && this.SourceUri != String.Empty)\r
585                                 baseUri = new Uri (this.SourceUri);\r
586                         return resolver.ResolveUri (baseUri, relativeUri).ToString ();\r
587                 }\r
588 \r
589                 internal bool IsNamespaceAbsent (string ns)\r
590                 {\r
591                         return this.schemas [ns] == null;\r
592                 }\r
593 \r
594                 #endregion\r
595 \r
596                 private void Validate(ValidationEventHandler handler)\r
597                 {\r
598                         ValidationId = CompilationId;\r
599 \r
600                         // Firstly Element needs to be filled their substitution group info\r
601                         foreach(XmlSchemaElement elem in Elements.Values)\r
602                                 elem.FillSubstitutionElementInfo ();\r
603 \r
604                         // Validate\r
605                         foreach(XmlSchemaAttribute attr in Attributes.Values)\r
606                         {\r
607                                 errorCount += attr.Validate(handler, this);\r
608                         }\r
609                         foreach(XmlSchemaAttributeGroup attrgrp in AttributeGroups.Values)\r
610                         {\r
611                                 errorCount += attrgrp.Validate(handler, this);\r
612                         }\r
613                         foreach(XmlSchemaType type in SchemaTypes.Values)\r
614                         {\r
615                                 errorCount += type.Validate(handler, this);\r
616                         }\r
617                         foreach(XmlSchemaElement elem in Elements.Values)\r
618                         {\r
619                                 errorCount += elem.Validate(handler, this);\r
620                         }\r
621                         foreach(XmlSchemaGroup grp in Groups.Values)\r
622                         {\r
623                                 errorCount += grp.Validate(handler, this);\r
624                         }\r
625                         foreach(XmlSchemaNotation ntn in Notations.Values)\r
626                         {\r
627                                 errorCount += ntn.Validate(handler, this);\r
628                         }\r
629                 }\r
630 \r
631                 #region Read\r
632 \r
633                 // We cannot use xml deserialization, since it does not provide line info, qname context, and so on.\r
634                 public static XmlSchema Read (TextReader reader, ValidationEventHandler validationEventHandler)\r
635                 {\r
636                         return Read (new XmlTextReader (reader),validationEventHandler);\r
637                 }\r
638                 public static XmlSchema Read (Stream stream, ValidationEventHandler validationEventHandler)\r
639                 {\r
640                         return Read (new XmlTextReader (stream),validationEventHandler);\r
641                 }\r
642 \r
643                 public static XmlSchema Read (XmlReader rdr, ValidationEventHandler validationEventHandler)\r
644                 {\r
645                         XmlSchemaReader reader = new XmlSchemaReader (rdr, validationEventHandler);\r
646 \r
647                         if (reader.ReadState == ReadState.Initial)\r
648                                 reader.ReadNextElement ();\r
649 \r
650                         int startDepth = reader.Depth;\r
651 \r
652                         do\r
653                         {\r
654                                 switch(reader.NodeType)\r
655                                 {\r
656                                 case XmlNodeType.Element:\r
657                                         if(reader.LocalName == "schema")\r
658                                         {\r
659                                                 XmlSchema schema = new XmlSchema ();\r
660                                                 schema.nameTable = rdr.NameTable;\r
661 \r
662                                                 schema.LineNumber = reader.LineNumber;\r
663                                                 schema.LinePosition = reader.LinePosition;\r
664                                                 schema.SourceUri = reader.BaseURI;\r
665 \r
666                                                 ReadAttributes(schema, reader, validationEventHandler);\r
667                                                 //IsEmptyElement does not behave properly if reader is\r
668                                                 //positioned at an attribute.\r
669                                                 reader.MoveToElement();\r
670                                                 if(!reader.IsEmptyElement)\r
671                                                 {\r
672                                                         ReadContent(schema, reader, validationEventHandler);\r
673                                                 }\r
674                                                 else\r
675                                                         rdr.Skip ();\r
676 \r
677                                                 if (rdr.NodeType == XmlNodeType.EndElement)\r
678                                                         rdr.Read ();\r
679                                                 return schema;\r
680                                         }\r
681                                         else\r
682                                                 //Schema can't be generated. Throw an exception\r
683                                                 error (validationEventHandler, "The root element must be schema", null);\r
684                                         break;\r
685                                 default:\r
686                                         error(validationEventHandler, "This should never happen. XmlSchema.Read 1 ",null);\r
687                                         break;\r
688                                 }\r
689                         } while(reader.Depth > startDepth && reader.ReadNextElement());\r
690 \r
691                         // This is thrown regardless of ValidationEventHandler existence.\r
692                         throw new XmlSchemaException ("The top level schema must have namespace " + XmlSchema.Namespace, null);\r
693                 }\r
694 \r
695                 private static void ReadAttributes(XmlSchema schema, XmlSchemaReader reader, ValidationEventHandler h)\r
696                 {\r
697                         Exception ex;\r
698 \r
699                         reader.MoveToElement();\r
700                         while(reader.MoveToNextAttribute())\r
701                         {\r
702                                 switch(reader.Name)\r
703                                 {\r
704                                         case "attributeFormDefault" :\r
705                                                 schema.attributeFormDefault = XmlSchemaUtil.ReadFormAttribute(reader,out ex);\r
706                                                 if(ex != null)\r
707                                                         error(h, reader.Value + " is not a valid value for attributeFormDefault.", ex);\r
708                                                 break;\r
709                                         case "blockDefault" :\r
710                                                 schema.blockDefault = XmlSchemaUtil.ReadDerivationAttribute(reader,out ex, "blockDefault",\r
711                                                         XmlSchemaUtil.ElementBlockAllowed);\r
712                                                 if(ex != null)\r
713                                                         error (h, ex.Message, ex);\r
714                                                 break;\r
715                                         case "elementFormDefault":\r
716                                                 schema.elementFormDefault = XmlSchemaUtil.ReadFormAttribute(reader, out ex);\r
717                                                 if(ex != null)\r
718                                                         error(h, reader.Value + " is not a valid value for elementFormDefault.", ex);\r
719                                                 break;\r
720                                         case "finalDefault":\r
721                                                 schema.finalDefault = XmlSchemaUtil.ReadDerivationAttribute(reader, out ex, "finalDefault",\r
722                                                         XmlSchemaUtil.FinalAllowed);\r
723                                                 if(ex != null)\r
724                                                         error (h, ex.Message , ex);\r
725                                                 break;\r
726                                         case "id":\r
727                                                 schema.id = reader.Value;\r
728                                                 break;\r
729                                         case "targetNamespace":\r
730                                                 schema.targetNamespace = reader.Value;\r
731                                                 break;\r
732                                         case "version":\r
733                                                 schema.version = reader.Value;\r
734                                                 break;\r
735                                         case "xml:lang":\r
736                                                 schema.language = reader.Value;\r
737                                                 break;\r
738                                         default:\r
739                                                 if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)\r
740                                                         error(h, reader.Name + " attribute is not allowed in schema element",null);\r
741                                                 else\r
742                                                 {\r
743                                                         XmlSchemaUtil.ReadUnhandledAttribute(reader,schema);\r
744                                                 }\r
745                                                 break;\r
746                                 }\r
747                         }\r
748                 }\r
749 \r
750                 private static void ReadContent(XmlSchema schema, XmlSchemaReader reader, ValidationEventHandler h)\r
751                 {\r
752                         reader.MoveToElement();\r
753                         if(reader.LocalName != "schema" && reader.NamespaceURI != XmlSchema.Namespace && reader.NodeType != XmlNodeType.Element)\r
754                                 error(h, "UNREACHABLE CODE REACHED: Method: Schema.ReadContent, " + reader.LocalName + ", " + reader.NamespaceURI,null);\r
755 \r
756                         //(include | import | redefine | annotation)*,\r
757                         //((simpleType | complexType | group | attributeGroup | element | attribute | notation | annotation)*\r
758                         int level = 1;\r
759                         while(reader.ReadNextElement())\r
760                         {\r
761                                 if(reader.NodeType == XmlNodeType.EndElement)\r
762                                 {\r
763                                         if(reader.LocalName != xmlname)\r
764                                                 error(h,"Should not happen :2: XmlSchema.Read, name="+reader.Name,null);\r
765                                         break;\r
766                                 }\r
767                                 if(level <= 1)\r
768                                 {\r
769                                         if(reader.LocalName == "include")\r
770                                         {\r
771                                                 XmlSchemaInclude include = XmlSchemaInclude.Read(reader,h);\r
772                                                 if(include != null)\r
773                                                         schema.includes.Add(include);\r
774                                                 continue;\r
775                                         }\r
776                                         if(reader.LocalName == "import")\r
777                                         {\r
778                                                 XmlSchemaImport import = XmlSchemaImport.Read(reader,h);\r
779                                                 if(import != null)\r
780                                                         schema.includes.Add(import);\r
781                                                 continue;\r
782                                         }\r
783                                         if(reader.LocalName == "redefine")\r
784                                         {\r
785                                                 XmlSchemaRedefine redefine = XmlSchemaRedefine.Read(reader,h);\r
786                                                 if(redefine != null)\r
787                                                         schema.includes.Add(redefine);\r
788                                                 continue;\r
789                                         }\r
790                                         if(reader.LocalName == "annotation")\r
791                                         {\r
792                                                 XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);\r
793                                                 if(annotation != null)\r
794                                                         schema.items.Add(annotation);\r
795                                                 continue;\r
796                                         }\r
797                                 }\r
798                                 if(level <=2)\r
799                                 {\r
800                                         level = 2;\r
801                                         if(reader.LocalName == "simpleType")\r
802                                         {\r
803                                                 XmlSchemaSimpleType stype = XmlSchemaSimpleType.Read(reader,h);\r
804                                                 if(stype != null)\r
805                                                         schema.items.Add(stype);\r
806                                                 continue;\r
807                                         }\r
808                                         if(reader.LocalName == "complexType")\r
809                                         {\r
810                                                 XmlSchemaComplexType ctype = XmlSchemaComplexType.Read(reader,h);\r
811                                                 if(ctype != null)\r
812                                                         schema.items.Add(ctype);\r
813                                                 continue;\r
814                                         }\r
815                                         if(reader.LocalName == "group")\r
816                                         {\r
817                                                 XmlSchemaGroup group = XmlSchemaGroup.Read(reader,h);\r
818                                                 if(group != null)\r
819                                                         schema.items.Add(group);\r
820                                                 continue;\r
821                                         }\r
822                                         if(reader.LocalName == "attributeGroup")\r
823                                         {\r
824                                                 XmlSchemaAttributeGroup attributeGroup = XmlSchemaAttributeGroup.Read(reader,h);\r
825                                                 if(attributeGroup != null)\r
826                                                         schema.items.Add(attributeGroup);\r
827                                                 continue;\r
828                                         }\r
829                                         if(reader.LocalName == "element")\r
830                                         {\r
831                                                 XmlSchemaElement element = XmlSchemaElement.Read(reader,h);\r
832                                                 if(element != null)\r
833                                                         schema.items.Add(element);\r
834                                                 continue;\r
835                                         }\r
836                                         if(reader.LocalName == "attribute")\r
837                                         {\r
838                                                 XmlSchemaAttribute attr = XmlSchemaAttribute.Read(reader,h);\r
839                                                 if(attr != null)\r
840                                                         schema.items.Add(attr);\r
841                                                 continue;\r
842                                         }\r
843                                         if(reader.LocalName == "notation")\r
844                                         {\r
845                                                 XmlSchemaNotation notation = XmlSchemaNotation.Read(reader,h);\r
846                                                 if(notation != null)\r
847                                                         schema.items.Add(notation);\r
848                                                 continue;\r
849                                         }\r
850                                         if(reader.LocalName == "annotation")\r
851                                         {\r
852                                                 XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);\r
853                                                 if(annotation != null)\r
854                                                         schema.items.Add(annotation);\r
855                                                 continue;\r
856                                         }\r
857                                 }\r
858                                 reader.RaiseInvalidElementError();\r
859                         }\r
860                 }\r
861                 #endregion\r
862 \r
863                 #region write\r
864 \r
865                 public void Write(System.IO.Stream stream)\r
866                 {\r
867                         Write(stream,null);\r
868                 }\r
869                 public void Write(System.IO.TextWriter writer)\r
870                 {\r
871                         Write(writer,null);\r
872                 }\r
873                 public void Write(System.Xml.XmlWriter writer)\r
874                 {\r
875                         Write(writer,null);\r
876                 }\r
877                 public void Write(System.IO.Stream stream, System.Xml.XmlNamespaceManager namespaceManager)\r
878                 {\r
879                         Write(new XmlTextWriter(stream,null),namespaceManager);\r
880                 }\r
881                 public void Write(System.IO.TextWriter writer, System.Xml.XmlNamespaceManager namespaceManager)\r
882                 {\r
883                         XmlTextWriter xwriter = new XmlTextWriter(writer);\r
884                         xwriter.Formatting = Formatting.Indented;\r
885                         Write(xwriter,namespaceManager);\r
886                 }\r
887 \r
888                 public void Write (System.Xml.XmlWriter writer, System.Xml.XmlNamespaceManager namespaceManager)\r
889                 {\r
890                         XmlSerializerNamespaces nss = new XmlSerializerNamespaces ();\r
891 \r
892                         if (namespaceManager != null) {\r
893                                 if (nss == null)\r
894                                         nss = new XmlSerializerNamespaces ();\r
895                                 foreach (string name in namespaceManager) {\r
896                                         //xml and xmlns namespaces are added by default in namespaceManager.\r
897                                         //So we should ignore them\r
898                                         if (name !="xml" && name != "xmlns")\r
899                                                 nss.Add (name, namespaceManager.LookupNamespace (name));\r
900                                 }\r
901                         }\r
902 \r
903                         if (Namespaces != null && Namespaces.Count > 0) {\r
904                                 nss.Add (String.Empty, XmlSchema.Namespace);\r
905                                 foreach (XmlQualifiedName qn in Namespaces.ToArray ()) {\r
906                                         nss.Add (qn.Name, qn.Namespace);\r
907                                 }\r
908                         }\r
909 \r
910                         if (nss.Count == 0) {\r
911                                 // Add the xml schema namespace. (It is done \r
912                                 // only when no entry exists in Namespaces).\r
913                                 nss.Add ("xs", XmlSchema.Namespace);\r
914                                 if (TargetNamespace != null)\r
915                                         nss.Add ("tns", TargetNamespace);\r
916                         }\r
917 \r
918 //                      XmlSerializer xser = new XmlSerializer (typeof (XmlSchema));\r
919 //                      xser.Serialize (writer, this, nss);\r
920                         XmlSchemaSerializer xser = new XmlSchemaSerializer ();\r
921                         xser.Serialize (writer, this, nss);\r
922                         writer.Flush();\r
923                 }\r
924                 #endregion\r
925         }\r
926
927         class XmlSchemaSerializer : XmlSerializer\r
928         {\r
929                 protected override void Serialize (object o, XmlSerializationWriter writer)\r
930                 {\r
931                         XmlSchemaSerializationWriter w = writer as XmlSchemaSerializationWriter;\r
932                         w.WriteRoot_XmlSchema ((XmlSchema) o);\r
933                 }\r
934 \r
935                 protected override XmlSerializationWriter CreateWriter ()\r
936                 {\r
937                         return new XmlSchemaSerializationWriter ();\r
938                 }\r
939         }\r
940 }