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