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