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