This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[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                                                         // Just skip nested inclusion. \r
373                                                         // The spec is "carefully written"\r
374                                                         // not to handle it as an error.\r
375         //                                              error (handler, "Nested inclusion was found: " + url);\r
376                                                         // must skip this inclusion\r
377                                                         continue;\r
378                                                 }\r
379                                                 if (rootSchema.handledUris.Contains (url))\r
380                                                         // This schema is already handled, so simply skip (otherwise, duplicate definition errrors occur.\r
381                                                         continue;\r
382                                                 rootSchema.handledUris.Add (url, url);\r
383                                                 try {\r
384                                                         stream = resolver.GetEntity (new Uri (url), null, typeof (Stream)) as Stream;\r
385                                                 } catch (Exception) {\r
386                                                 // 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
387                                                         warn (handler, "Could not resolve schema location URI: " + url);\r
388                                                         stream = null;\r
389                                                 }\r
390                                         }\r
391 \r
392                                         // Process redefinition children in advance.\r
393                                         XmlSchemaRedefine redefine = Includes [i] as XmlSchemaRedefine;\r
394                                         if (redefine != null) {\r
395                                                 for (int j = 0; j < redefine.Items.Count; j++) {\r
396                                                         XmlSchemaObject redefinedObj = redefine.Items [j];\r
397                                                         redefinedObj.isRedefinedComponent = true;\r
398                                                         redefinedObj.isRedefineChild = true;\r
399                                                         if (redefinedObj is XmlSchemaType ||\r
400                                                                 redefinedObj is XmlSchemaGroup ||\r
401                                                                 redefinedObj is XmlSchemaAttributeGroup)\r
402                                                                 compilationItems.Add (redefinedObj);\r
403                                                         else\r
404                                                                 error (handler, "Redefinition is only allowed to simpleType, complexType, group and attributeGroup.");\r
405                                                 }\r
406                                         }\r
407 \r
408                                         XmlSchema includedSchema = null;\r
409                                         if (stream == null) {\r
410                                                 // It is missing schema components.\r
411                                                 missedSubComponents = true;\r
412                                                 continue;\r
413                                         } else {\r
414                                                 schemaLocationStack.Push (url);\r
415                                                 XmlTextReader xtr = null;\r
416                                                 try {\r
417                                                         xtr = new XmlTextReader (url, stream, nameTable);\r
418                                                         includedSchema = XmlSchema.Read (xtr, handler);\r
419                                                 } finally {\r
420                                                         if (xtr != null)\r
421                                                                 xtr.Close ();\r
422                                                 }\r
423                                                 includedSchema.schemas = schemas;\r
424                                         }\r
425 \r
426                                         // Set - actual - target namespace for the included schema * before compilation*.\r
427                                         XmlSchemaImport import = ext as XmlSchemaImport;\r
428                                         if (import != null) {\r
429                                                 if (TargetNamespace == includedSchema.TargetNamespace) {\r
430                                                         error (handler, "Target namespace must be different from that of included schema.");\r
431                                                         continue;\r
432                                                 } else if (includedSchema.TargetNamespace != import.Namespace) {\r
433                                                         error (handler, "Attribute namespace and its importing schema's target namespace must be the same.");\r
434                                                         continue;\r
435                                                 }\r
436                                         } else {\r
437                                                 if (TargetNamespace == null && \r
438                                                         includedSchema.TargetNamespace != null) {\r
439                                                         error (handler, "Target namespace is required to include a schema which has its own target namespace");\r
440                                                         continue;\r
441                                                 }\r
442                                                 else if (TargetNamespace != null && \r
443                                                         includedSchema.TargetNamespace == null)\r
444                                                         includedSchema.TargetNamespace = TargetNamespace;\r
445                                         }\r
446 \r
447                                         // Compile included schema.\r
448                                         includedSchema.idCollection = this.IDCollection;\r
449                                         includedSchema.Compile (handler, schemaLocationStack, rootSchema, col, resolver);\r
450                                         schemaLocationStack.Pop ();\r
451 \r
452                                         if (import != null)\r
453                                                 rootSchema.schemas.Add (includedSchema);\r
454 \r
455                                         // Note that we use compiled items. Items\r
456                                         // may not exist in Items, since included\r
457                                         // schema also includes another schemas.\r
458                                         foreach (DictionaryEntry entry in includedSchema.Attributes)\r
459                                                 compilationItems.Add ((XmlSchemaObject) entry.Value);\r
460                                         foreach (DictionaryEntry entry in includedSchema.Elements)\r
461                                                 compilationItems.Add ((XmlSchemaObject) entry.Value);\r
462                                         foreach (DictionaryEntry entry in includedSchema.SchemaTypes)\r
463                                                 compilationItems.Add ((XmlSchemaObject) entry.Value);\r
464                                         foreach (DictionaryEntry entry in includedSchema.AttributeGroups)\r
465                                                 compilationItems.Add ((XmlSchemaObject) entry.Value);\r
466                                         foreach (DictionaryEntry entry in includedSchema.Groups)\r
467                                                 compilationItems.Add ((XmlSchemaObject) entry.Value);\r
468                                         foreach (DictionaryEntry entry in includedSchema.Notations)\r
469                                                 compilationItems.Add ((XmlSchemaObject) entry.Value);\r
470                                 }\r
471                                 else\r
472                                 {\r
473                                         error(handler,"Object of Type "+Includes [i].GetType().Name+" is not valid in Includes Property of XmlSchema");\r
474                                 }\r
475                         }\r
476 \r
477                         // Compilation phase.\r
478                         // At least each Compile() must gives unique (qualified) name for each component.\r
479                         // It also checks self-resolvable properties correct.\r
480                         // Post compilation schema information contribution is not required here.\r
481                         // It should be done by Validate().\r
482                         for (int i = 0; i < compilationItems.Count; i++) {\r
483                                 XmlSchemaObject obj = compilationItems [i];\r
484                                 if(obj is XmlSchemaAnnotation)\r
485                                 {\r
486                                         int numerr = ((XmlSchemaAnnotation)obj).Compile(handler, this);\r
487                                         errorCount += numerr;\r
488                                 }\r
489                                 else if(obj is XmlSchemaAttribute)\r
490                                 {\r
491                                         XmlSchemaAttribute attr = (XmlSchemaAttribute) obj;\r
492                                         attr.ParentIsSchema = true;\r
493                                         int numerr = attr.Compile(handler, this);\r
494                                         errorCount += numerr;\r
495                                         if(numerr == 0)\r
496                                         {\r
497                                                 if (!attr.IsComplied (this.CompilationId))\r
498                                                         schemas.SchemaSet.GlobalAttributes.Add (attr.QualifiedName, attr);\r
499                                                 XmlSchemaUtil.AddToTable (Attributes, attr, attr.QualifiedName, handler);\r
500                                         }\r
501                                 }\r
502                                 else if(obj is XmlSchemaAttributeGroup)\r
503                                 {\r
504                                         XmlSchemaAttributeGroup attrgrp = (XmlSchemaAttributeGroup) obj;\r
505                                         int numerr = attrgrp.Compile(handler, this);\r
506                                         errorCount += numerr;\r
507                                         if(numerr == 0)\r
508                                         {\r
509                                                 XmlSchemaUtil.AddToTable (AttributeGroups, attrgrp, attrgrp.QualifiedName, handler);\r
510                                         }\r
511                                 }\r
512                                 else if(obj is XmlSchemaComplexType)\r
513                                 {\r
514                                         XmlSchemaComplexType ctype = (XmlSchemaComplexType) obj;\r
515                                         ctype.ParentIsSchema = true;\r
516                                         int numerr = ctype.Compile(handler, this);\r
517                                         errorCount += numerr;\r
518                                         if(numerr == 0)\r
519                                         {\r
520                                                 if (!ctype.IsComplied (this.CompilationId))\r
521                                                         schemas.SchemaSet.GlobalTypes.Add (ctype.QualifiedName, ctype);\r
522                                                 XmlSchemaUtil.AddToTable (schemaTypes, ctype, ctype.QualifiedName, handler);\r
523                                         }\r
524                                 }\r
525                                 else if(obj is XmlSchemaSimpleType)\r
526                                 {\r
527                                         XmlSchemaSimpleType stype = (XmlSchemaSimpleType) obj;\r
528                                         stype.islocal = false; //This simple type is toplevel\r
529                                         int numerr = stype.Compile(handler, this);\r
530                                         errorCount += numerr;\r
531                                         if(numerr == 0)\r
532                                         {\r
533                                                 if (!stype.IsComplied (this.CompilationId))\r
534                                                         schemas.SchemaSet.GlobalTypes.Add (stype.QualifiedName, stype);\r
535                                                 XmlSchemaUtil.AddToTable (SchemaTypes, stype, stype.QualifiedName, handler);\r
536                                         }\r
537                                 }\r
538                                 else if(obj is XmlSchemaElement)\r
539                                 {\r
540                                         XmlSchemaElement elem = (XmlSchemaElement) obj;\r
541                                         elem.parentIsSchema = true;\r
542                                         int numerr = elem.Compile(handler, this);\r
543                                         errorCount += numerr;\r
544                                         if(numerr == 0)\r
545                                         {\r
546                                                 if (!elem.IsComplied (this.CompilationId))\r
547                                                         schemas.SchemaSet.GlobalElements.Add (elem.QualifiedName, elem);\r
548                                                 XmlSchemaUtil.AddToTable (Elements, elem, elem.QualifiedName, handler);\r
549                                         }\r
550                                 }\r
551                                 else if(obj is XmlSchemaGroup)\r
552                                 {\r
553                                         XmlSchemaGroup grp = (XmlSchemaGroup) obj;\r
554                                         int numerr = grp.Compile(handler, this);\r
555                                         errorCount += numerr;\r
556                                         if(numerr == 0)\r
557                                         {\r
558                                                 XmlSchemaUtil.AddToTable (Groups, grp, grp.QualifiedName, handler);\r
559                                         }\r
560                                 }\r
561                                 else if(obj is XmlSchemaNotation)\r
562                                 {\r
563                                         XmlSchemaNotation ntn = (XmlSchemaNotation) obj;\r
564                                         int numerr = ntn.Compile(handler, this);\r
565                                         errorCount += numerr;\r
566                                         if(numerr == 0)\r
567                                         {\r
568                                                 XmlSchemaUtil.AddToTable (Notations, ntn, ntn.QualifiedName, handler);\r
569                                         }\r
570                                 }\r
571                                 else\r
572                                 {\r
573                                         ValidationHandler.RaiseValidationEvent (\r
574                                                 handler, null,\r
575                                                 "Object of Type "+obj.GetType().Name+" is not valid in Item Property of Schema",\r
576                                                 null, this, null, XmlSeverityType.Error);\r
577                                 }\r
578                         }\r
579 \r
580                         if (rootSchema == this)\r
581                                 Validate(handler);\r
582                 }\r
583 \r
584                 private string GetResolvedUri (XmlResolver resolver, string relativeUri)\r
585                 {\r
586                         Uri baseUri = null;\r
587                         if (this.SourceUri != null && this.SourceUri != String.Empty)\r
588                                 baseUri = new Uri (this.SourceUri);\r
589                         return resolver.ResolveUri (baseUri, relativeUri).ToString ();\r
590                 }\r
591 \r
592                 internal bool IsNamespaceAbsent (string ns)\r
593                 {\r
594                         return this.schemas [ns] == null;\r
595                 }\r
596 \r
597                 #endregion\r
598 \r
599                 private void Validate(ValidationEventHandler handler)\r
600                 {\r
601                         ValidationId = CompilationId;\r
602 \r
603                         // Firstly Element needs to be filled their substitution group info\r
604                         foreach(XmlSchemaElement elem in Elements.Values)\r
605                                 elem.FillSubstitutionElementInfo ();\r
606 \r
607                         // Validate\r
608                         foreach(XmlSchemaAttribute attr in Attributes.Values)\r
609                         {\r
610                                 errorCount += attr.Validate(handler, this);\r
611                         }\r
612                         foreach(XmlSchemaAttributeGroup attrgrp in AttributeGroups.Values)\r
613                         {\r
614                                 errorCount += attrgrp.Validate(handler, this);\r
615                         }\r
616                         foreach(XmlSchemaType type in SchemaTypes.Values)\r
617                         {\r
618                                 errorCount += type.Validate(handler, this);\r
619                         }\r
620                         foreach(XmlSchemaElement elem in Elements.Values)\r
621                         {\r
622                                 errorCount += elem.Validate(handler, this);\r
623                         }\r
624                         foreach(XmlSchemaGroup grp in Groups.Values)\r
625                         {\r
626                                 errorCount += grp.Validate(handler, this);\r
627                         }\r
628                         foreach(XmlSchemaNotation ntn in Notations.Values)\r
629                         {\r
630                                 errorCount += ntn.Validate(handler, this);\r
631                         }\r
632                 }\r
633 \r
634                 #region Read\r
635 \r
636                 // We cannot use xml deserialization, since it does not provide line info, qname context, and so on.\r
637                 public static XmlSchema Read (TextReader reader, ValidationEventHandler validationEventHandler)\r
638                 {\r
639                         return Read (new XmlTextReader (reader),validationEventHandler);\r
640                 }\r
641                 public static XmlSchema Read (Stream stream, ValidationEventHandler validationEventHandler)\r
642                 {\r
643                         return Read (new XmlTextReader (stream),validationEventHandler);\r
644                 }\r
645 \r
646                 public static XmlSchema Read (XmlReader rdr, ValidationEventHandler validationEventHandler)\r
647                 {\r
648                         XmlSchemaReader reader = new XmlSchemaReader (rdr, validationEventHandler);\r
649 \r
650                         if (reader.ReadState == ReadState.Initial)\r
651                                 reader.ReadNextElement ();\r
652 \r
653                         int startDepth = reader.Depth;\r
654 \r
655                         do\r
656                         {\r
657                                 switch(reader.NodeType)\r
658                                 {\r
659                                 case XmlNodeType.Element:\r
660                                         if(reader.LocalName == "schema")\r
661                                         {\r
662                                                 XmlSchema schema = new XmlSchema ();\r
663                                                 schema.nameTable = rdr.NameTable;\r
664 \r
665                                                 schema.LineNumber = reader.LineNumber;\r
666                                                 schema.LinePosition = reader.LinePosition;\r
667                                                 schema.SourceUri = reader.BaseURI;\r
668 \r
669                                                 ReadAttributes(schema, reader, validationEventHandler);\r
670                                                 //IsEmptyElement does not behave properly if reader is\r
671                                                 //positioned at an attribute.\r
672                                                 reader.MoveToElement();\r
673                                                 if(!reader.IsEmptyElement)\r
674                                                 {\r
675                                                         ReadContent(schema, reader, validationEventHandler);\r
676                                                 }\r
677                                                 else\r
678                                                         rdr.Skip ();\r
679 \r
680                                                 if (rdr.NodeType == XmlNodeType.EndElement)\r
681                                                         rdr.Read ();\r
682                                                 return schema;\r
683                                         }\r
684                                         else\r
685                                                 //Schema can't be generated. Throw an exception\r
686                                                 error (validationEventHandler, "The root element must be schema", null);\r
687                                         break;\r
688                                 default:\r
689                                         error(validationEventHandler, "This should never happen. XmlSchema.Read 1 ",null);\r
690                                         break;\r
691                                 }\r
692                         } while(reader.Depth > startDepth && reader.ReadNextElement());\r
693 \r
694                         // This is thrown regardless of ValidationEventHandler existence.\r
695                         throw new XmlSchemaException ("The top level schema must have namespace " + XmlSchema.Namespace, null);\r
696                 }\r
697 \r
698                 private static void ReadAttributes(XmlSchema schema, XmlSchemaReader reader, ValidationEventHandler h)\r
699                 {\r
700                         Exception ex;\r
701 \r
702                         reader.MoveToElement();\r
703                         while(reader.MoveToNextAttribute())\r
704                         {\r
705                                 switch(reader.Name)\r
706                                 {\r
707                                         case "attributeFormDefault" :\r
708                                                 schema.attributeFormDefault = XmlSchemaUtil.ReadFormAttribute(reader,out ex);\r
709                                                 if(ex != null)\r
710                                                         error(h, reader.Value + " is not a valid value for attributeFormDefault.", ex);\r
711                                                 break;\r
712                                         case "blockDefault" :\r
713                                                 schema.blockDefault = XmlSchemaUtil.ReadDerivationAttribute(reader,out ex, "blockDefault",\r
714                                                         XmlSchemaUtil.ElementBlockAllowed);\r
715                                                 if(ex != null)\r
716                                                         error (h, ex.Message, ex);\r
717                                                 break;\r
718                                         case "elementFormDefault":\r
719                                                 schema.elementFormDefault = XmlSchemaUtil.ReadFormAttribute(reader, out ex);\r
720                                                 if(ex != null)\r
721                                                         error(h, reader.Value + " is not a valid value for elementFormDefault.", ex);\r
722                                                 break;\r
723                                         case "finalDefault":\r
724                                                 schema.finalDefault = XmlSchemaUtil.ReadDerivationAttribute(reader, out ex, "finalDefault",\r
725                                                         XmlSchemaUtil.FinalAllowed);\r
726                                                 if(ex != null)\r
727                                                         error (h, ex.Message , ex);\r
728                                                 break;\r
729                                         case "id":\r
730                                                 schema.id = reader.Value;\r
731                                                 break;\r
732                                         case "targetNamespace":\r
733                                                 schema.targetNamespace = reader.Value;\r
734                                                 break;\r
735                                         case "version":\r
736                                                 schema.version = reader.Value;\r
737                                                 break;\r
738                                         case "xml:lang":\r
739                                                 schema.language = reader.Value;\r
740                                                 break;\r
741                                         default:\r
742                                                 if((reader.NamespaceURI == "" && reader.Name != "xmlns") || reader.NamespaceURI == XmlSchema.Namespace)\r
743                                                         error(h, reader.Name + " attribute is not allowed in schema element",null);\r
744                                                 else\r
745                                                 {\r
746                                                         XmlSchemaUtil.ReadUnhandledAttribute(reader,schema);\r
747                                                 }\r
748                                                 break;\r
749                                 }\r
750                         }\r
751                 }\r
752 \r
753                 private static void ReadContent(XmlSchema schema, XmlSchemaReader reader, ValidationEventHandler h)\r
754                 {\r
755                         reader.MoveToElement();\r
756                         if(reader.LocalName != "schema" && reader.NamespaceURI != XmlSchema.Namespace && reader.NodeType != XmlNodeType.Element)\r
757                                 error(h, "UNREACHABLE CODE REACHED: Method: Schema.ReadContent, " + reader.LocalName + ", " + reader.NamespaceURI,null);\r
758 \r
759                         //(include | import | redefine | annotation)*,\r
760                         //((simpleType | complexType | group | attributeGroup | element | attribute | notation | annotation)*\r
761                         int level = 1;\r
762                         while(reader.ReadNextElement())\r
763                         {\r
764                                 if(reader.NodeType == XmlNodeType.EndElement)\r
765                                 {\r
766                                         if(reader.LocalName != xmlname)\r
767                                                 error(h,"Should not happen :2: XmlSchema.Read, name="+reader.Name,null);\r
768                                         break;\r
769                                 }\r
770                                 if(level <= 1)\r
771                                 {\r
772                                         if(reader.LocalName == "include")\r
773                                         {\r
774                                                 XmlSchemaInclude include = XmlSchemaInclude.Read(reader,h);\r
775                                                 if(include != null)\r
776                                                         schema.includes.Add(include);\r
777                                                 continue;\r
778                                         }\r
779                                         if(reader.LocalName == "import")\r
780                                         {\r
781                                                 XmlSchemaImport import = XmlSchemaImport.Read(reader,h);\r
782                                                 if(import != null)\r
783                                                         schema.includes.Add(import);\r
784                                                 continue;\r
785                                         }\r
786                                         if(reader.LocalName == "redefine")\r
787                                         {\r
788                                                 XmlSchemaRedefine redefine = XmlSchemaRedefine.Read(reader,h);\r
789                                                 if(redefine != null)\r
790                                                         schema.includes.Add(redefine);\r
791                                                 continue;\r
792                                         }\r
793                                         if(reader.LocalName == "annotation")\r
794                                         {\r
795                                                 XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);\r
796                                                 if(annotation != null)\r
797                                                         schema.items.Add(annotation);\r
798                                                 continue;\r
799                                         }\r
800                                 }\r
801                                 if(level <=2)\r
802                                 {\r
803                                         level = 2;\r
804                                         if(reader.LocalName == "simpleType")\r
805                                         {\r
806                                                 XmlSchemaSimpleType stype = XmlSchemaSimpleType.Read(reader,h);\r
807                                                 if(stype != null)\r
808                                                         schema.items.Add(stype);\r
809                                                 continue;\r
810                                         }\r
811                                         if(reader.LocalName == "complexType")\r
812                                         {\r
813                                                 XmlSchemaComplexType ctype = XmlSchemaComplexType.Read(reader,h);\r
814                                                 if(ctype != null)\r
815                                                         schema.items.Add(ctype);\r
816                                                 continue;\r
817                                         }\r
818                                         if(reader.LocalName == "group")\r
819                                         {\r
820                                                 XmlSchemaGroup group = XmlSchemaGroup.Read(reader,h);\r
821                                                 if(group != null)\r
822                                                         schema.items.Add(group);\r
823                                                 continue;\r
824                                         }\r
825                                         if(reader.LocalName == "attributeGroup")\r
826                                         {\r
827                                                 XmlSchemaAttributeGroup attributeGroup = XmlSchemaAttributeGroup.Read(reader,h);\r
828                                                 if(attributeGroup != null)\r
829                                                         schema.items.Add(attributeGroup);\r
830                                                 continue;\r
831                                         }\r
832                                         if(reader.LocalName == "element")\r
833                                         {\r
834                                                 XmlSchemaElement element = XmlSchemaElement.Read(reader,h);\r
835                                                 if(element != null)\r
836                                                         schema.items.Add(element);\r
837                                                 continue;\r
838                                         }\r
839                                         if(reader.LocalName == "attribute")\r
840                                         {\r
841                                                 XmlSchemaAttribute attr = XmlSchemaAttribute.Read(reader,h);\r
842                                                 if(attr != null)\r
843                                                         schema.items.Add(attr);\r
844                                                 continue;\r
845                                         }\r
846                                         if(reader.LocalName == "notation")\r
847                                         {\r
848                                                 XmlSchemaNotation notation = XmlSchemaNotation.Read(reader,h);\r
849                                                 if(notation != null)\r
850                                                         schema.items.Add(notation);\r
851                                                 continue;\r
852                                         }\r
853                                         if(reader.LocalName == "annotation")\r
854                                         {\r
855                                                 XmlSchemaAnnotation annotation = XmlSchemaAnnotation.Read(reader,h);\r
856                                                 if(annotation != null)\r
857                                                         schema.items.Add(annotation);\r
858                                                 continue;\r
859                                         }\r
860                                 }\r
861                                 reader.RaiseInvalidElementError();\r
862                         }\r
863                 }\r
864                 #endregion\r
865 \r
866                 #region write\r
867 \r
868                 public void Write(System.IO.Stream stream)\r
869                 {\r
870                         Write(stream,null);\r
871                 }\r
872                 public void Write(System.IO.TextWriter writer)\r
873                 {\r
874                         Write(writer,null);\r
875                 }\r
876                 public void Write(System.Xml.XmlWriter writer)\r
877                 {\r
878                         Write(writer,null);\r
879                 }\r
880                 public void Write(System.IO.Stream stream, System.Xml.XmlNamespaceManager namespaceManager)\r
881                 {\r
882                         Write(new XmlTextWriter(stream,null),namespaceManager);\r
883                 }\r
884                 public void Write(System.IO.TextWriter writer, System.Xml.XmlNamespaceManager namespaceManager)\r
885                 {\r
886                         XmlTextWriter xwriter = new XmlTextWriter(writer);\r
887                         xwriter.Formatting = Formatting.Indented;\r
888                         Write(xwriter,namespaceManager);\r
889                 }\r
890 \r
891                 public void Write (System.Xml.XmlWriter writer, System.Xml.XmlNamespaceManager namespaceManager)\r
892                 {\r
893                         XmlSerializerNamespaces nss = new XmlSerializerNamespaces ();\r
894 \r
895                         if (namespaceManager != null) {\r
896                                 if (nss == null)\r
897                                         nss = new XmlSerializerNamespaces ();\r
898                                 foreach (string name in namespaceManager) {\r
899                                         //xml and xmlns namespaces are added by default in namespaceManager.\r
900                                         //So we should ignore them\r
901                                         if (name !="xml" && name != "xmlns")\r
902                                                 nss.Add (name, namespaceManager.LookupNamespace (name));\r
903                                 }\r
904                         }\r
905 \r
906                         if (Namespaces != null && Namespaces.Count > 0) {\r
907                                 nss.Add (String.Empty, XmlSchema.Namespace);\r
908                                 foreach (XmlQualifiedName qn in Namespaces.ToArray ()) {\r
909                                         nss.Add (qn.Name, qn.Namespace);\r
910                                 }\r
911                         }\r
912 \r
913                         if (nss.Count == 0) {\r
914                                 // Add the xml schema namespace. (It is done \r
915                                 // only when no entry exists in Namespaces).\r
916                                 nss.Add ("xs", XmlSchema.Namespace);\r
917                                 if (TargetNamespace != null)\r
918                                         nss.Add ("tns", TargetNamespace);\r
919                         }\r
920 \r
921 //                      XmlSerializer xser = new XmlSerializer (typeof (XmlSchema));\r
922 //                      xser.Serialize (writer, this, nss);\r
923                         XmlSchemaSerializer xser = new XmlSchemaSerializer ();\r
924                         xser.Serialize (writer, this, nss);\r
925                         writer.Flush();\r
926                 }\r
927                 #endregion\r
928         }\r
929
930         class XmlSchemaSerializer : XmlSerializer\r
931         {\r
932                 protected override void Serialize (object o, XmlSerializationWriter writer)\r
933                 {\r
934                         XmlSchemaSerializationWriter w = writer as XmlSchemaSerializationWriter;\r
935                         w.WriteRoot_XmlSchema ((XmlSchema) o);\r
936                 }\r
937 \r
938                 protected override XmlSerializationWriter CreateWriter ()\r
939                 {\r
940                         return new XmlSchemaSerializationWriter ();\r
941                 }\r
942         }\r
943 }