2004-01-13 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / Mono.Xml.Schema / XsdValidatingReader.cs
1 //
2 // Mono.Xml.Schema.XsdValidatingReader.cs
3 //
4 // Author:
5 //      Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
6 //
7 //      (C)2003 Atsushi Enomoto
8 //
9 // Note:
10 //
11 // This class doesn't support set_XmlResolver, since it isn't common to XmlReader interface. 
12 // Try to set that of xml reader which is used to construct this object.
13 //
14 using System;
15 using System.Collections;
16 using System.Collections.Specialized;
17 using System.Text;
18 using System.Xml;
19 using System.Xml.Schema;
20 using Mono.Xml;
21
22 namespace Mono.Xml.Schema
23 {
24         public class XsdValidatingReader : XmlReader, IXmlLineInfo, IHasXmlSchemaInfo, IHasXmlParserContext
25         {
26                 static char [] wsChars = new char [] {' ', '\t', '\n', '\r'};
27
28                 XmlReader reader;
29                 XmlValidatingReader xvReader;
30                 IHasXmlSchemaInfo sourceReaderSchemaInfo;
31                 IXmlLineInfo readerLineInfo;
32                 bool laxElementValidation = true;
33                 bool reportNoValidationError;
34                 XmlSchemaCollection schemas = new XmlSchemaCollection ();
35                 bool namespaces = true;
36
37                 ArrayList idList = new ArrayList ();
38                 ArrayList missingIDReferences = new ArrayList ();
39                 string thisElementId;
40
41                 ArrayList keyTables = new ArrayList ();
42                 ArrayList currentKeyFieldConsumers = new ArrayList ();
43
44                 XsdValidationStateManager stateManager = new XsdValidationStateManager ();
45                 XsdValidationContext context = new XsdValidationContext ();
46                 XsdValidationState childParticleState;
47
48                 int xsiNilDepth = -1;
49                 StringBuilder storedCharacters = new StringBuilder ();
50                 bool shouldValidateCharacters;
51                 int skipValidationDepth = -1;
52
53                 XmlSchemaAttribute [] defaultAttributes = new XmlSchemaAttribute [0];
54                 int currentDefaultAttribute = -1;
55                 XmlQualifiedName currentQName;
56
57                 ArrayList elementQNameStack = new ArrayList ();
58                 bool popContext;
59
60                 // Property Cache.
61                 int nonDefaultAttributeCount;
62                 bool defaultAttributeConsumed;
63
64                 // Validation engine cached object
65                 ArrayList defaultAttributesCache = new ArrayList ();
66                 ArrayList tmpKeyrefPool = new ArrayList ();
67
68 #region .ctor
69                 public XsdValidatingReader (XmlReader reader)
70                         : this (reader, null)
71                 {
72                 }
73                 
74                 public XsdValidatingReader (XmlReader reader, XmlReader validatingReader)
75                 {
76                         this.reader = reader;
77                         xvReader = validatingReader as XmlValidatingReader;
78                         if (xvReader != null) {
79                                 if (xvReader.ValidationType == ValidationType.None)
80                                         reportNoValidationError = true;
81                         }
82                         readerLineInfo = reader as IXmlLineInfo;
83                         sourceReaderSchemaInfo = reader as IHasXmlSchemaInfo;
84                 }
85 #endregion
86                 // Provate Properties
87                 private XmlQualifiedName CurrentQName {
88                         get {
89                                 if (currentQName == null)
90                                         currentQName = new XmlQualifiedName (LocalName, NamespaceURI);
91                                 return currentQName;
92                         }
93                 }
94
95                 internal ArrayList CurrentKeyFieldConsumers {
96                         get { return currentKeyFieldConsumers; }
97                 }
98
99                 // Public Non-overrides
100
101                 public bool Namespaces {
102                         get { return namespaces; }
103                         set { namespaces = value; }
104                 }
105
106                 public XmlReader Reader {
107                         get { return reader; }
108                 }
109
110                 // This should be changed before the first Read() call.
111                 public XmlSchemaCollection Schemas {
112                         get { return schemas; }
113                 }
114
115                 public object SchemaType {
116                         get {
117                                 if (ReadState != ReadState.Interactive)
118                                         return null;
119
120                                 switch (NodeType) {
121                                 case XmlNodeType.Element:
122                                         if (context.ActualType != null)
123                                                 return context.ActualType;
124                                         else if (context.Element != null)
125                                                 return context.Element.ElementType;
126                                         else
127                                                 return SourceReaderSchemaType;
128                                 case XmlNodeType.Attribute:
129                                         XmlSchemaComplexType ct = context.ActualType as XmlSchemaComplexType;
130                                         if (ct != null) {
131                                                 XmlSchemaAttribute attdef = ct.AttributeUses [CurrentQName] as XmlSchemaAttribute;
132                                                 if (attdef != null)
133                                                         return attdef.AttributeType;
134                                         }
135                                         return SourceReaderSchemaType;
136                                 default:
137                                         return SourceReaderSchemaType;
138                                 }
139                         }
140                 }
141
142                 private object SourceReaderSchemaType {
143                         get { return this.sourceReaderSchemaInfo != null ? sourceReaderSchemaInfo.SchemaType : null; }
144                 }
145
146                 // This property is never used in Mono.
147                 public ValidationType ValidationType {
148                         get {
149                                 if (reportNoValidationError)
150                                         return ValidationType.None;
151                                 else
152                                         return ValidationType.Schema;
153                         }
154                 }
155
156                 // It is used only for independent XmlReader use, not for XmlValidatingReader.
157                 public object ReadTypedValue ()
158                 {
159                         XmlSchemaDatatype dt = SchemaType as XmlSchemaDatatype;
160                         XmlSchemaSimpleType st = SchemaType as XmlSchemaSimpleType;
161                         if (st != null)
162                                 dt = st.Datatype;
163                         if (dt == null)
164                                 return null;
165
166                         switch (NodeType) {
167                         case XmlNodeType.Element:
168                                 if (IsEmptyElement)
169                                         return null;
170
171                                 storedCharacters.Length = 0;
172                                 bool loop = true;
173                                 do {
174                                         Read ();
175                                         switch (NodeType) {
176                                         case XmlNodeType.SignificantWhitespace:
177                                         case XmlNodeType.Text:
178                                         case XmlNodeType.CDATA:
179                                                 storedCharacters.Append (Value);
180                                                 break;
181                                         case XmlNodeType.Comment:
182                                                 break;
183                                         default:
184                                                 loop = false;
185                                                 break;
186                                         }
187                                 } while (loop && !EOF);
188                                 return dt.ParseValue (storedCharacters.ToString (), NameTable, ParserContext.NamespaceManager);
189                         case XmlNodeType.Attribute:
190                                 return dt.ParseValue (Value, NameTable, ParserContext.NamespaceManager);
191                         }
192                         return null;
193                 }
194
195                 public ValidationEventHandler ValidationEventHandler;
196
197                 // Public Overrided Properties
198
199                 public override int AttributeCount {
200                         get {
201                                 /*
202                                 if (NodeType == XmlNodeType.Element)
203                                         return attributeCount;
204                                 else if (IsDefault)
205                                         return 0;
206                                 else
207                                         return reader.AttributeCount;
208                                 */
209                                 return nonDefaultAttributeCount + defaultAttributes.Length;
210                         }
211                 }
212
213                 public override string BaseURI {
214                         get { return reader.BaseURI; }
215                 }
216
217                 // If this class is used to implement XmlValidatingReader,
218                 // it should be left to DTDValidatingReader. In other cases,
219                 // it depends on the reader's ability.
220                 public override bool CanResolveEntity {
221                         get { return reader.CanResolveEntity; }
222                 }
223
224                 public override int Depth {
225                         get {
226                                 if (currentDefaultAttribute < 0)
227                                         return reader.Depth;
228                                 if (this.defaultAttributeConsumed)
229                                         return reader.Depth + 2;
230                                 return reader.Depth + 1;
231                         }
232                 }
233
234                 public override bool EOF {
235                         get { return reader.EOF; }
236                 }
237
238                 public override bool HasValue {
239                         get {
240                                 if (currentDefaultAttribute < 0)
241                                         return reader.HasValue;
242                                 return true;
243                         }
244                 }
245
246                 public override bool IsDefault {
247                         get {
248                                 if (currentDefaultAttribute < 0)
249                                         return reader.IsDefault;
250                                 return true;
251                         }
252                 }
253
254                 public override bool IsEmptyElement {
255                         get {
256                                 if (currentDefaultAttribute < 0)
257                                         return reader.IsEmptyElement;
258                                 return false;
259                         }
260                 }
261
262                 public override string this [int i] {
263                         get { return GetAttribute (i); }
264                 }
265
266                 public override string this [string name] {
267                         get { return GetAttribute (name); }
268                 }
269
270                 public override string this [string localName, string ns] {
271                         get { return GetAttribute (localName, ns); }
272                 }
273
274                 int IXmlLineInfo.LineNumber {
275                         get { return readerLineInfo != null ? readerLineInfo.LineNumber : 0; }
276                 }
277
278                 int IXmlLineInfo.LinePosition {
279                         get { return readerLineInfo != null ? readerLineInfo.LinePosition : 0; }
280                 }
281
282                 public override string LocalName {
283                         get {
284                                 if (currentDefaultAttribute < 0)
285                                         return reader.LocalName;
286                                 if (defaultAttributeConsumed)
287                                         return String.Empty;
288                                 return defaultAttributes [currentDefaultAttribute].QualifiedName.Name;
289                         }
290                 }
291
292                 public override string Name {
293                         get {
294                                 if (currentDefaultAttribute < 0)
295                                         return reader.Name;
296                                 if (defaultAttributeConsumed)
297                                         return String.Empty;
298
299                                 XmlQualifiedName qname = defaultAttributes [currentDefaultAttribute].QualifiedName;
300                                 string prefix = Prefix;
301                                 if (prefix == String.Empty)
302                                         return qname.Name;
303                                 else
304                                         return String.Concat (prefix, ":", qname.Name);
305                         }
306                 }
307
308                 public override string NamespaceURI {
309                         get {
310                                 if (currentDefaultAttribute < 0)
311                                         return reader.NamespaceURI;
312                                 if (defaultAttributeConsumed)
313                                         return String.Empty;
314                                 return defaultAttributes [currentDefaultAttribute].QualifiedName.Namespace;
315                         }
316                 }
317
318                 public override XmlNameTable NameTable {
319                         get { return reader.NameTable; }
320                 }
321
322                 public override XmlNodeType NodeType {
323                         get {
324                                 if (currentDefaultAttribute < 0)
325                                         return reader.NodeType;
326                                 if (defaultAttributeConsumed)
327                                         return XmlNodeType.Text;
328                                 return XmlNodeType.Attribute;
329                         }
330                 }
331
332                 public XmlParserContext ParserContext {
333                         get { return XmlSchemaUtil.GetParserContext (reader); }
334                 }
335
336                 public override string Prefix {
337                         get {
338                                 if (currentDefaultAttribute < 0)
339                                         return reader.Prefix;
340                                 if (defaultAttributeConsumed)
341                                         return String.Empty;
342                                 XmlQualifiedName qname = defaultAttributes [currentDefaultAttribute].QualifiedName;
343                                 string prefix = this.ParserContext.NamespaceManager.LookupPrefix (qname.Namespace);
344                                 if (prefix == null)
345                                         return String.Empty;
346                                 else
347                                         return prefix;
348                         }
349                 }
350
351                 public override char QuoteChar {
352                         get { return reader.QuoteChar; }
353                 }
354
355                 public override ReadState ReadState {
356                         get { return reader.ReadState; }
357                 }
358
359                 public override string Value {
360                         get {
361                                 if (currentDefaultAttribute < 0)
362                                         return reader.Value;
363                                 return defaultAttributes [currentDefaultAttribute].ValidatedDefaultValue;
364                         }
365                 }
366
367                 XmlQualifiedName qnameXmlLang = new XmlQualifiedName ("lang", XmlNamespaceManager.XmlnsXml);
368
369                 public override string XmlLang {
370                         get {
371                                 string xmlLang = reader.XmlLang;
372                                 if (xmlLang != null)
373                                         return xmlLang;
374                                 int idx = this.FindDefaultAttribute ("lang", XmlNamespaceManager.XmlnsXml);
375                                 if (idx < 0)
376                                         return null;
377                                 return defaultAttributes [idx].ValidatedDefaultValue;
378                         }
379                 }
380
381                 public override XmlSpace XmlSpace {
382                         get {
383                                 XmlSpace space = reader.XmlSpace;
384                                 if (space != XmlSpace.None)
385                                         return space;
386                                 int idx = this.FindDefaultAttribute ("space", XmlNamespaceManager.XmlnsXml);
387                                 if (idx < 0)
388                                         return XmlSpace.None;
389                                 return (XmlSpace) Enum.Parse (typeof (XmlSpace), defaultAttributes [idx].ValidatedDefaultValue, false);
390                         }
391                 }
392
393                 // Private Methods
394
395                 private XmlQualifiedName QualifyName (string name)
396                 {
397                         int colonAt = name.IndexOf (':');
398                         if (colonAt < 0)
399                                 return new XmlQualifiedName (name, null);
400                         else
401                                 return new XmlQualifiedName (name.Substring (colonAt + 1),
402                                         LookupNamespace (name.Substring (0, colonAt)));
403                 }
404
405                 private void HandleError (string error)
406                 {
407                         HandleError (error, null);
408                 }
409
410                 private void HandleError (string error, Exception innerException)
411                 {
412                         if (reportNoValidationError)    // extra quick check
413                                 return;
414
415                         XmlSchemaException schemaException = new XmlSchemaException (error, 
416                                         this, this.BaseURI, null, innerException);
417                         HandleError (schemaException);
418                 }
419
420                 private void HandleError (XmlSchemaException schemaException)
421                 {
422                         if (reportNoValidationError)
423                                 return;
424
425                         ValidationEventArgs e = new ValidationEventArgs (schemaException,
426                                 schemaException.Message, XmlSeverityType.Error);
427
428                         if (this.ValidationEventHandler != null)
429                                 this.ValidationEventHandler (this, e);
430                         else if (xvReader != null)
431                                 xvReader.OnValidationEvent (this, e);
432                         else if (e.Severity == XmlSeverityType.Error)
433 #if NON_MONO_ENV
434                                 this.xvReader.OnValidationEvent (this, e);
435 #else
436                                 throw e.Exception;
437 #endif
438                 }
439
440                 private XmlSchemaElement FindElement (string name, string ns)
441                 {
442                         foreach (XmlSchema target in schemas) {
443                                 XmlSchema matches = target.Schemas [ns];
444                                 if (matches != null) {
445                                         XmlSchemaElement result = target.Elements [new XmlQualifiedName (name, ns)] as XmlSchemaElement;
446                                         if (result != null)
447                                                 return result;
448                                 }
449                         }
450                         return null;
451                 }
452
453                 private XmlSchemaType FindType (XmlQualifiedName qname)
454                 {
455                         foreach (XmlSchema target in schemas) {
456                                 XmlSchemaType type = target.SchemaTypes [qname] as XmlSchemaType;
457                                 if (type != null)
458                                         return type;
459                         }
460                         return null;
461                 }
462
463                 private void ValidateStartElementParticle ()
464                 {
465                         stateManager.CurrentElement = null;
466                         context.ParticleState = context.ParticleState.EvaluateStartElement (reader.LocalName, reader.NamespaceURI);
467                         if (context.ParticleState == XsdValidationState.Invalid)
468                                 HandleError ("Invalid start element: " + reader.NamespaceURI + ":" + reader.LocalName);
469
470                         context.Element = stateManager.CurrentElement;
471                         if (context.Element != null)
472                                 context.SchemaType = context.Element.ElementType;
473                 }
474
475                 private void ValidateEndElementParticle ()
476                 {
477                         if (childParticleState != null) {
478                                 if (!childParticleState.EvaluateEndElement ()) {
479                                         HandleError ("Invalid end element: " + reader.Name);
480                                 }
481                         }
482                         context.PopScope (reader.Depth);
483                 }
484
485                 // Utility for missing validation completion related to child items.
486                 private void ValidateCharacters ()
487                 {
488                         // TODO: value context validation here.
489                         if (xsiNilDepth >= 0 && xsiNilDepth < reader.Depth)
490                                 HandleError ("Element item appeared, while current element context is nil.");
491
492                         storedCharacters.Append (reader.Value);
493                 }
494
495                 // Utility for missing validation completion related to child items.
496                 private void ValidateEndCharacters ()
497                 {
498                         if (context.ActualType == null)
499                                 return;
500
501                         string value = storedCharacters.ToString ();
502
503                         if (storedCharacters.Length == 0) {
504                                 // 3.3.4 Element Locally Valid (Element) 5.1.2
505                                 // TODO: check entire DefaultValid (3.3.6)
506                                 if (context.Element != null && context.Element.ValidatedDefaultValue != null)
507                                         value = context.Element.ValidatedDefaultValue;
508                         }
509
510                         XmlSchemaDatatype dt = context.ActualType as XmlSchemaDatatype;
511                         XmlSchemaSimpleType st = context.ActualType as XmlSchemaSimpleType;
512                         if (dt == null) {
513                                 if (st != null) {
514 //                                      if (st.Variety == XmlSchemaDerivationMethod.Restriction)
515                                         dt = st.Datatype;
516                                 } else {
517                                         XmlSchemaComplexType ct = context.ActualType as XmlSchemaComplexType;
518                                         dt = ct.Datatype;
519                                         switch (ct.ContentType) {
520                                         case XmlSchemaContentType.ElementOnly:
521                                         case XmlSchemaContentType.Empty:
522                                                 if (storedCharacters.Length > 0)
523                                                         HandleError ("Character content not allowed.");
524                                                 break;
525                                         }
526                                 }
527                         }
528                         if (dt != null) {
529                                 // 3.3.4 Element Locally Valid (Element) :: 5.2.2.2. Fixed value constraints
530                                 if (context.Element != null && context.Element.ValidatedFixedValue != null)
531                                         if (value != context.Element.ValidatedFixedValue)
532                                                 HandleError ("Fixed value constraint was not satisfied.");
533                                 AssessStringValid (st, dt, value);
534                         }
535
536                         // Identity field value
537                         while (this.currentKeyFieldConsumers.Count > 0) {
538                                 XsdKeyEntryField field = this.currentKeyFieldConsumers [0] as XsdKeyEntryField;
539                                 if (field.Identity != null)
540                                         HandleError ("Two or more identical field was found. Former value is '" + field.Identity + "' .");
541                                 object identity = null;
542                                 if (dt != null) {
543                                         try {
544                                                 identity = dt.ParseValue (value, NameTable, ParserContext.NamespaceManager);
545                                         } catch (Exception ex) { // FIXME: (wishlist) This is bad manner ;-(
546                                                 HandleError ("Identity value is invalid against its data type " + dt.TokenizedType, ex);
547                                         }
548                                 }
549                                 if (identity == null)
550                                         identity = value;
551                                 
552                                 if (!field.SetIdentityField (identity, dt as XsdAnySimpleType, this))
553                                         HandleError ("Two or more identical key value was found: '" + value + "' .");
554                                 this.currentKeyFieldConsumers.RemoveAt (0);
555                         }
556
557                         shouldValidateCharacters = false;
558                 }
559
560                 // 3.14.4 String Valid 
561                 private void AssessStringValid (XmlSchemaSimpleType st,
562                         XmlSchemaDatatype dt, string value)
563                 {
564                         XmlSchemaDatatype validatedDatatype = dt;
565                         if (st != null) {
566                                 string normalized = validatedDatatype.Normalize (value);
567                                 string [] values;
568                                 XmlSchemaDatatype itemDatatype;
569                                 XmlSchemaSimpleType itemSimpleType;
570                                 switch (st.DerivedBy) {
571                                 case XmlSchemaDerivationMethod.List:
572                                         XmlSchemaSimpleTypeList listContent = st.Content as XmlSchemaSimpleTypeList;
573                                         values = normalized.Split (wsChars);
574                                         itemDatatype = listContent.ValidatedListItemType as XmlSchemaDatatype;
575                                         itemSimpleType = listContent.ValidatedListItemType as XmlSchemaSimpleType;
576                                         foreach (string each in values) {
577                                                 if (each == String.Empty)
578                                                         continue;
579                                                 // validate against ValidatedItemType
580                                                 if (itemDatatype != null) {
581                                                         try {
582                                                                 itemDatatype.ParseValue (each, NameTable, ParserContext.NamespaceManager);
583                                                         } catch (Exception ex) { // FIXME: (wishlist) better exception handling ;-(
584                                                                 HandleError ("List type value contains one or more invalid values.", ex);
585                                                                 break;
586                                                         }
587                                                 }
588                                                 else
589                                                         AssessStringValid (itemSimpleType, itemSimpleType.Datatype, each);
590                                         }
591                                         break;
592                                 case XmlSchemaDerivationMethod.Union:
593                                         XmlSchemaSimpleTypeUnion union = st.Content as XmlSchemaSimpleTypeUnion;
594                                         {
595                                                 string each = normalized;
596                                                 // validate against ValidatedItemType
597                                                 bool passed = false;
598                                                 foreach (object eachType in union.ValidatedTypes) {
599                                                         itemDatatype = eachType as XmlSchemaDatatype;
600                                                         itemSimpleType = eachType as XmlSchemaSimpleType;
601                                                         if (itemDatatype != null) {
602                                                                 try {
603                                                                         itemDatatype.ParseValue (each, NameTable, ParserContext.NamespaceManager);
604                                                                 } catch (Exception) { // FIXME: (wishlist) better exception handling ;-(
605                                                                         continue;
606                                                                 }
607                                                         }
608                                                         else {
609                                                                 try {
610                                                                         AssessStringValid (itemSimpleType, itemSimpleType.Datatype, each);
611                                                                 } catch (XmlSchemaException) {
612                                                                         continue;
613                                                                 }
614                                                         }
615                                                         passed = true;
616                                                         break;
617                                                 }
618                                                 if (!passed) {
619                                                         HandleError ("Union type value contains one or more invalid values.");
620                                                         break;
621                                                 }
622                                         }
623                                         break;
624                                 case XmlSchemaDerivationMethod.Restriction:
625                                         XmlSchemaSimpleTypeRestriction str = st.Content as XmlSchemaSimpleTypeRestriction;
626                                         // facet validation
627                                         if (str != null) {
628                                                 /* Don't forget to validate against inherited type's facets 
629                                                  * Could we simplify this by assuming that the basetype will also
630                                                  * be restriction?
631                                                  * */
632                                                  // mmm, will check later.
633                                                 XmlSchemaSimpleType baseType = str.ActualBaseSchemaType as XmlSchemaSimpleType;
634                                                 if (baseType != null) {
635                                                          AssessStringValid(baseType, dt, normalized);
636                                                 }
637                                                 if (!str.ValidateValueWithFacets (normalized, NameTable)) {
638                                                         HandleError ("Specified value was invalid against the facets.");
639                                                         break;
640                                                 }
641                                         }
642                                         validatedDatatype = st.Datatype;
643                                         break;
644                                 }
645                         }
646                         if (validatedDatatype != null) {
647                                 try {
648                                         validatedDatatype.ParseValue (value, NameTable, ParserContext.NamespaceManager);
649                                 } catch (Exception ex) {        // FIXME: (wishlist) It is bad manner ;-(
650                                         HandleError ("Invalidly typed data was specified.", ex);
651                                 }
652                         }
653                 }
654
655                 private object GetLocalTypeDefinition (string name)
656                 {
657                         object xsiType = null;
658                         XmlQualifiedName typeQName = QualifyName (name);
659                         if (typeQName.Namespace == XmlSchema.Namespace) {
660                                 if (typeQName.Name == "anyType")
661                                         xsiType = XmlSchemaComplexType.AnyType;
662                                 else
663                                         xsiType = XmlSchemaDatatype.FromName (typeQName);
664                         }
665                         else
666                                 xsiType = FindType (typeQName);
667                         return xsiType;
668                 }
669
670                 // It is common to ElementLocallyValid::4 and SchemaValidityAssessment::1.2.1.2.4
671                 private void AssessLocalTypeDerivationOK (object xsiType, object baseType, XmlSchemaDerivationMethod flag)
672                 {
673                         XmlSchemaType xsiSchemaType = xsiType as XmlSchemaType;
674                         XmlSchemaComplexType baseComplexType = baseType as XmlSchemaComplexType;
675                         XmlSchemaComplexType xsiComplexType = xsiSchemaType as XmlSchemaComplexType;
676                         if (xsiType != baseType) {
677                                 // Extracted (not extraneous) check for 3.4.6 TypeDerivationOK.
678                                 if (baseComplexType != null)
679                                         flag |= baseComplexType.BlockResolved;
680                                 if (flag == XmlSchemaDerivationMethod.All) {
681                                         HandleError ("Prohibited element type substitution.");
682                                         return;
683                                 } else if (xsiSchemaType != null && (flag & xsiSchemaType.DerivedBy) != 0) {
684                                         HandleError ("Prohibited element type substitution.");
685                                         return;
686                                 }
687                         }
688
689                         if (xsiComplexType != null)
690                                 try {
691                                         xsiComplexType.ValidateTypeDerivationOK (baseType, null, null);
692                                 } catch (XmlSchemaException ex) {
693 //                                      HandleError ("Locally specified schema complex type derivation failed. " + ex.Message, ex);
694                                         HandleError (ex);
695                                 }
696                         else {
697                                 XmlSchemaSimpleType xsiSimpleType = xsiType as XmlSchemaSimpleType;
698                                 if (xsiSimpleType != null) {
699                                         try {
700                                                 xsiSimpleType.ValidateTypeDerivationOK (baseType, null, null, true);
701                                         } catch (XmlSchemaException ex) {
702 //                                              HandleError ("Locally specified schema simple type derivation failed. " + ex.Message, ex);
703                                                 HandleError (ex);
704                                         }
705                                 }
706                                 else if (xsiType is XmlSchemaDatatype) {
707                                         // do nothing
708                                 }
709                                 else
710                                         HandleError ("Primitive data type cannot be derived type using xsi:type specification.");
711                         }
712                 }
713
714                 // Section 3.3.4 of the spec.
715                 private void AssessStartElementSchemaValidity ()
716                 {
717                         // If the reader is inside xsi:nil (and failed on validation),
718                         // then simply skip its content.
719                         if (xsiNilDepth >= 0 && xsiNilDepth < reader.Depth)
720                                 HandleError ("Element item appeared, while current element context is nil.");
721
722                         context.Load (reader.Depth);
723                         if (childParticleState != null) {
724                                 context.ParticleState = childParticleState;
725                                 childParticleState = null;
726                         }
727
728                         // If validation state exists, then first assess particle validity.
729                         if (context.ParticleState != null) {
730                                 ValidateStartElementParticle ();
731                         }
732
733                         string xsiNilValue = GetAttribute ("nil", XmlSchema.InstanceNamespace);
734                         if (xsiNilValue != null)
735                                 xsiNilValue = xsiNilValue.Trim (XmlChar.WhitespaceChars);
736                         bool isXsiNil = xsiNilValue == "true";
737                         if (isXsiNil && this.xsiNilDepth < 0)
738                                 xsiNilDepth = reader.Depth;
739
740                         // [Schema Validity Assessment (Element) 1.2]
741                         // Evaluate "local type definition" from xsi:type.
742                         // (See spec 3.3.4 Schema Validity Assessment (Element) 1.2.1.2.3.
743                         // Note that Schema Validity Assessment(Element) 1.2 takes
744                         // precedence than 1.1 of that.
745
746                         string xsiTypeName = reader.GetAttribute ("type", XmlSchema.InstanceNamespace);
747                         if (xsiTypeName != null) {
748                                 xsiTypeName = xsiTypeName.Trim (XmlChar.WhitespaceChars);
749                                 object xsiType = GetLocalTypeDefinition (xsiTypeName);
750                                 if (xsiType == null)
751                                         HandleError ("The instance type was not found: " + xsiTypeName + " .");
752                                 else {
753                                         XmlSchemaType xsiSchemaType = xsiType as XmlSchemaType;
754                                         if (xsiSchemaType != null && this.context.Element != null) {
755                                                 XmlSchemaType elemBaseType = context.Element.ElementType as XmlSchemaType;
756                                                 if (elemBaseType != null && (xsiSchemaType.DerivedBy & elemBaseType.FinalResolved) != 0)
757                                                         HandleError ("The instance type is prohibited by the type of the context element.");
758                                                 if (elemBaseType != xsiType && (xsiSchemaType.DerivedBy & this.context.Element.BlockResolved) != 0)
759                                                         HandleError ("The instance type is prohibited by the context element.");
760                                         }
761                                         XmlSchemaComplexType xsiComplexType = xsiType as XmlSchemaComplexType;
762                                         if (xsiComplexType != null && xsiComplexType.IsAbstract)
763                                                 HandleError ("The instance type is abstract: " + xsiTypeName + " .");
764                                         else {
765                                                 // If current schema type exists, then this xsi:type must be
766                                                 // valid extension of that type. See 1.2.1.2.4.
767                                                 if (context.Element != null) {
768                                                         // FIXME: supply *correct* base type
769                                                         AssessLocalTypeDerivationOK (xsiType, context.Element.ElementType, context.Element.BlockResolved);
770                                                 }
771                                                 AssessStartElementLocallyValidType (xsiType);   // 1.2.2:
772                                                 context.LocalTypeDefinition = xsiType;
773                                         }
774                                 }
775                         }
776
777                         // Create Validation Root, if not exist.
778                         // [Schema Validity Assessment (Element) 1.1]
779                         if (context.Element == null)
780                                 context.Element = FindElement (reader.LocalName, reader.NamespaceURI);
781                         if (context.Element != null) {
782                                 if (xsiTypeName == null) {
783                                         context.SchemaType = context.Element.ElementType;
784                                         AssessElementLocallyValidElement (context.Element, xsiNilValue);        // 1.1.2
785                                 }
786                         } else {
787                                 XmlSchema schema;
788                                 switch (stateManager.ProcessContents) {
789                                 case XmlSchemaContentProcessing.Skip:
790                                         break;
791                                 case XmlSchemaContentProcessing.Lax:
792                                         /*
793                                         schema = schemas [reader.NamespaceURI];
794                                         if (schema != null && !schema.missedSubComponents)
795                                                 HandleError ("Element declaration for " + reader.LocalName + " is missing.");
796                                         */
797                                         break;
798                                 default:
799                                         schema = schemas [reader.NamespaceURI];
800                                         if (xsiTypeName == null && (schema == null || !schema.missedSubComponents))
801                                                 HandleError ("Element declaration for " + reader.LocalName + " is missing.");
802                                         break;
803                                 }
804                         }
805
806                         if (stateManager.ProcessContents == XmlSchemaContentProcessing.Skip)
807                                 skipValidationDepth = reader.Depth;
808
809                         // Finally, create child particle state.
810                         XmlSchemaComplexType xsComplexType = SchemaType as XmlSchemaComplexType;
811                         if (xsComplexType != null)
812                                 childParticleState = stateManager.Create (xsComplexType.ContentTypeParticle);
813                         else if (stateManager.ProcessContents == XmlSchemaContentProcessing.Lax)
814                                 childParticleState = stateManager.Create (XmlSchemaAny.AnyTypeContent);
815                         else
816                                 childParticleState = stateManager.Create (XmlSchemaParticle.Empty);
817
818                         AssessStartIdentityConstraints ();
819
820                         context.PushScope (reader.Depth);
821                 }
822
823                 // 3.3.4 Element Locally Valid (Element)
824                 private void AssessElementLocallyValidElement (XmlSchemaElement element, string xsiNilValue)
825                 {
826                         XmlQualifiedName qname = new XmlQualifiedName (reader.LocalName, reader.NamespaceURI);
827                         // 1.
828                         if (element == null)
829                                 HandleError ("Element declaration is required for " + qname);
830                         // 2.
831                         if (element.ActualIsAbstract)
832                                 HandleError ("Abstract element declaration was specified for " + qname);
833                         // 3.1.
834                         if (!element.ActualIsNillable && xsiNilValue != null)
835                                 HandleError ("This element declaration is not nillable: " + qname);
836                         // 3.2.
837                         // Note that 3.2.1 xsi:nil constraints are to be validated in
838                         else if (xsiNilValue == "true") {
839                                 // AssessElementSchemaValidity() and ValidateCharacters()
840
841                                 if (element.ValidatedFixedValue != null)
842                                         HandleError ("Schema instance nil was specified, where the element declaration for " + qname + "has fixed value constraints.");
843                         }
844                         // 4.
845                         string xsiType = reader.GetAttribute ("type", XmlSchema.InstanceNamespace);
846                         if (xsiType != null) {
847                                 context.LocalTypeDefinition = GetLocalTypeDefinition (xsiType);
848                                 AssessLocalTypeDerivationOK (context.LocalTypeDefinition, element.ElementType, element.BlockResolved);
849                         }
850
851                         // 5 Not all things cannot be assessed here.
852                         // It is common to 5.1 and 5.2
853                         if (element.ElementType != null)
854                                 AssessStartElementLocallyValidType (SchemaType);
855
856                         // 6. should be out from here.
857                         // See invokation of AssessStartIdentityConstraints().
858
859                         // 7 is going to be validated in Read() (in case of xmlreader's EOF).
860                 }
861
862                 // 3.3.4 Element Locally Valid (Type)
863                 private void AssessStartElementLocallyValidType (object schemaType)
864                 {
865                         if (schemaType == null) {       // 1.
866                                 HandleError ("Schema type does not exist.");
867                                 return;
868                         }
869                         XmlSchemaComplexType cType = schemaType as XmlSchemaComplexType;
870                         XmlSchemaSimpleType sType = schemaType as XmlSchemaSimpleType;
871                         if (sType != null) {
872                                 // 3.1.1.
873                                 while (reader.MoveToNextAttribute ()) {
874                                         if (reader.NamespaceURI == XmlNamespaceManager.XmlnsXmlns)
875                                                 continue;
876                                         if (reader.NamespaceURI != XmlSchema.InstanceNamespace)
877                                                 HandleError ("Current simple type cannot accept attributes other than schema instance namespace.");
878                                         switch (reader.LocalName) {
879                                         case "type":
880                                         case "nil":
881                                         case "schemaLocation":
882                                         case "noNamespaceSchemaLocation":
883                                                 break;
884                                         default:
885                                                 HandleError ("Unknown schema instance namespace attribute: " + reader.LocalName);
886                                                 break;
887                                         }
888                                 }
889                                 reader.MoveToElement ();
890                                 // 3.1.2 and 3.1.3 cannot be assessed here.
891                         } else if (cType != null) {
892                                 if (cType.IsAbstract) { // 2.
893                                         HandleError ("Target complex type is abstract.");
894                                         return;
895                                 }
896                                 // 3.2
897                                 AssessElementLocallyValidComplexType (cType);
898                         }
899                 }
900
901                 // 3.4.4 Element Locally Valid (Complex Type)
902                 // TODO ("wild IDs constraints.")
903                 private void AssessElementLocallyValidComplexType (XmlSchemaComplexType cType)
904                 {
905                         // 1.
906                         if (cType.IsAbstract)
907                                 HandleError ("Target complex type is abstract.");
908
909                         // 2 (xsi:nil and content prohibition)
910                         // See AssessStartElementSchemaValidity() and ValidateCharacters()
911
912                         string elementNs = reader.NamespaceURI;
913                         // 3. attribute uses and 
914                         // 5. wild IDs
915                         while (reader.MoveToNextAttribute ()) {
916                                 if (reader.NamespaceURI == "http://www.w3.org/2000/xmlns/")
917                                         continue;
918                                 else if (reader.NamespaceURI == XmlSchema.InstanceNamespace)
919                                         continue;
920                                 XmlQualifiedName qname = new XmlQualifiedName (reader.LocalName, reader.NamespaceURI);
921                                 object attMatch = FindAttributeDeclaration (cType, qname, elementNs);
922                                 if (attMatch == null)
923                                         HandleError ("Attribute declaration was not found for " + qname);
924                                 else {
925                                         XmlSchemaAttribute attdecl = attMatch as XmlSchemaAttribute;
926                                         if (attdecl == null) { // i.e. anyAttribute
927                                                 XmlSchemaAnyAttribute anyAttrMatch = attMatch as XmlSchemaAnyAttribute;
928                                         } else {
929                                                 AssessAttributeLocallyValidUse (attdecl);
930                                                 AssessAttributeLocallyValid (attdecl, true);
931                                         }
932                                 }
933                         }
934                         reader.MoveToElement ();
935
936                         // Collect default attributes.
937                         // 4.
938                         // FIXME: FixedValue check maybe extraneous.
939                         foreach (DictionaryEntry entry in cType.AttributeUses) {
940                                 XmlSchemaAttribute attr = (XmlSchemaAttribute) entry.Value;
941                                 if (reader [attr.QualifiedName.Name, attr.QualifiedName.Namespace] == null) {
942                                         if (attr.ValidatedUse == XmlSchemaUse.Required && 
943                                                 attr.ValidatedFixedValue == null)
944                                                 HandleError ("Required attribute " + attr.QualifiedName + " was not found.");
945                                         else if (attr.ValidatedDefaultValue != null)
946                                                 defaultAttributesCache.Add (attr);
947                                 }
948                         }
949                         defaultAttributes = (XmlSchemaAttribute []) 
950                                 defaultAttributesCache.ToArray (typeof (XmlSchemaAttribute));
951                         context.DefaultAttributes = defaultAttributes;
952                         defaultAttributesCache.Clear ();
953                         // 5. wild IDs was already checked above.
954                 }
955
956                 // Spec 3.10.4 Item Valid (Wildcard)
957                 private bool AttributeWildcardItemValid (XmlSchemaAnyAttribute anyAttr, XmlQualifiedName qname)
958                 {
959                         if (anyAttr.HasValueAny)
960                                 return true;
961                         if (anyAttr.HasValueOther && (anyAttr.TargetNamespace == "" || reader.NamespaceURI != anyAttr.TargetNamespace))
962                                 return true;
963                         if (anyAttr.HasValueTargetNamespace && reader.NamespaceURI == anyAttr.TargetNamespace)
964                                 return true;
965                         if (anyAttr.HasValueLocal && reader.NamespaceURI == "")
966                                 return true;
967                         foreach (string ns in anyAttr.ResolvedNamespaces)
968                                 if (ns == reader.NamespaceURI)
969                                         return true;
970                         return false;
971                 }
972
973                 private XmlSchemaObject FindAttributeDeclaration (XmlSchemaComplexType cType,
974                         XmlQualifiedName qname, string elementNs)
975                 {
976                         XmlSchemaObject result = cType.AttributeUses [qname];
977                         if (result != null)
978                                 return result;
979                         if (cType.AttributeWildcard == null)
980                                 return null;
981
982                         if (!AttributeWildcardItemValid (cType.AttributeWildcard, qname))
983                                 return null;
984
985                         if (cType.AttributeWildcard.ProcessContents == XmlSchemaContentProcessing.Skip)
986                                 return cType.AttributeWildcard;
987                         foreach (XmlSchema schema in schemas) {
988                                 foreach (DictionaryEntry entry in schema.Attributes) {
989                                         XmlSchemaAttribute attr = (XmlSchemaAttribute) entry.Value;
990                                         if (attr.QualifiedName == qname)
991                                                 return attr;
992                                 }
993                         }
994                         if (cType.AttributeWildcard.ProcessContents == XmlSchemaContentProcessing.Lax)
995                                 return cType.AttributeWildcard;
996                         else
997                                 return null;
998                 }
999
1000                 // 3.2.4 Attribute Locally Valid and 3.4.4 - 5.wildIDs
1001                 // TODO
1002                 private void AssessAttributeLocallyValid (XmlSchemaAttribute attr, bool checkWildIDs)
1003                 {
1004                         // 1.
1005                         switch (reader.NamespaceURI) {
1006                         case XmlNamespaceManager.XmlnsXml:
1007                         case XmlNamespaceManager.XmlnsXmlns:
1008                         case XmlSchema.InstanceNamespace:
1009                                 break;
1010                         }
1011                         // TODO 2. - 4.
1012                         if (attr.AttributeType == null)
1013                                 HandleError ("Attribute type is missing for " + attr.QualifiedName);
1014                         XmlSchemaDatatype dt = attr.AttributeType as XmlSchemaDatatype;
1015                         if (dt == null)
1016                                 dt = ((XmlSchemaSimpleType) attr.AttributeType).Datatype;
1017                         // It is a bit heavy process, so let's omit as long as possible ;-)
1018                         if (dt != XmlSchemaSimpleType.AnySimpleType || attr.ValidatedFixedValue != null) {
1019                                 string normalized = dt.Normalize (reader.Value);
1020                                 object parsedValue = null;
1021                                 try {
1022                                         dt.ParseValue (normalized, reader.NameTable, this.ParserContext.NamespaceManager);
1023                                 } catch (Exception ex) { // FIXME: (wishlist) It is bad manner ;-(
1024                                         HandleError ("Attribute value is invalid against its data type " + dt.TokenizedType, ex);
1025                                 }
1026                                 if (attr.ValidatedFixedValue != null && attr.ValidatedFixedValue != normalized)
1027                                         HandleError ("The value of the attribute " + attr.QualifiedName + " does not match with its fixed value.");
1028                                 // FIXME: this is extraneous checks in 3.2.4 Attribute Locally Valid.
1029                                 if (checkWildIDs)
1030                                         AssessEachAttributeIdentityConstraint (dt, normalized, parsedValue);
1031                         }
1032                 }
1033
1034                 private void AssessEachAttributeIdentityConstraint (XmlSchemaDatatype dt,
1035                         string normalized, object parsedValue)
1036                 {
1037                         // Get normalized value and (if required) parsedValue if missing.
1038                         switch (dt.TokenizedType) {
1039                         case XmlTokenizedType.IDREFS:
1040                                 if (normalized == null)
1041                                         normalized = dt.Normalize (reader.Value);
1042                                 if (parsedValue == null)
1043                                         parsedValue = dt.ParseValue (normalized, reader.NameTable, ParserContext.NamespaceManager);
1044                                 break;
1045                         case XmlTokenizedType.ID:
1046                         case XmlTokenizedType.IDREF:
1047                                 if (normalized == null)
1048                                         normalized = dt.Normalize (reader.Value);
1049                                 break;
1050                         }
1051
1052                         // Validate identity constraints.
1053                         switch (dt.TokenizedType) {
1054                         case XmlTokenizedType.ID:
1055                                 if (thisElementId != null)
1056                                         HandleError ("ID type attribute was already assigned in the containing element.");
1057                                 thisElementId = normalized;
1058                                 idList.Add (normalized);
1059                                 break;
1060                         case XmlTokenizedType.IDREF:
1061                                 if (missingIDReferences.Contains (normalized))
1062                                         missingIDReferences.Remove (normalized);
1063                                 else
1064                                         missingIDReferences.Add (normalized);
1065                                 break;
1066                         case XmlTokenizedType.IDREFS:
1067                                 foreach (string id in (string []) parsedValue) {
1068                                         if (missingIDReferences.Contains (id))
1069                                                 missingIDReferences.Remove (id);
1070                                         else
1071                                                 missingIDReferences.Add (id);
1072                                 }
1073                                 break;
1074                         }
1075                 }
1076
1077                 // TODO
1078                 private void AssessAttributeLocallyValidUse (XmlSchemaAttribute attr)
1079                 {
1080                         // TODO: value constraint check
1081                         // This is extra check than spec 3.5.4
1082                         if (attr.ValidatedUse == XmlSchemaUse.Prohibited)
1083                                 HandleError ("Attribute " + attr.QualifiedName + " is prohibited in this context.");
1084                 }
1085
1086                 private void AssessEndElementSchemaValidity ()
1087                 {
1088                         if (childParticleState == null)
1089                                 childParticleState = context.ParticleState;
1090                         ValidateEndElementParticle ();  // validate against childrens' state.
1091
1092                         context.Load (reader.Depth);
1093
1094                         // 3.3.4 Assess ElementLocallyValidElement 5: value constraints.
1095                         // 3.3.4 Assess ElementLocallyValidType 3.1.3. = StringValid(3.14.4)
1096                         // => ValidateEndCharacters().
1097
1098                         // Reset Identity constraints.
1099                         for (int i = 0; i < keyTables.Count; i++) {
1100                                 XsdKeyTable keyTable = this.keyTables [i] as XsdKeyTable;
1101                                 if (keyTable.StartDepth == reader.Depth) {
1102                                         EndIdentityValidation (keyTable);
1103                                 } else {
1104                                         for (int k = 0; k < keyTable.Entries.Count; k++) {
1105                                                 XsdKeyEntry entry = keyTable.Entries [k] as XsdKeyEntry;
1106                                                 // Remove finished (maybe key not found) entries.
1107                                                 if (entry.StartDepth == reader.Depth) {
1108                                                         if (entry.KeyFound)
1109                                                                 keyTable.FinishedEntries.Add (entry);
1110                                                         else if (entry.KeySequence.SourceSchemaIdentity is XmlSchemaKey)
1111                                                                 HandleError ("Key sequence is missing.");
1112                                                         keyTable.Entries.RemoveAt (k);
1113                                                         k--;
1114                                                 }
1115                                                 // Pop validated key depth to find two or more fields.
1116                                                 else {
1117                                                         foreach (XsdKeyEntryField kf in entry.KeyFields) {
1118                                                                 if (!kf.FieldFound && kf.FieldFoundDepth == reader.Depth) {
1119                                                                         kf.FieldFoundDepth = 0;
1120                                                                         kf.FieldFoundPath = null;
1121                                                                 }
1122                                                         }
1123                                                 }
1124                                         }
1125                                 }
1126                         }
1127                         for (int i = 0; i < keyTables.Count; i++) {
1128                                 XsdKeyTable keyseq = this.keyTables [i] as XsdKeyTable;
1129                                 if (keyseq.StartDepth == reader.Depth) {
1130 //Console.WriteLine ("Finishing table.");
1131                                         keyTables.RemoveAt (i);
1132                                         i--;
1133                                 }
1134                         }
1135
1136                         // Reset xsi:nil, if required.
1137                         if (xsiNilDepth == reader.Depth)
1138                                 xsiNilDepth = -1;
1139                 }
1140
1141                 // 3.11.4 Identity Constraint Satisfied
1142                 // TODO
1143                 private void AssessStartIdentityConstraints ()
1144                 {
1145                         tmpKeyrefPool.Clear ();
1146                         if (context.Element != null && context.Element.Constraints.Count > 0) {
1147                                 // (a) Create new key sequences, if required.
1148                                 foreach (XmlSchemaIdentityConstraint ident in context.Element.Constraints) {
1149                                         XsdKeyTable seq = CreateNewKeyTable (ident);
1150                                         if (ident is XmlSchemaKeyref)
1151                                                 tmpKeyrefPool.Add (seq);
1152                                 }
1153                         }
1154
1155                         // (b) Evaluate current key sequences.
1156                         foreach (XsdKeyTable seq in this.keyTables) {
1157                                 if (seq.SelectorMatches (this.elementQNameStack, reader) != null) {
1158                                         // creates and registers new entry.
1159                                         XsdKeyEntry entry = new XsdKeyEntry (seq, reader);
1160                                         seq.Entries.Add (entry);
1161                                 }
1162                         }
1163
1164                         // (c) Evaluate field paths.
1165                         foreach (XsdKeyTable seq in this.keyTables) {
1166                                 // If possible, create new field entry candidates.
1167                                 for (int i = 0; i < seq.Entries.Count; i++) {
1168                                         XsdKeyEntry entry = seq.Entries [i] as XsdKeyEntry;
1169 //                                      if (entry.KeyFound)
1170 // FIXME: it should not be skipped for multiple key check!!
1171 //                                              continue;
1172                                         try {
1173                                                 entry.FieldMatches (this.elementQNameStack, this);
1174                                         } catch (Exception ex) { // FIXME: (wishlist) It is bad manner ;-(
1175                                                 HandleError ("Identity field value is invalid against its data type.", ex);
1176                                         }
1177                                 }
1178                         }
1179                 }
1180
1181                 private XsdKeyTable CreateNewKeyTable (XmlSchemaIdentityConstraint ident)
1182                 {
1183                         XsdKeyTable seq = new XsdKeyTable (ident, this);
1184                         seq.StartDepth = reader.Depth;
1185                         XmlSchemaKeyref keyref = ident as XmlSchemaKeyref;
1186                         this.keyTables.Add (seq);
1187                         return seq;
1188                 }
1189
1190                 private void EndIdentityValidation (XsdKeyTable seq)
1191                 {
1192                         ArrayList errors = new ArrayList ();
1193                         foreach (XsdKeyEntry entry in seq./*NotFound*/Entries) {
1194                                 if (entry.KeyFound)
1195                                         continue;
1196                                 if (seq.SourceSchemaIdentity is XmlSchemaKey)
1197                                         errors.Add ("line " + entry.SelectorLineNumber + "position " + entry.SelectorLinePosition);
1198                         }
1199                         if (errors.Count > 0)
1200                                 HandleError ("Invalid identity constraints were found. Key was not found. "
1201                                         + String.Join (", ", errors.ToArray (typeof (string)) as string []));
1202
1203                         errors.Clear ();
1204                         // Find reference target
1205                         XmlSchemaKeyref xsdKeyref = seq.SourceSchemaIdentity as XmlSchemaKeyref;
1206                         if (xsdKeyref != null) {
1207                                 for (int i = this.keyTables.Count - 1; i >= 0; i--) {
1208                                         XsdKeyTable target = this.keyTables [i] as XsdKeyTable;
1209                                         if (target.SourceSchemaIdentity == xsdKeyref.Target) {
1210                                                 seq.ReferencedKey = target;
1211                                                 foreach (XsdKeyEntry entry in seq.FinishedEntries) {
1212                                                         foreach (XsdKeyEntry targetEntry in target.FinishedEntries) {
1213                                                                 if (entry.CompareIdentity (targetEntry)) {
1214                                                                         entry.KeyRefFound = true;
1215                                                                         break;
1216                                                                 }
1217                                                         }
1218                                                 }
1219                                         }
1220                                 }
1221                                 if (seq.ReferencedKey == null)
1222                                         HandleError ("Target key was not found.");
1223                                 foreach (XsdKeyEntry entry in seq.FinishedEntries) {
1224                                         if (!entry.KeyRefFound)
1225                                                 errors.Add (" line " + entry.SelectorLineNumber + ", position " + entry.SelectorLinePosition);
1226                                 }
1227                                 if (errors.Count > 0)
1228                                         HandleError ("Invalid identity constraints were found. Referenced key was not found: "
1229                                                 + String.Join (" / ", errors.ToArray (typeof (string)) as string []));
1230                         }
1231                 }
1232
1233                 // Overrided Methods
1234
1235                 public override void Close ()
1236                 {
1237                         reader.Close ();
1238                 }
1239
1240                 public override string GetAttribute (int i)
1241                 {
1242                         switch (reader.NodeType) {
1243                         case XmlNodeType.XmlDeclaration:
1244                         case XmlNodeType.DocumentType:
1245                                 return reader.GetAttribute (i);
1246                         }
1247
1248                         if (reader.AttributeCount > i)
1249                                 reader.GetAttribute (i);
1250                         int defIdx = i - nonDefaultAttributeCount;
1251                         if (i < AttributeCount)
1252                                 return defaultAttributes [defIdx].DefaultValue;
1253
1254                         throw new ArgumentOutOfRangeException ("i", i, "Specified attribute index is out of range.");
1255                 }
1256
1257                 public override string GetAttribute (string name)
1258                 {
1259                         switch (reader.NodeType) {
1260                         case XmlNodeType.XmlDeclaration:
1261                         case XmlNodeType.DocumentType:
1262                                 return reader.GetAttribute (name);
1263                         }
1264
1265                         string value = reader.GetAttribute (name);
1266                         if (value != null)
1267                                 return value;
1268
1269                         XmlQualifiedName qname = SplitQName (name);
1270                         return GetDefaultAttribute (qname.Name, qname.Namespace);
1271                 }
1272
1273                 private XmlQualifiedName SplitQName (string name)
1274                 {
1275                         if (!XmlChar.IsName (name))
1276                                 throw new ArgumentException ("Invalid name was specified.", "name");
1277
1278                         Exception ex = null;
1279                         XmlQualifiedName qname = XmlSchemaUtil.ToQName (reader, name, out ex);
1280                         if (ex != null)
1281                                 return XmlQualifiedName.Empty;
1282                         else
1283                                 return qname;
1284                 }
1285
1286                 public override string GetAttribute (string localName, string ns)
1287                 {
1288                         switch (reader.NodeType) {
1289                         case XmlNodeType.XmlDeclaration:
1290                         case XmlNodeType.DocumentType:
1291                                 return reader.GetAttribute (localName, ns);
1292                         }
1293
1294                         string value = reader.GetAttribute (localName, ns);
1295                         if (value != null)
1296                                 return value;
1297
1298                         return GetDefaultAttribute (localName, ns);
1299                 }
1300
1301                 private string GetDefaultAttribute (string localName, string ns)
1302                 {
1303                         int idx = this.FindDefaultAttribute (localName, ns);
1304                         if (idx >= 0)
1305                                 return defaultAttributes [idx].ValidatedDefaultValue;
1306                         else
1307                                 return null;
1308                 }
1309
1310                 private int FindDefaultAttribute (string localName, string ns)
1311                 {
1312                         for (int i = 0; i < this.defaultAttributes.Length; i++) {
1313                                 XmlSchemaAttribute attr = defaultAttributes [i];
1314                                 if (attr.QualifiedName.Name == localName &&
1315                                         (ns == null || attr.QualifiedName.Namespace == ns))
1316                                         return i;
1317                         }
1318                         return -1;
1319                 }
1320
1321                 bool IXmlLineInfo.HasLineInfo ()
1322                 {
1323                         return readerLineInfo != null && readerLineInfo.HasLineInfo ();
1324                 }
1325
1326                 public override string LookupNamespace (string prefix)
1327                 {
1328                         return reader.LookupNamespace (prefix);
1329                 }
1330
1331                 public override void MoveToAttribute (int i)
1332                 {
1333                         switch (reader.NodeType) {
1334                         case XmlNodeType.XmlDeclaration:
1335                         case XmlNodeType.DocumentType:
1336                                 reader.MoveToAttribute (i);
1337                                 return;
1338                         }
1339
1340                         currentQName = null;
1341                         if (i < this.nonDefaultAttributeCount) {
1342                                 reader.MoveToAttribute (i);
1343                                 this.currentDefaultAttribute = -1;
1344                                 this.defaultAttributeConsumed = false;
1345                         }
1346
1347                         if (i < AttributeCount) {
1348                                 this.currentDefaultAttribute = i - nonDefaultAttributeCount;
1349                                 this.defaultAttributeConsumed = false;
1350                         }
1351                         else
1352                                 throw new ArgumentOutOfRangeException ("i", i, "Attribute index is out of range.");
1353                 }
1354
1355                 public override bool MoveToAttribute (string name)
1356                 {
1357                         switch (reader.NodeType) {
1358                         case XmlNodeType.XmlDeclaration:
1359                         case XmlNodeType.DocumentType:
1360                                 return reader.MoveToAttribute (name);
1361                         }
1362
1363                         currentQName = null;
1364                         bool b = reader.MoveToAttribute (name);
1365                         if (b) {
1366                                 this.currentDefaultAttribute = -1;
1367                                 this.defaultAttributeConsumed = false;
1368                                 return true;
1369                         }
1370
1371                         return MoveToDefaultAttribute (name, null);
1372                 }
1373
1374                 public override bool MoveToAttribute (string localName, string ns)
1375                 {
1376                         switch (reader.NodeType) {
1377                         case XmlNodeType.XmlDeclaration:
1378                         case XmlNodeType.DocumentType:
1379                                 return reader.MoveToAttribute (localName, ns);
1380                         }
1381
1382                         currentQName = null;
1383                         bool b = reader.MoveToAttribute (localName, ns);
1384                         if (b) {
1385                                 this.currentDefaultAttribute = -1;
1386                                 this.defaultAttributeConsumed = false;
1387                                 return true;
1388                         }
1389
1390                         return MoveToDefaultAttribute (localName, ns);
1391                 }
1392
1393                 private bool MoveToDefaultAttribute (string localName, string ns)
1394                 {
1395                         int idx = this.FindDefaultAttribute (localName, ns);
1396                         if (idx < 0)
1397                                 return false;
1398                         currentDefaultAttribute = idx;
1399                         defaultAttributeConsumed = false;
1400                         return true;
1401                 }
1402
1403                 public override bool MoveToElement ()
1404                 {
1405                         currentDefaultAttribute = -1;
1406                         defaultAttributeConsumed = false;
1407                         currentQName = null;
1408                         return reader.MoveToElement ();
1409                 }
1410
1411                 public override bool MoveToFirstAttribute ()
1412                 {
1413                         switch (reader.NodeType) {
1414                         case XmlNodeType.XmlDeclaration:
1415                         case XmlNodeType.DocumentType:
1416                                 return reader.MoveToFirstAttribute ();
1417                         }
1418
1419                         currentQName = null;
1420                         if (this.nonDefaultAttributeCount > 0) {
1421                                 bool b = reader.MoveToFirstAttribute ();
1422                                 if (b) {
1423                                         currentDefaultAttribute = -1;
1424                                         defaultAttributeConsumed = false;
1425                                 }
1426                                 return b;
1427                         }
1428
1429                         if (this.defaultAttributes.Length > 0) {
1430                                 currentDefaultAttribute = 0;
1431                                 defaultAttributeConsumed = false;
1432                                 return true;
1433                         }
1434                         else
1435                                 return false;
1436                 }
1437
1438                 public override bool MoveToNextAttribute ()
1439                 {
1440                         switch (reader.NodeType) {
1441                         case XmlNodeType.XmlDeclaration:
1442                         case XmlNodeType.DocumentType:
1443                                 return reader.MoveToNextAttribute ();
1444                         }
1445
1446                         currentQName = null;
1447                         if (currentDefaultAttribute >= 0) {
1448                                 if (defaultAttributes.Length == currentDefaultAttribute + 1)
1449                                         return false;
1450                                 currentDefaultAttribute++;
1451                                 defaultAttributeConsumed = false;
1452                                 return true;
1453                         }
1454
1455                         bool b = reader.MoveToNextAttribute ();
1456                         if (b) {
1457                                 currentDefaultAttribute = -1;
1458                                 defaultAttributeConsumed = false;
1459                                 return true;
1460                         }
1461
1462                         if (defaultAttributes.Length > 0) {
1463                                 currentDefaultAttribute = 0;
1464                                 defaultAttributeConsumed = false;
1465                                 return true;
1466                         }
1467                         else
1468                                 return false;
1469                 }
1470
1471                 private void ExamineAdditionalSchema ()
1472                 {
1473                         XmlSchema schema = null;
1474                         string schemaLocation = reader.GetAttribute ("schemaLocation", XmlSchema.InstanceNamespace);
1475                         if (schemaLocation != null) {
1476                                 string [] tmp = XmlSchemaDatatype.FromName ("NMTOKENS").ParseValue (schemaLocation, NameTable, null) as string [];
1477                                 if (tmp.Length % 2 != 0)
1478                                         HandleError ("Invalid schemaLocation attribute format.");
1479                                 for (int i = 0; i < tmp.Length; i += 2) {
1480                                         try {
1481                                                 Uri absUri = new Uri ((this.BaseURI != "" ? new Uri (BaseURI) : null), tmp [i + 1]);
1482                                                 XmlTextReader xtr = new XmlTextReader (absUri.ToString ());
1483                                                 schema = XmlSchema.Read (xtr, null);
1484                                         } catch (Exception) { // FIXME: (wishlist) It is bad manner ;-(
1485                                                 continue;
1486                                         }
1487                                         if (schema.TargetNamespace == null)
1488                                                 schema.TargetNamespace = tmp [i];
1489                                         else if (schema.TargetNamespace != tmp [i])
1490                                                 HandleError ("Specified schema has different target namespace.");
1491                                 }
1492                         }
1493                         if (schema != null) {
1494                                 try {
1495                                         schemas.Add (schema);
1496                                 } catch (XmlSchemaException ex) {
1497                                         HandleError (ex);
1498                                 }
1499                         }
1500                         schema = null;
1501                         string noNsSchemaLocation = reader.GetAttribute ("noNamespaceSchemaLocation", XmlSchema.InstanceNamespace);
1502                         if (noNsSchemaLocation != null) {
1503                                 try {
1504                                         Uri absUri = new Uri ((this.BaseURI != "" ? new Uri (BaseURI) : null), noNsSchemaLocation);
1505                                         XmlTextReader xtr = new XmlTextReader (absUri.ToString ());
1506                                         schema = XmlSchema.Read (xtr, null);
1507                                 } catch (Exception) { // FIXME: (wishlist) It is bad manner ;-(
1508                                 }
1509                                 if (schema != null && schema.TargetNamespace != null)
1510                                         HandleError ("Specified schema has different target namespace.");
1511                         }
1512                         if (schema != null) {
1513                                 try {
1514                                         schemas.Add (schema);
1515                                 } catch (XmlSchemaException ex) {
1516                                         HandleError (ex);
1517                                 }
1518                         }
1519                 }
1520
1521                 public override bool Read ()
1522                 {
1523                         nonDefaultAttributeCount = 0;
1524                         currentDefaultAttribute = -1;
1525                         defaultAttributeConsumed = false;
1526                         currentQName = null;
1527                         thisElementId = null;
1528                         defaultAttributes = new XmlSchemaAttribute [0];
1529                         if (popContext) {
1530                                 elementQNameStack.RemoveAt (elementQNameStack.Count - 1);
1531                                 popContext = false;
1532                         }
1533
1534                         bool result = reader.Read ();
1535                         // 3.3.4 ElementLocallyValidElement 7 = Root Valid.
1536                         if (!result && missingIDReferences.Count > 0)
1537                                 HandleError ("There are missing ID references: " +
1538                                         String.Join (" ",
1539                                         this.missingIDReferences.ToArray (typeof (string)) as string []));
1540
1541                         switch (reader.NodeType) {
1542                         case XmlNodeType.Element:
1543                                 nonDefaultAttributeCount = reader.AttributeCount;
1544
1545                                 if (reader.Depth == 0)
1546                                         ExamineAdditionalSchema ();
1547
1548                                 this.elementQNameStack.Add (new XmlQualifiedName (reader.LocalName, reader.NamespaceURI));
1549
1550                                 // If there is no schema information, then no validation is performed.
1551                                 if (schemas.Count == 0)
1552                                         break;
1553
1554 //                              context.Load (reader.Depth);
1555                                 if (skipValidationDepth < 0 || reader.Depth <= skipValidationDepth) {
1556                                         if (shouldValidateCharacters) {
1557                                                 ValidateEndCharacters ();
1558                                                 shouldValidateCharacters = false;
1559                                         }
1560                                         AssessStartElementSchemaValidity ();
1561                                         storedCharacters.Length = 0;
1562                                 } else {
1563                                         context.Clear ();
1564                                 }
1565
1566                                 if (reader.IsEmptyElement)
1567                                         goto case XmlNodeType.EndElement;
1568                                 else
1569                                         shouldValidateCharacters = true;
1570                                 break;
1571                         case XmlNodeType.EndElement:
1572                                 if (reader.Depth == skipValidationDepth) {
1573                                         skipValidationDepth = -1;
1574                                         context.Clear ();
1575                                 } else {
1576 //                                      context.Load (reader.Depth);
1577                                         if (shouldValidateCharacters) {
1578                                                 ValidateEndCharacters ();
1579                                                 shouldValidateCharacters = false;
1580                                         }
1581                                         AssessEndElementSchemaValidity ();
1582                                 }
1583                                 storedCharacters.Length = 0;
1584                                 childParticleState = null;
1585                                 popContext = true;
1586                                 break;
1587
1588                         case XmlNodeType.CDATA:
1589                         case XmlNodeType.SignificantWhitespace:
1590                         case XmlNodeType.Text:
1591                                 XmlSchemaComplexType ct = context.ActualType as XmlSchemaComplexType;
1592                                 if (ct != null && storedCharacters.Length > 0) {
1593                                         switch (ct.ContentType) {
1594                                         case XmlSchemaContentType.ElementOnly:
1595                                         case XmlSchemaContentType.Empty:
1596                                                 HandleError ("Not allowed character content was found.");
1597                                                 break;
1598                                         }
1599                                 }
1600
1601                                 ValidateCharacters ();
1602                                 break;
1603                         }
1604
1605                         return result;
1606                 }
1607
1608                 public override bool ReadAttributeValue ()
1609                 {
1610                         if (currentDefaultAttribute < 0)
1611                                 return reader.ReadAttributeValue ();
1612
1613                         if (this.defaultAttributeConsumed)
1614                                 return false;
1615
1616                         defaultAttributeConsumed = true;
1617                         return true;
1618                 }
1619
1620 #if NET_1_0
1621                 public override string ReadInnerXml ()
1622                 {
1623                         // MS.NET 1.0 has a serious bug here. It skips validation.
1624                         return reader.ReadInnerXml ();
1625                 }
1626
1627                 public override string ReadOuterXml ()
1628                 {
1629                         // MS.NET 1.0 has a serious bug here. It skips validation.
1630                         return reader.ReadOuterXml ();
1631                 }
1632 #endif
1633
1634                 // XmlReader.ReadString() should call derived this.Read().
1635                 public override string ReadString ()
1636                 {
1637 #if NET_1_0
1638                         return reader.ReadString ();
1639 #else
1640                         return base.ReadString ();
1641 #endif
1642                 }
1643
1644                 // This class itself does not have this feature.
1645                 public override void ResolveEntity ()
1646                 {
1647                         reader.ResolveEntity ();
1648                 }
1649
1650                 internal class XsdValidationContext
1651                 {
1652                         Hashtable contextStack;
1653
1654                         public XsdValidationContext ()
1655                         {
1656                                 contextStack = new Hashtable ();
1657                         }
1658
1659                         // Some of them might be missing (See the spec section 5.3, and also 3.3.4).
1660                         public XmlSchemaElement Element;
1661                         public XsdValidationState ParticleState;
1662                         public XmlSchemaAttribute [] DefaultAttributes;
1663
1664                         // Some of them might be missing (See the spec section 5.3).
1665                         public object SchemaType;
1666
1667                         public object LocalTypeDefinition;
1668
1669                         public object ActualType {
1670                                 get {
1671                                         if (LocalTypeDefinition != null)
1672                                                 return LocalTypeDefinition;
1673                                         else
1674                                                 return SchemaType;
1675                                 }
1676                         }
1677
1678                         public void Clear ()
1679                         {
1680                                 Element = null;
1681                                 SchemaType = null;
1682                                 ParticleState = null;
1683                                 LocalTypeDefinition = null;
1684                         }
1685
1686                         public void PushScope (int depth)
1687                         {
1688                                 contextStack [depth] = this.MemberwiseClone ();
1689                         }
1690
1691                         public void PopScope (int depth)
1692                         {
1693                                 Load (depth);
1694                                 contextStack.Remove (depth + 1);
1695                         }
1696
1697                         public void Load (int depth)
1698                         {
1699                                 Clear ();
1700                                 XsdValidationContext restored = (XsdValidationContext) contextStack [depth];
1701                                 if (restored != null) {
1702                                         this.Element = restored.Element;
1703                                         this.ParticleState = restored.ParticleState;
1704                                         this.SchemaType = restored.SchemaType;
1705                                         this.LocalTypeDefinition = restored.LocalTypeDefinition;
1706                                 }
1707                         }
1708                 }
1709
1710                 /*
1711                 internal class XsdValidityState
1712                 {
1713                         ArrayList currentParticles = new ArrayList ();
1714                         ArrayList occured = new ArrayList ();
1715                         Hashtable xsAllConsumed = new Hashtable ();
1716                         XmlSchemaParticle parciele;
1717                         int particleDepth;
1718
1719                         public XsdValidityState (XmlSchemaParticle particle)
1720                         {
1721                                 this.parciele = particle;
1722                                 currentParticles.Add (particle);
1723                         }
1724
1725                 }
1726                 */
1727         }
1728
1729 }