2 // Mono.Xml.Schema.XsdValidatingReader.cs
5 // Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
7 // (C)2003 Atsushi Enomoto
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.
15 using System.Collections;
16 using System.Collections.Specialized;
19 using System.Xml.Schema;
22 namespace Mono.Xml.Schema
24 public class XsdValidatingReader : XmlReader, IXmlLineInfo, IHasXmlSchemaInfo, IHasXmlParserContext
26 static char [] wsChars = new char [] {' ', '\t', '\n', '\r'};
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;
37 Hashtable idList = new Hashtable ();
38 ArrayList missingIDReferences = new ArrayList ();
41 ArrayList keyTables = new ArrayList ();
42 ArrayList currentKeyFieldConsumers = new ArrayList ();
44 XsdValidationStateManager stateManager = new XsdValidationStateManager ();
45 XsdValidationContext context = new XsdValidationContext ();
46 XsdValidationState childParticleState;
49 StringBuilder storedCharacters = new StringBuilder ();
50 bool shouldValidateCharacters;
51 int skipValidationDepth = -1;
53 XmlSchemaAttribute [] defaultAttributes = new XmlSchemaAttribute [0];
54 int currentDefaultAttribute = -1;
55 XmlQualifiedName currentQName;
57 ArrayList elementQNameStack = new ArrayList ();
61 int nonDefaultAttributeCount;
62 bool defaultAttributeConsumed;
64 // Validation engine cached object
65 ArrayList defaultAttributesCache = new ArrayList ();
66 ArrayList tmpKeyrefPool = new ArrayList ();
69 public XsdValidatingReader (XmlReader reader)
74 public XsdValidatingReader (XmlReader reader, XmlReader validatingReader)
77 xvReader = validatingReader as XmlValidatingReader;
78 if (xvReader != null) {
79 if (xvReader.ValidationType == ValidationType.None)
80 reportNoValidationError = true;
82 readerLineInfo = reader as IXmlLineInfo;
83 sourceReaderSchemaInfo = reader as IHasXmlSchemaInfo;
87 private XmlQualifiedName CurrentQName {
89 if (currentQName == null)
90 currentQName = new XmlQualifiedName (LocalName, NamespaceURI);
95 internal ArrayList CurrentKeyFieldConsumers {
96 get { return currentKeyFieldConsumers; }
99 // Public Non-overrides
101 public int XsiNilDepth {
102 get { return xsiNilDepth; }
105 public bool Namespaces {
106 get { return namespaces; }
107 set { namespaces = value; }
110 public XmlReader Reader {
111 get { return reader; }
114 // This should be changed before the first Read() call.
115 public XmlSchemaCollection Schemas {
116 get { return schemas; }
119 public object SchemaType {
121 if (ReadState != ReadState.Interactive)
125 case XmlNodeType.Element:
126 if (context.ActualType != null)
127 return context.ActualType;
128 else if (context.Element != null)
129 return context.Element.ElementType;
131 return SourceReaderSchemaType;
132 case XmlNodeType.Attribute:
133 XmlSchemaComplexType ct = context.ActualType as XmlSchemaComplexType;
135 XmlSchemaAttribute attdef = ct.AttributeUses [CurrentQName] as XmlSchemaAttribute;
137 return attdef.AttributeType;
139 return SourceReaderSchemaType;
141 return SourceReaderSchemaType;
146 private object SourceReaderSchemaType {
147 get { return this.sourceReaderSchemaInfo != null ? sourceReaderSchemaInfo.SchemaType : null; }
150 // This property is never used in Mono.
151 public ValidationType ValidationType {
153 if (reportNoValidationError)
154 return ValidationType.None;
156 return ValidationType.Schema;
160 // It is used only for independent XmlReader use, not for XmlValidatingReader.
161 public object ReadTypedValue ()
163 XmlSchemaDatatype dt = SchemaType as XmlSchemaDatatype;
164 XmlSchemaSimpleType st = SchemaType as XmlSchemaSimpleType;
171 case XmlNodeType.Element:
175 storedCharacters.Length = 0;
180 case XmlNodeType.SignificantWhitespace:
181 case XmlNodeType.Text:
182 case XmlNodeType.CDATA:
183 storedCharacters.Append (Value);
185 case XmlNodeType.Comment:
191 } while (loop && !EOF);
192 return dt.ParseValue (storedCharacters.ToString (), NameTable, ParserContext.NamespaceManager);
193 case XmlNodeType.Attribute:
194 return dt.ParseValue (Value, NameTable, ParserContext.NamespaceManager);
200 public ValueType ReadTypedValueType ()
202 XmlSchemaDatatype dt = SchemaType as XmlSchemaDatatype;
203 XmlSchemaSimpleType st = SchemaType as XmlSchemaSimpleType;
210 case XmlNodeType.Element:
214 storedCharacters.Length = 0;
219 case XmlNodeType.SignificantWhitespace:
220 case XmlNodeType.Text:
221 case XmlNodeType.CDATA:
222 storedCharacters.Append (Value);
224 case XmlNodeType.Comment:
230 } while (loop && !EOF);
231 return dt.ParseValueType (storedCharacters.ToString (), NameTable, ParserContext.NamespaceManager);
232 case XmlNodeType.Attribute:
233 return dt.ParseValueType (Value, NameTable, ParserContext.NamespaceManager);
239 public ValidationEventHandler ValidationEventHandler;
241 // Public Overrided Properties
243 public override int AttributeCount {
246 if (NodeType == XmlNodeType.Element)
247 return attributeCount;
251 return reader.AttributeCount;
253 return nonDefaultAttributeCount + defaultAttributes.Length;
257 public override string BaseURI {
258 get { return reader.BaseURI; }
261 // If this class is used to implement XmlValidatingReader,
262 // it should be left to DTDValidatingReader. In other cases,
263 // it depends on the reader's ability.
264 public override bool CanResolveEntity {
265 get { return reader.CanResolveEntity; }
268 public override int Depth {
270 if (currentDefaultAttribute < 0)
272 if (this.defaultAttributeConsumed)
273 return reader.Depth + 2;
274 return reader.Depth + 1;
278 public override bool EOF {
279 get { return reader.EOF; }
282 public override bool HasValue {
284 if (currentDefaultAttribute < 0)
285 return reader.HasValue;
290 public override bool IsDefault {
292 if (currentDefaultAttribute < 0)
293 return reader.IsDefault;
298 public override bool IsEmptyElement {
300 if (currentDefaultAttribute < 0)
301 return reader.IsEmptyElement;
306 public override string this [int i] {
307 get { return GetAttribute (i); }
310 public override string this [string name] {
311 get { return GetAttribute (name); }
314 public override string this [string localName, string ns] {
315 get { return GetAttribute (localName, ns); }
318 int IXmlLineInfo.LineNumber {
319 get { return readerLineInfo != null ? readerLineInfo.LineNumber : 0; }
322 int IXmlLineInfo.LinePosition {
323 get { return readerLineInfo != null ? readerLineInfo.LinePosition : 0; }
326 public override string LocalName {
328 if (currentDefaultAttribute < 0)
329 return reader.LocalName;
330 if (defaultAttributeConsumed)
332 return defaultAttributes [currentDefaultAttribute].QualifiedName.Name;
336 public override string Name {
338 if (currentDefaultAttribute < 0)
340 if (defaultAttributeConsumed)
343 XmlQualifiedName qname = defaultAttributes [currentDefaultAttribute].QualifiedName;
344 string prefix = Prefix;
345 if (prefix == String.Empty)
348 return String.Concat (prefix, ":", qname.Name);
352 public override string NamespaceURI {
354 if (currentDefaultAttribute < 0)
355 return reader.NamespaceURI;
356 if (defaultAttributeConsumed)
358 return defaultAttributes [currentDefaultAttribute].QualifiedName.Namespace;
362 public override XmlNameTable NameTable {
363 get { return reader.NameTable; }
366 public override XmlNodeType NodeType {
368 if (currentDefaultAttribute < 0)
369 return reader.NodeType;
370 if (defaultAttributeConsumed)
371 return XmlNodeType.Text;
372 return XmlNodeType.Attribute;
376 public XmlParserContext ParserContext {
377 get { return XmlSchemaUtil.GetParserContext (reader); }
380 public override string Prefix {
382 if (currentDefaultAttribute < 0)
383 return reader.Prefix;
384 if (defaultAttributeConsumed)
386 XmlQualifiedName qname = defaultAttributes [currentDefaultAttribute].QualifiedName;
387 string prefix = this.ParserContext.NamespaceManager.LookupPrefix (qname.Namespace);
395 public override char QuoteChar {
396 get { return reader.QuoteChar; }
399 public override ReadState ReadState {
400 get { return reader.ReadState; }
403 public override string Value {
405 if (currentDefaultAttribute < 0)
407 string value = defaultAttributes [currentDefaultAttribute].ValidatedDefaultValue;
409 value = defaultAttributes [currentDefaultAttribute].ValidatedFixedValue;
414 XmlQualifiedName qnameXmlLang = new XmlQualifiedName ("lang", XmlNamespaceManager.XmlnsXml);
416 public override string XmlLang {
418 string xmlLang = reader.XmlLang;
421 int idx = this.FindDefaultAttribute ("lang", XmlNamespaceManager.XmlnsXml);
424 xmlLang = defaultAttributes [idx].ValidatedDefaultValue;
426 xmlLang = defaultAttributes [idx].ValidatedFixedValue;
431 public override XmlSpace XmlSpace {
433 XmlSpace space = reader.XmlSpace;
434 if (space != XmlSpace.None)
436 int idx = this.FindDefaultAttribute ("space", XmlNamespaceManager.XmlnsXml);
438 return XmlSpace.None;
439 string spaceSpec = defaultAttributes [idx].ValidatedDefaultValue;
440 if (spaceSpec == null)
441 spaceSpec = defaultAttributes [idx].ValidatedFixedValue;
442 return (XmlSpace) Enum.Parse (typeof (XmlSpace), spaceSpec, false);
448 private XmlQualifiedName QualifyName (string name)
450 int colonAt = name.IndexOf (':');
452 return new XmlQualifiedName (name, null);
454 return new XmlQualifiedName (name.Substring (colonAt + 1),
455 LookupNamespace (name.Substring (0, colonAt)));
458 private void HandleError (string error)
460 HandleError (error, null);
463 private void HandleError (string error, Exception innerException)
465 if (reportNoValidationError) // extra quick check
468 XmlSchemaException schemaException = new XmlSchemaException (error,
469 this, this.BaseURI, null, innerException);
470 HandleError (schemaException);
473 private void HandleError (XmlSchemaException schemaException)
475 if (reportNoValidationError)
478 ValidationEventArgs e = new ValidationEventArgs (schemaException,
479 schemaException.Message, XmlSeverityType.Error);
481 if (this.ValidationEventHandler != null)
482 this.ValidationEventHandler (this, e);
483 else if (xvReader != null)
484 xvReader.OnValidationEvent (this, e);
485 else if (e.Severity == XmlSeverityType.Error)
487 this.xvReader.OnValidationEvent (this, e);
493 private XmlSchemaElement FindElement (string name, string ns)
495 foreach (XmlSchema target in schemas) {
496 XmlSchema matches = target.Schemas [ns];
497 if (matches != null) {
498 XmlSchemaElement result = target.Elements [new XmlQualifiedName (name, ns)] as XmlSchemaElement;
506 private XmlSchemaType FindType (XmlQualifiedName qname)
508 foreach (XmlSchema target in schemas) {
509 XmlSchemaType type = target.SchemaTypes [qname] as XmlSchemaType;
516 private void ValidateStartElementParticle ()
518 stateManager.CurrentElement = null;
519 context.ParticleState = context.ParticleState.EvaluateStartElement (reader.LocalName, reader.NamespaceURI);
520 if (context.ParticleState == XsdValidationState.Invalid)
521 HandleError ("Invalid start element: " + reader.NamespaceURI + ":" + reader.LocalName);
523 context.Element = stateManager.CurrentElement;
524 if (context.Element != null)
525 context.SchemaType = context.Element.ElementType;
528 private void ValidateEndElementParticle ()
530 if (childParticleState != null) {
531 if (!childParticleState.EvaluateEndElement ()) {
532 HandleError ("Invalid end element: " + reader.Name);
535 context.PopScope (reader.Depth);
538 // Utility for missing validation completion related to child items.
539 private void ValidateCharacters ()
541 // TODO: value context validation here.
542 if (xsiNilDepth >= 0 && xsiNilDepth < reader.Depth)
543 HandleError ("Element item appeared, while current element context is nil.");
545 storedCharacters.Append (reader.Value);
548 // Utility for missing validation completion related to child items.
549 private void ValidateEndCharacters ()
551 if (context.ActualType == null)
554 string value = storedCharacters.ToString ();
556 if (storedCharacters.Length == 0) {
557 // 3.3.4 Element Locally Valid (Element) 5.1.2
558 // TODO: check entire DefaultValid (3.3.6)
559 if (context.Element != null) {
560 if (context.Element.ValidatedDefaultValue != null)
561 value = context.Element.ValidatedDefaultValue;
565 XmlSchemaDatatype dt = context.ActualType as XmlSchemaDatatype;
566 XmlSchemaSimpleType st = context.ActualType as XmlSchemaSimpleType;
571 XmlSchemaComplexType ct = context.ActualType as XmlSchemaComplexType;
573 switch (ct.ContentType) {
574 case XmlSchemaContentType.ElementOnly:
575 case XmlSchemaContentType.Empty:
576 if (storedCharacters.Length > 0)
577 HandleError ("Character content not allowed.");
583 // 3.3.4 Element Locally Valid (Element) :: 5.2.2.2. Fixed value constraints
584 if (context.Element != null && context.Element.ValidatedFixedValue != null)
585 if (value != context.Element.ValidatedFixedValue)
586 HandleError ("Fixed value constraint was not satisfied.");
587 AssessStringValid (st, dt, value);
590 // Identity field value
591 while (this.currentKeyFieldConsumers.Count > 0) {
592 XsdKeyEntryField field = this.currentKeyFieldConsumers [0] as XsdKeyEntryField;
593 if (field.Identity != null)
594 HandleError ("Two or more identical field was found. Former value is '" + field.Identity + "' .");
595 object identity = null; // This means empty value
598 identity = dt.ParseValue (value, NameTable, ParserContext.NamespaceManager);
599 } catch (Exception ex) { // FIXME: (wishlist) This is bad manner ;-(
600 HandleError ("Identity value is invalid against its data type " + dt.TokenizedType, ex);
603 if (identity == null)
606 if (!field.SetIdentityField (identity, reader.Depth == xsiNilDepth, dt as XsdAnySimpleType, this))
607 HandleError ("Two or more identical key value was found: '" + value + "' .");
608 this.currentKeyFieldConsumers.RemoveAt (0);
611 shouldValidateCharacters = false;
614 // 3.14.4 String Valid
615 private void AssessStringValid (XmlSchemaSimpleType st,
616 XmlSchemaDatatype dt, string value)
618 XmlSchemaDatatype validatedDatatype = dt;
620 string normalized = validatedDatatype.Normalize (value);
622 XmlSchemaDatatype itemDatatype;
623 XmlSchemaSimpleType itemSimpleType;
624 switch (st.DerivedBy) {
625 case XmlSchemaDerivationMethod.List:
626 XmlSchemaSimpleTypeList listContent = st.Content as XmlSchemaSimpleTypeList;
627 values = normalized.Split (wsChars);
628 itemDatatype = listContent.ValidatedListItemType as XmlSchemaDatatype;
629 itemSimpleType = listContent.ValidatedListItemType as XmlSchemaSimpleType;
630 foreach (string each in values) {
631 if (each == String.Empty)
633 // validate against ValidatedItemType
634 if (itemDatatype != null) {
636 itemDatatype.ParseValue (each, NameTable, ParserContext.NamespaceManager);
637 } catch (Exception ex) { // FIXME: (wishlist) better exception handling ;-(
638 HandleError ("List type value contains one or more invalid values.", ex);
643 AssessStringValid (itemSimpleType, itemSimpleType.Datatype, each);
646 case XmlSchemaDerivationMethod.Union:
647 XmlSchemaSimpleTypeUnion union = st.Content as XmlSchemaSimpleTypeUnion;
649 string each = normalized;
650 // validate against ValidatedItemType
652 foreach (object eachType in union.ValidatedTypes) {
653 itemDatatype = eachType as XmlSchemaDatatype;
654 itemSimpleType = eachType as XmlSchemaSimpleType;
655 if (itemDatatype != null) {
657 itemDatatype.ParseValue (each, NameTable, ParserContext.NamespaceManager);
658 } catch (Exception) { // FIXME: (wishlist) better exception handling ;-(
664 AssessStringValid (itemSimpleType, itemSimpleType.Datatype, each);
665 } catch (XmlSchemaException) {
673 HandleError ("Union type value contains one or more invalid values.");
678 case XmlSchemaDerivationMethod.Restriction:
679 XmlSchemaSimpleTypeRestriction str = st.Content as XmlSchemaSimpleTypeRestriction;
682 /* Don't forget to validate against inherited type's facets
683 * Could we simplify this by assuming that the basetype will also
686 // mmm, will check later.
687 XmlSchemaSimpleType baseType = st.BaseXmlSchemaType as XmlSchemaSimpleType;
688 if (baseType != null) {
689 AssessStringValid(baseType, dt, normalized);
691 if (!str.ValidateValueWithFacets (normalized, NameTable)) {
692 HandleError ("Specified value was invalid against the facets.");
696 validatedDatatype = st.Datatype;
700 if (validatedDatatype != null) {
702 validatedDatatype.ParseValue (value, NameTable, ParserContext.NamespaceManager);
703 } catch (Exception ex) { // FIXME: (wishlist) It is bad manner ;-(
704 HandleError ("Invalidly typed data was specified.", ex);
709 private object GetLocalTypeDefinition (string name)
711 object xsiType = null;
712 XmlQualifiedName typeQName = QualifyName (name);
713 if (typeQName.Namespace == XmlSchema.Namespace) {
714 if (typeQName.Name == "anyType")
715 xsiType = XmlSchemaComplexType.AnyType;
717 xsiType = XmlSchemaDatatype.FromName (typeQName);
720 xsiType = FindType (typeQName);
724 // It is common to ElementLocallyValid::4 and SchemaValidityAssessment::1.2.1.2.4
725 private void AssessLocalTypeDerivationOK (object xsiType, object baseType, XmlSchemaDerivationMethod flag)
727 XmlSchemaType xsiSchemaType = xsiType as XmlSchemaType;
728 XmlSchemaComplexType baseComplexType = baseType as XmlSchemaComplexType;
729 XmlSchemaComplexType xsiComplexType = xsiSchemaType as XmlSchemaComplexType;
730 if (xsiType != baseType) {
731 // Extracted (not extraneous) check for 3.4.6 TypeDerivationOK.
732 if (baseComplexType != null)
733 flag |= baseComplexType.BlockResolved;
734 if (flag == XmlSchemaDerivationMethod.All) {
735 HandleError ("Prohibited element type substitution.");
737 } else if (xsiSchemaType != null && (flag & xsiSchemaType.DerivedBy) != 0) {
738 HandleError ("Prohibited element type substitution.");
743 if (xsiComplexType != null)
745 xsiComplexType.ValidateTypeDerivationOK (baseType, null, null);
746 } catch (XmlSchemaException ex) {
747 // HandleError ("Locally specified schema complex type derivation failed. " + ex.Message, ex);
751 XmlSchemaSimpleType xsiSimpleType = xsiType as XmlSchemaSimpleType;
752 if (xsiSimpleType != null) {
754 xsiSimpleType.ValidateTypeDerivationOK (baseType, null, null, true);
755 } catch (XmlSchemaException ex) {
756 // HandleError ("Locally specified schema simple type derivation failed. " + ex.Message, ex);
760 else if (xsiType is XmlSchemaDatatype) {
764 HandleError ("Primitive data type cannot be derived type using xsi:type specification.");
768 // Section 3.3.4 of the spec.
769 private void AssessStartElementSchemaValidity ()
771 // If the reader is inside xsi:nil (and failed on validation),
772 // then simply skip its content.
773 if (xsiNilDepth >= 0 && xsiNilDepth < reader.Depth)
774 HandleError ("Element item appeared, while current element context is nil.");
776 context.Load (reader.Depth);
777 if (childParticleState != null) {
778 context.ParticleState = childParticleState;
779 childParticleState = null;
782 // If validation state exists, then first assess particle validity.
783 if (context.ParticleState != null) {
784 ValidateStartElementParticle ();
787 string xsiNilValue = reader.GetAttribute ("nil", XmlSchema.InstanceNamespace);
788 if (xsiNilValue != null)
789 xsiNilValue = xsiNilValue.Trim (XmlChar.WhitespaceChars);
790 bool isXsiNil = xsiNilValue == "true";
791 if (isXsiNil && this.xsiNilDepth < 0)
792 xsiNilDepth = reader.Depth;
794 // [Schema Validity Assessment (Element) 1.2]
795 // Evaluate "local type definition" from xsi:type.
796 // (See spec 3.3.4 Schema Validity Assessment (Element) 1.2.1.2.3.
797 // Note that Schema Validity Assessment(Element) 1.2 takes
798 // precedence than 1.1 of that.
800 string xsiTypeName = reader.GetAttribute ("type", XmlSchema.InstanceNamespace);
801 if (xsiTypeName != null) {
802 xsiTypeName = xsiTypeName.Trim (XmlChar.WhitespaceChars);
803 object xsiType = GetLocalTypeDefinition (xsiTypeName);
805 HandleError ("The instance type was not found: " + xsiTypeName + " .");
807 XmlSchemaType xsiSchemaType = xsiType as XmlSchemaType;
808 if (xsiSchemaType != null && this.context.Element != null) {
809 XmlSchemaType elemBaseType = context.Element.ElementType as XmlSchemaType;
810 if (elemBaseType != null && (xsiSchemaType.DerivedBy & elemBaseType.FinalResolved) != 0)
811 HandleError ("The instance type is prohibited by the type of the context element.");
812 if (elemBaseType != xsiType && (xsiSchemaType.DerivedBy & this.context.Element.BlockResolved) != 0)
813 HandleError ("The instance type is prohibited by the context element.");
815 XmlSchemaComplexType xsiComplexType = xsiType as XmlSchemaComplexType;
816 if (xsiComplexType != null && xsiComplexType.IsAbstract)
817 HandleError ("The instance type is abstract: " + xsiTypeName + " .");
819 // If current schema type exists, then this xsi:type must be
820 // valid extension of that type. See 1.2.1.2.4.
821 if (context.Element != null) {
822 // FIXME: supply *correct* base type
823 AssessLocalTypeDerivationOK (xsiType, context.Element.ElementType, context.Element.BlockResolved);
825 AssessStartElementLocallyValidType (xsiType); // 1.2.2:
826 context.LocalTypeDefinition = xsiType;
831 // Create Validation Root, if not exist.
832 // [Schema Validity Assessment (Element) 1.1]
833 if (context.Element == null)
834 context.Element = FindElement (reader.LocalName, reader.NamespaceURI);
835 if (context.Element != null) {
836 if (xsiTypeName == null) {
837 context.SchemaType = context.Element.ElementType;
838 AssessElementLocallyValidElement (context.Element, xsiNilValue); // 1.1.2
842 switch (stateManager.ProcessContents) {
843 case XmlSchemaContentProcessing.Skip:
845 case XmlSchemaContentProcessing.Lax:
847 schema = schemas [reader.NamespaceURI];
848 if (schema != null && !schema.missedSubComponents)
849 HandleError ("Element declaration for " + reader.LocalName + " is missing.");
853 schema = schemas [reader.NamespaceURI];
854 if (xsiTypeName == null && (schema == null || !schema.missedSubComponents))
855 HandleError ("Element declaration for " + reader.LocalName + " is missing.");
860 if (stateManager.ProcessContents == XmlSchemaContentProcessing.Skip)
861 skipValidationDepth = reader.Depth;
863 // Finally, create child particle state.
864 XmlSchemaComplexType xsComplexType = SchemaType as XmlSchemaComplexType;
865 if (xsComplexType != null)
866 childParticleState = stateManager.Create (xsComplexType.ValidatableParticle);
867 else if (stateManager.ProcessContents == XmlSchemaContentProcessing.Lax)
868 childParticleState = stateManager.Create (XmlSchemaAny.AnyTypeContent);
870 childParticleState = stateManager.Create (XmlSchemaParticle.Empty);
872 AssessStartIdentityConstraints ();
874 context.PushScope (reader.Depth);
877 // 3.3.4 Element Locally Valid (Element)
878 private void AssessElementLocallyValidElement (XmlSchemaElement element, string xsiNilValue)
880 XmlQualifiedName qname = new XmlQualifiedName (reader.LocalName, reader.NamespaceURI);
883 HandleError ("Element declaration is required for " + qname);
885 if (element.ActualIsAbstract)
886 HandleError ("Abstract element declaration was specified for " + qname);
888 if (!element.ActualIsNillable && xsiNilValue != null)
889 HandleError ("This element declaration is not nillable: " + qname);
891 // Note that 3.2.1 xsi:nil constraints are to be validated in
892 else if (xsiNilValue == "true") {
893 // AssessElementSchemaValidity() and ValidateCharacters()
895 if (element.ValidatedFixedValue != null)
896 HandleError ("Schema instance nil was specified, where the element declaration for " + qname + "has fixed value constraints.");
899 string xsiType = reader.GetAttribute ("type", XmlSchema.InstanceNamespace);
900 if (xsiType != null) {
901 context.LocalTypeDefinition = GetLocalTypeDefinition (xsiType);
902 AssessLocalTypeDerivationOK (context.LocalTypeDefinition, element.ElementType, element.BlockResolved);
905 // 5 Not all things cannot be assessed here.
906 // It is common to 5.1 and 5.2
907 if (element.ElementType != null)
908 AssessStartElementLocallyValidType (SchemaType);
910 // 6. should be out from here.
911 // See invokation of AssessStartIdentityConstraints().
913 // 7 is going to be validated in Read() (in case of xmlreader's EOF).
916 // 3.3.4 Element Locally Valid (Type)
917 private void AssessStartElementLocallyValidType (object schemaType)
919 if (schemaType == null) { // 1.
920 HandleError ("Schema type does not exist.");
923 XmlSchemaComplexType cType = schemaType as XmlSchemaComplexType;
924 XmlSchemaSimpleType sType = schemaType as XmlSchemaSimpleType;
927 while (reader.MoveToNextAttribute ()) {
928 if (reader.NamespaceURI == XmlNamespaceManager.XmlnsXmlns)
930 if (reader.NamespaceURI != XmlSchema.InstanceNamespace)
931 HandleError ("Current simple type cannot accept attributes other than schema instance namespace.");
932 switch (reader.LocalName) {
935 case "schemaLocation":
936 case "noNamespaceSchemaLocation":
939 HandleError ("Unknown schema instance namespace attribute: " + reader.LocalName);
943 reader.MoveToElement ();
944 // 3.1.2 and 3.1.3 cannot be assessed here.
945 } else if (cType != null) {
946 if (cType.IsAbstract) { // 2.
947 HandleError ("Target complex type is abstract.");
951 AssessElementLocallyValidComplexType (cType);
955 // 3.4.4 Element Locally Valid (Complex Type)
956 // TODO ("wild IDs constraints.")
957 private void AssessElementLocallyValidComplexType (XmlSchemaComplexType cType)
960 if (cType.IsAbstract)
961 HandleError ("Target complex type is abstract.");
963 // 2 (xsi:nil and content prohibition)
964 // See AssessStartElementSchemaValidity() and ValidateCharacters()
966 string elementNs = reader.NamespaceURI;
967 // 3. attribute uses and
969 while (reader.MoveToNextAttribute ()) {
970 if (reader.NamespaceURI == "http://www.w3.org/2000/xmlns/")
972 else if (reader.NamespaceURI == XmlSchema.InstanceNamespace)
974 XmlQualifiedName qname = new XmlQualifiedName (reader.LocalName, reader.NamespaceURI);
975 object attMatch = FindAttributeDeclaration (cType, qname, elementNs);
976 if (attMatch == null)
977 HandleError ("Attribute declaration was not found for " + qname);
979 XmlSchemaAttribute attdecl = attMatch as XmlSchemaAttribute;
980 if (attdecl == null) { // i.e. anyAttribute
981 XmlSchemaAnyAttribute anyAttrMatch = attMatch as XmlSchemaAnyAttribute;
983 AssessAttributeLocallyValidUse (attdecl);
984 AssessAttributeLocallyValid (attdecl, true);
988 reader.MoveToElement ();
990 // Collect default attributes.
992 // FIXME: FixedValue check maybe extraneous.
993 foreach (DictionaryEntry entry in cType.AttributeUses) {
994 XmlSchemaAttribute attr = (XmlSchemaAttribute) entry.Value;
995 if (reader [attr.QualifiedName.Name, attr.QualifiedName.Namespace] == null) {
996 if (attr.ValidatedUse == XmlSchemaUse.Required &&
997 attr.ValidatedFixedValue == null)
998 HandleError ("Required attribute " + attr.QualifiedName + " was not found.");
999 else if (attr.ValidatedDefaultValue != null)
1000 defaultAttributesCache.Add (attr);
1001 else if (attr.ValidatedFixedValue != null)
1002 defaultAttributesCache.Add (attr);
1005 defaultAttributes = (XmlSchemaAttribute [])
1006 defaultAttributesCache.ToArray (typeof (XmlSchemaAttribute));
1007 context.DefaultAttributes = defaultAttributes;
1008 defaultAttributesCache.Clear ();
1009 // 5. wild IDs was already checked above.
1012 // Spec 3.10.4 Item Valid (Wildcard)
1013 private bool AttributeWildcardItemValid (XmlSchemaAnyAttribute anyAttr, XmlQualifiedName qname)
1015 if (anyAttr.HasValueAny)
1017 if (anyAttr.HasValueOther && (anyAttr.TargetNamespace == "" || reader.NamespaceURI != anyAttr.TargetNamespace))
1019 if (anyAttr.HasValueTargetNamespace && reader.NamespaceURI == anyAttr.TargetNamespace)
1021 if (anyAttr.HasValueLocal && reader.NamespaceURI == "")
1023 foreach (string ns in anyAttr.ResolvedNamespaces)
1024 if (ns == reader.NamespaceURI)
1029 private XmlSchemaObject FindAttributeDeclaration (XmlSchemaComplexType cType,
1030 XmlQualifiedName qname, string elementNs)
1032 XmlSchemaObject result = cType.AttributeUses [qname];
1035 if (cType.AttributeWildcard == null)
1038 if (!AttributeWildcardItemValid (cType.AttributeWildcard, qname))
1041 if (cType.AttributeWildcard.ProcessContents == XmlSchemaContentProcessing.Skip)
1042 return cType.AttributeWildcard;
1043 foreach (XmlSchema schema in schemas) {
1044 foreach (DictionaryEntry entry in schema.Attributes) {
1045 XmlSchemaAttribute attr = (XmlSchemaAttribute) entry.Value;
1046 if (attr.QualifiedName == qname)
1050 if (cType.AttributeWildcard.ProcessContents == XmlSchemaContentProcessing.Lax)
1051 return cType.AttributeWildcard;
1056 // 3.2.4 Attribute Locally Valid and 3.4.4 - 5.wildIDs
1058 private void AssessAttributeLocallyValid (XmlSchemaAttribute attr, bool checkWildIDs)
1061 switch (reader.NamespaceURI) {
1062 case XmlNamespaceManager.XmlnsXml:
1063 case XmlNamespaceManager.XmlnsXmlns:
1064 case XmlSchema.InstanceNamespace:
1068 if (attr.AttributeType == null)
1069 HandleError ("Attribute type is missing for " + attr.QualifiedName);
1070 XmlSchemaDatatype dt = attr.AttributeType as XmlSchemaDatatype;
1072 dt = ((XmlSchemaSimpleType) attr.AttributeType).Datatype;
1073 // It is a bit heavy process, so let's omit as long as possible ;-)
1074 if (dt != XmlSchemaSimpleType.AnySimpleType || attr.ValidatedFixedValue != null) {
1075 string normalized = dt.Normalize (reader.Value);
1076 object parsedValue = null;
1078 parsedValue = dt.ParseValue (normalized, reader.NameTable, this.ParserContext.NamespaceManager);
1079 } catch (Exception ex) { // FIXME: (wishlist) It is bad manner ;-(
1080 HandleError ("Attribute value is invalid against its data type " + dt.TokenizedType, ex);
1082 if (attr.ValidatedFixedValue != null && attr.ValidatedFixedValue != normalized)
1083 HandleError ("The value of the attribute " + attr.QualifiedName + " does not match with its fixed value.");
1084 // FIXME: this is extraneous checks in 3.2.4 Attribute Locally Valid.
1086 AssessEachAttributeIdentityConstraint (dt, normalized, parsedValue);
1090 private void AssessEachAttributeIdentityConstraint (XmlSchemaDatatype dt,
1091 string normalized, object parsedValue)
1093 // Get normalized value and (if required) parsedValue if missing.
1094 switch (dt.TokenizedType) {
1095 case XmlTokenizedType.IDREFS:
1096 if (normalized == null)
1097 normalized = dt.Normalize (reader.Value);
1098 if (parsedValue == null)
1099 parsedValue = dt.ParseValue (normalized, reader.NameTable, ParserContext.NamespaceManager);
1101 case XmlTokenizedType.ID:
1102 case XmlTokenizedType.IDREF:
1103 if (normalized == null)
1104 normalized = dt.Normalize (reader.Value);
1108 // Validate identity constraints.
1109 switch (dt.TokenizedType) {
1110 case XmlTokenizedType.ID:
1111 if (thisElementId != null)
1112 HandleError ("ID type attribute was already assigned in the containing element.");
1113 thisElementId = normalized;
1114 if (idList.Contains (normalized))
1115 HandleError ("Duplicate ID value was found.");
1117 idList.Add (normalized, normalized);
1119 case XmlTokenizedType.IDREF:
1120 if (missingIDReferences.Contains (normalized))
1121 missingIDReferences.Remove (normalized);
1123 missingIDReferences.Add (normalized);
1125 case XmlTokenizedType.IDREFS:
1126 foreach (string id in (string []) parsedValue) {
1127 if (missingIDReferences.Contains (id))
1128 missingIDReferences.Remove (id);
1130 missingIDReferences.Add (id);
1137 private void AssessAttributeLocallyValidUse (XmlSchemaAttribute attr)
1139 // TODO: value constraint check
1140 // This is extra check than spec 3.5.4
1141 if (attr.ValidatedUse == XmlSchemaUse.Prohibited)
1142 HandleError ("Attribute " + attr.QualifiedName + " is prohibited in this context.");
1145 private void AssessEndElementSchemaValidity ()
1147 if (childParticleState == null)
1148 childParticleState = context.ParticleState;
1149 ValidateEndElementParticle (); // validate against childrens' state.
1151 context.Load (reader.Depth);
1153 // 3.3.4 Assess ElementLocallyValidElement 5: value constraints.
1154 // 3.3.4 Assess ElementLocallyValidType 3.1.3. = StringValid(3.14.4)
1155 // => ValidateEndCharacters().
1157 // Reset Identity constraints.
1158 for (int i = 0; i < keyTables.Count; i++) {
1159 XsdKeyTable keyTable = this.keyTables [i] as XsdKeyTable;
1160 if (keyTable.StartDepth == reader.Depth) {
1161 EndIdentityValidation (keyTable);
1163 for (int k = 0; k < keyTable.Entries.Count; k++) {
1164 XsdKeyEntry entry = keyTable.Entries [k] as XsdKeyEntry;
1165 // Remove finished (maybe key not found) entries.
1166 if (entry.StartDepth == reader.Depth) {
1168 keyTable.FinishedEntries.Add (entry);
1169 else if (entry.KeySequence.SourceSchemaIdentity is XmlSchemaKey)
1170 HandleError ("Key sequence is missing.");
1171 keyTable.Entries.RemoveAt (k);
1174 // Pop validated key depth to find two or more fields.
1176 foreach (XsdKeyEntryField kf in entry.KeyFields) {
1177 if (!kf.FieldFound && kf.FieldFoundDepth == reader.Depth) {
1178 kf.FieldFoundDepth = 0;
1179 kf.FieldFoundPath = null;
1186 for (int i = 0; i < keyTables.Count; i++) {
1187 XsdKeyTable keyseq = this.keyTables [i] as XsdKeyTable;
1188 if (keyseq.StartDepth == reader.Depth) {
1189 //Console.WriteLine ("Finishing table.");
1190 keyTables.RemoveAt (i);
1195 // Reset xsi:nil, if required.
1196 if (xsiNilDepth == reader.Depth)
1200 // 3.11.4 Identity Constraint Satisfied
1202 private void AssessStartIdentityConstraints ()
1204 tmpKeyrefPool.Clear ();
1205 if (context.Element != null && context.Element.Constraints.Count > 0) {
1206 // (a) Create new key sequences, if required.
1207 foreach (XmlSchemaIdentityConstraint ident in context.Element.Constraints) {
1208 XsdKeyTable seq = CreateNewKeyTable (ident);
1209 if (ident is XmlSchemaKeyref)
1210 tmpKeyrefPool.Add (seq);
1214 // (b) Evaluate current key sequences.
1215 foreach (XsdKeyTable seq in this.keyTables) {
1216 if (seq.SelectorMatches (this.elementQNameStack, reader) != null) {
1217 // creates and registers new entry.
1218 XsdKeyEntry entry = new XsdKeyEntry (seq, reader);
1219 seq.Entries.Add (entry);
1223 // (c) Evaluate field paths.
1224 foreach (XsdKeyTable seq in this.keyTables) {
1225 // If possible, create new field entry candidates.
1226 for (int i = 0; i < seq.Entries.Count; i++) {
1227 XsdKeyEntry entry = seq.Entries [i] as XsdKeyEntry;
1228 // if (entry.KeyFound)
1229 // FIXME: it should not be skipped for multiple key check!!
1232 entry.FieldMatches (this.elementQNameStack, this);
1233 } catch (Exception ex) { // FIXME: (wishlist) It is bad manner ;-(
1234 HandleError ("Identity field value is invalid against its data type.", ex);
1240 private XsdKeyTable CreateNewKeyTable (XmlSchemaIdentityConstraint ident)
1242 XsdKeyTable seq = new XsdKeyTable (ident, this);
1243 seq.StartDepth = reader.Depth;
1244 XmlSchemaKeyref keyref = ident as XmlSchemaKeyref;
1245 this.keyTables.Add (seq);
1249 private void EndIdentityValidation (XsdKeyTable seq)
1251 ArrayList errors = new ArrayList ();
1252 foreach (XsdKeyEntry entry in seq./*NotFound*/Entries) {
1255 if (seq.SourceSchemaIdentity is XmlSchemaKey)
1256 errors.Add ("line " + entry.SelectorLineNumber + "position " + entry.SelectorLinePosition);
1258 if (errors.Count > 0)
1259 HandleError ("Invalid identity constraints were found. Key was not found. "
1260 + String.Join (", ", errors.ToArray (typeof (string)) as string []));
1263 // Find reference target
1264 XmlSchemaKeyref xsdKeyref = seq.SourceSchemaIdentity as XmlSchemaKeyref;
1265 if (xsdKeyref != null) {
1266 for (int i = this.keyTables.Count - 1; i >= 0; i--) {
1267 XsdKeyTable target = this.keyTables [i] as XsdKeyTable;
1268 if (target.SourceSchemaIdentity == xsdKeyref.Target) {
1269 seq.ReferencedKey = target;
1270 foreach (XsdKeyEntry entry in seq.FinishedEntries) {
1271 foreach (XsdKeyEntry targetEntry in target.FinishedEntries) {
1272 if (entry.CompareIdentity (targetEntry)) {
1273 entry.KeyRefFound = true;
1280 if (seq.ReferencedKey == null)
1281 HandleError ("Target key was not found.");
1282 foreach (XsdKeyEntry entry in seq.FinishedEntries) {
1283 if (!entry.KeyRefFound)
1284 errors.Add (" line " + entry.SelectorLineNumber + ", position " + entry.SelectorLinePosition);
1286 if (errors.Count > 0)
1287 HandleError ("Invalid identity constraints were found. Referenced key was not found: "
1288 + String.Join (" / ", errors.ToArray (typeof (string)) as string []));
1292 // Overrided Methods
1294 public override void Close ()
1299 public override string GetAttribute (int i)
1301 switch (reader.NodeType) {
1302 case XmlNodeType.XmlDeclaration:
1303 case XmlNodeType.DocumentType:
1304 return reader.GetAttribute (i);
1307 if (reader.AttributeCount > i)
1308 reader.GetAttribute (i);
1309 int defIdx = i - nonDefaultAttributeCount;
1310 if (i < AttributeCount)
1311 return defaultAttributes [defIdx].DefaultValue;
1313 throw new ArgumentOutOfRangeException ("i", i, "Specified attribute index is out of range.");
1316 public override string GetAttribute (string name)
1318 switch (reader.NodeType) {
1319 case XmlNodeType.XmlDeclaration:
1320 case XmlNodeType.DocumentType:
1321 return reader.GetAttribute (name);
1324 string value = reader.GetAttribute (name);
1328 XmlQualifiedName qname = SplitQName (name);
1329 return GetDefaultAttribute (qname.Name, qname.Namespace);
1332 private XmlQualifiedName SplitQName (string name)
1334 if (!XmlChar.IsName (name))
1335 throw new ArgumentException ("Invalid name was specified.", "name");
1337 Exception ex = null;
1338 XmlQualifiedName qname = XmlSchemaUtil.ToQName (reader, name, out ex);
1340 return XmlQualifiedName.Empty;
1345 public override string GetAttribute (string localName, string ns)
1347 switch (reader.NodeType) {
1348 case XmlNodeType.XmlDeclaration:
1349 case XmlNodeType.DocumentType:
1350 return reader.GetAttribute (localName, ns);
1353 string value = reader.GetAttribute (localName, ns);
1357 return GetDefaultAttribute (localName, ns);
1360 private string GetDefaultAttribute (string localName, string ns)
1362 int idx = this.FindDefaultAttribute (localName, ns);
1365 string value = defaultAttributes [idx].ValidatedDefaultValue;
1367 value = defaultAttributes [idx].ValidatedFixedValue;
1371 private int FindDefaultAttribute (string localName, string ns)
1373 for (int i = 0; i < this.defaultAttributes.Length; i++) {
1374 XmlSchemaAttribute attr = defaultAttributes [i];
1375 if (attr.QualifiedName.Name == localName &&
1376 (ns == null || attr.QualifiedName.Namespace == ns))
1382 bool IXmlLineInfo.HasLineInfo ()
1384 return readerLineInfo != null && readerLineInfo.HasLineInfo ();
1387 public override string LookupNamespace (string prefix)
1389 return reader.LookupNamespace (prefix);
1392 public override void MoveToAttribute (int i)
1394 switch (reader.NodeType) {
1395 case XmlNodeType.XmlDeclaration:
1396 case XmlNodeType.DocumentType:
1397 reader.MoveToAttribute (i);
1401 currentQName = null;
1402 if (i < this.nonDefaultAttributeCount) {
1403 reader.MoveToAttribute (i);
1404 this.currentDefaultAttribute = -1;
1405 this.defaultAttributeConsumed = false;
1408 if (i < AttributeCount) {
1409 this.currentDefaultAttribute = i - nonDefaultAttributeCount;
1410 this.defaultAttributeConsumed = false;
1413 throw new ArgumentOutOfRangeException ("i", i, "Attribute index is out of range.");
1416 public override bool MoveToAttribute (string name)
1418 switch (reader.NodeType) {
1419 case XmlNodeType.XmlDeclaration:
1420 case XmlNodeType.DocumentType:
1421 return reader.MoveToAttribute (name);
1424 currentQName = null;
1425 bool b = reader.MoveToAttribute (name);
1427 this.currentDefaultAttribute = -1;
1428 this.defaultAttributeConsumed = false;
1432 return MoveToDefaultAttribute (name, null);
1435 public override bool MoveToAttribute (string localName, string ns)
1437 switch (reader.NodeType) {
1438 case XmlNodeType.XmlDeclaration:
1439 case XmlNodeType.DocumentType:
1440 return reader.MoveToAttribute (localName, ns);
1443 currentQName = null;
1444 bool b = reader.MoveToAttribute (localName, ns);
1446 this.currentDefaultAttribute = -1;
1447 this.defaultAttributeConsumed = false;
1451 return MoveToDefaultAttribute (localName, ns);
1454 private bool MoveToDefaultAttribute (string localName, string ns)
1456 int idx = this.FindDefaultAttribute (localName, ns);
1459 currentDefaultAttribute = idx;
1460 defaultAttributeConsumed = false;
1464 public override bool MoveToElement ()
1466 currentDefaultAttribute = -1;
1467 defaultAttributeConsumed = false;
1468 currentQName = null;
1469 return reader.MoveToElement ();
1472 public override bool MoveToFirstAttribute ()
1474 switch (reader.NodeType) {
1475 case XmlNodeType.XmlDeclaration:
1476 case XmlNodeType.DocumentType:
1477 return reader.MoveToFirstAttribute ();
1480 currentQName = null;
1481 if (this.nonDefaultAttributeCount > 0) {
1482 bool b = reader.MoveToFirstAttribute ();
1484 currentDefaultAttribute = -1;
1485 defaultAttributeConsumed = false;
1490 if (this.defaultAttributes.Length > 0) {
1491 currentDefaultAttribute = 0;
1492 defaultAttributeConsumed = false;
1499 public override bool MoveToNextAttribute ()
1501 switch (reader.NodeType) {
1502 case XmlNodeType.XmlDeclaration:
1503 case XmlNodeType.DocumentType:
1504 return reader.MoveToNextAttribute ();
1507 currentQName = null;
1508 if (currentDefaultAttribute >= 0) {
1509 if (defaultAttributes.Length == currentDefaultAttribute + 1)
1511 currentDefaultAttribute++;
1512 defaultAttributeConsumed = false;
1516 bool b = reader.MoveToNextAttribute ();
1518 currentDefaultAttribute = -1;
1519 defaultAttributeConsumed = false;
1523 if (defaultAttributes.Length > 0) {
1524 currentDefaultAttribute = 0;
1525 defaultAttributeConsumed = false;
1532 private void ExamineAdditionalSchema ()
1534 XmlSchema schema = null;
1535 string schemaLocation = reader.GetAttribute ("schemaLocation", XmlSchema.InstanceNamespace);
1536 if (schemaLocation != null) {
1537 string [] tmp = XmlSchemaDatatype.FromName ("NMTOKENS").ParseValue (schemaLocation, NameTable, null) as string [];
1538 if (tmp.Length % 2 != 0)
1539 HandleError ("Invalid schemaLocation attribute format.");
1540 for (int i = 0; i < tmp.Length; i += 2) {
1542 Uri absUri = new Uri ((this.BaseURI != "" ? new Uri (BaseURI) : null), tmp [i + 1]);
1543 XmlTextReader xtr = new XmlTextReader (absUri.ToString ());
1544 schema = XmlSchema.Read (xtr, null);
1545 } catch (Exception) { // FIXME: (wishlist) It is bad manner ;-(
1548 if (schema.TargetNamespace == null)
1549 schema.TargetNamespace = tmp [i];
1550 else if (schema.TargetNamespace != tmp [i])
1551 HandleError ("Specified schema has different target namespace.");
1554 if (schema != null) {
1556 schemas.Add (schema);
1557 } catch (XmlSchemaException ex) {
1562 string noNsSchemaLocation = reader.GetAttribute ("noNamespaceSchemaLocation", XmlSchema.InstanceNamespace);
1563 if (noNsSchemaLocation != null) {
1565 Uri absUri = new Uri ((this.BaseURI != "" ? new Uri (BaseURI) : null), noNsSchemaLocation);
1566 XmlTextReader xtr = new XmlTextReader (absUri.ToString ());
1567 schema = XmlSchema.Read (xtr, null);
1568 } catch (Exception) { // FIXME: (wishlist) It is bad manner ;-(
1570 if (schema != null && schema.TargetNamespace != null)
1571 HandleError ("Specified schema has different target namespace.");
1573 if (schema != null) {
1575 schemas.Add (schema);
1576 } catch (XmlSchemaException ex) {
1582 public override bool Read ()
1584 nonDefaultAttributeCount = 0;
1585 currentDefaultAttribute = -1;
1586 defaultAttributeConsumed = false;
1587 currentQName = null;
1588 thisElementId = null;
1589 defaultAttributes = new XmlSchemaAttribute [0];
1591 elementQNameStack.RemoveAt (elementQNameStack.Count - 1);
1595 bool result = reader.Read ();
1596 // 3.3.4 ElementLocallyValidElement 7 = Root Valid.
1597 if (!result && missingIDReferences.Count > 0)
1598 HandleError ("There are missing ID references: " +
1600 this.missingIDReferences.ToArray (typeof (string)) as string []));
1602 switch (reader.NodeType) {
1603 case XmlNodeType.Element:
1604 nonDefaultAttributeCount = reader.AttributeCount;
1606 if (reader.Depth == 0)
1607 ExamineAdditionalSchema ();
1609 this.elementQNameStack.Add (new XmlQualifiedName (reader.LocalName, reader.NamespaceURI));
1611 // If there is no schema information, then no validation is performed.
1612 if (schemas.Count == 0)
1615 // context.Load (reader.Depth);
1616 if (skipValidationDepth < 0 || reader.Depth <= skipValidationDepth) {
1617 if (shouldValidateCharacters) {
1618 ValidateEndCharacters ();
1619 shouldValidateCharacters = false;
1621 AssessStartElementSchemaValidity ();
1622 storedCharacters.Length = 0;
1627 if (reader.IsEmptyElement)
1628 goto case XmlNodeType.EndElement;
1630 shouldValidateCharacters = true;
1632 case XmlNodeType.EndElement:
1633 if (reader.Depth == skipValidationDepth) {
1634 skipValidationDepth = -1;
1637 // context.Load (reader.Depth);
1638 if (shouldValidateCharacters) {
1639 ValidateEndCharacters ();
1640 shouldValidateCharacters = false;
1642 AssessEndElementSchemaValidity ();
1644 storedCharacters.Length = 0;
1645 childParticleState = null;
1649 case XmlNodeType.CDATA:
1650 case XmlNodeType.SignificantWhitespace:
1651 case XmlNodeType.Text:
1652 XmlSchemaComplexType ct = context.ActualType as XmlSchemaComplexType;
1653 if (ct != null && storedCharacters.Length > 0) {
1654 switch (ct.ContentType) {
1655 case XmlSchemaContentType.ElementOnly:
1656 case XmlSchemaContentType.Empty:
1657 HandleError ("Not allowed character content was found.");
1662 ValidateCharacters ();
1669 public override bool ReadAttributeValue ()
1671 if (currentDefaultAttribute < 0)
1672 return reader.ReadAttributeValue ();
1674 if (this.defaultAttributeConsumed)
1677 defaultAttributeConsumed = true;
1682 public override string ReadInnerXml ()
1684 // MS.NET 1.0 has a serious bug here. It skips validation.
1685 return reader.ReadInnerXml ();
1688 public override string ReadOuterXml ()
1690 // MS.NET 1.0 has a serious bug here. It skips validation.
1691 return reader.ReadOuterXml ();
1695 // XmlReader.ReadString() should call derived this.Read().
1696 public override string ReadString ()
1699 return reader.ReadString ();
1701 return base.ReadString ();
1705 // This class itself does not have this feature.
1706 public override void ResolveEntity ()
1708 reader.ResolveEntity ();
1711 internal class XsdValidationContext
1713 Hashtable contextStack;
1715 public XsdValidationContext ()
1717 contextStack = new Hashtable ();
1720 // Some of them might be missing (See the spec section 5.3, and also 3.3.4).
1721 public XmlSchemaElement Element;
1722 public XsdValidationState ParticleState;
1723 public XmlSchemaAttribute [] DefaultAttributes;
1725 // Some of them might be missing (See the spec section 5.3).
1726 public object SchemaType;
1728 public object LocalTypeDefinition;
1730 public object ActualType {
1732 if (LocalTypeDefinition != null)
1733 return LocalTypeDefinition;
1739 public void Clear ()
1743 ParticleState = null;
1744 LocalTypeDefinition = null;
1747 public void PushScope (int depth)
1749 contextStack [depth] = this.MemberwiseClone ();
1752 public void PopScope (int depth)
1755 contextStack.Remove (depth + 1);
1758 public void Load (int depth)
1761 XsdValidationContext restored = (XsdValidationContext) contextStack [depth];
1762 if (restored != null) {
1763 this.Element = restored.Element;
1764 this.ParticleState = restored.ParticleState;
1765 this.SchemaType = restored.SchemaType;
1766 this.LocalTypeDefinition = restored.LocalTypeDefinition;
1772 internal class XsdValidityState
1774 ArrayList currentParticles = new ArrayList ();
1775 ArrayList occured = new ArrayList ();
1776 Hashtable xsAllConsumed = new Hashtable ();
1777 XmlSchemaParticle parciele;
1780 public XsdValidityState (XmlSchemaParticle particle)
1782 this.parciele = particle;
1783 currentParticles.Add (particle);