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 char [] wsChars = new char [] {' ', '\t', '\n', '\r'};
29 XmlValidatingReader xvReader;
30 IXmlLineInfo readerLineInfo;
31 bool laxElementValidation = true;
32 bool reportNoValidationError;
33 XmlSchemaCollection schemas = new XmlSchemaCollection ();
34 bool namespaces = true;
36 ArrayList idList = new ArrayList ();
37 ArrayList missingIDReferences = new ArrayList ();
40 ArrayList keyTables = new ArrayList ();
41 ArrayList currentKeyFieldConsumers = new ArrayList ();
43 XsdValidationStateManager stateManager = new XsdValidationStateManager ();
44 XsdValidationContext context = new XsdValidationContext ();
45 XsdValidationState childParticleState;
48 StringBuilder storedCharacters = new StringBuilder ();
49 bool shouldValidateCharacters;
50 int skipValidationDepth = -1;
52 XmlSchemaAttribute [] defaultAttributes = new XmlSchemaAttribute [0];
53 int currentDefaultAttribute = -1;
54 XmlQualifiedName currentQName;
56 ArrayList elementQNameStack = new ArrayList ();
60 int nonDefaultAttributeCount;
61 bool defaultAttributeConsumed;
63 // Validation engine cached object
64 ArrayList defaultAttributesCache = new ArrayList ();
65 ArrayList tmpKeyrefPool = new ArrayList ();
68 public XsdValidatingReader (XmlReader reader)
73 public XsdValidatingReader (XmlReader reader, XmlReader validatingReader)
76 xvReader = validatingReader as XmlValidatingReader;
77 if (xvReader != null) {
78 if (xvReader.ValidationType == ValidationType.None)
79 reportNoValidationError = true;
81 readerLineInfo = reader as IXmlLineInfo;
85 private XmlQualifiedName CurrentQName {
87 if (currentQName == null)
88 currentQName = new XmlQualifiedName (LocalName, NamespaceURI);
93 internal ArrayList CurrentKeyFieldConsumers {
94 get { return currentKeyFieldConsumers; }
97 // Public Non-overrides
99 public bool Namespaces {
100 get { return namespaces; }
101 set { namespaces = value; }
104 public XmlReader Reader {
105 get { return reader; }
108 // This should be changed before the first Read() call.
109 public XmlSchemaCollection Schemas {
110 get { return schemas; }
113 public object SchemaType {
115 if (ReadState != ReadState.Interactive)
119 case XmlNodeType.Element:
120 if (context.ActualType != null)
121 return context.ActualType;
122 else if (context.Element != null)
123 return context.Element.ElementType;
126 case XmlNodeType.Attribute:
127 // TODO: Default attribute support
128 XmlSchemaComplexType ct = context.ActualType as XmlSchemaComplexType;
130 XmlSchemaAttribute attdef = ct.AttributeUses [CurrentQName] as XmlSchemaAttribute;
132 return attdef.AttributeType;
141 // This property is never used in Mono.
142 public ValidationType ValidationType {
144 if (reportNoValidationError)
145 return ValidationType.None;
147 return ValidationType.Schema;
151 // It is used only for independent XmlReader use, not for XmlValidatingReader.
152 public object ReadTypedValue ()
154 XmlSchemaDatatype dt = SchemaType as XmlSchemaDatatype;
155 XmlSchemaSimpleType st = SchemaType as XmlSchemaSimpleType;
162 case XmlNodeType.Element:
166 storedCharacters.Length = 0;
171 case XmlNodeType.SignificantWhitespace:
172 case XmlNodeType.Text:
173 case XmlNodeType.CDATA:
174 storedCharacters.Append (Value);
176 case XmlNodeType.Comment:
182 } while (loop && !EOF);
183 return dt.ParseValue (storedCharacters.ToString (), NameTable, ParserContext.NamespaceManager);
184 case XmlNodeType.Attribute:
185 return dt.ParseValue (Value, NameTable, ParserContext.NamespaceManager);
190 public ValidationEventHandler ValidationEventHandler;
192 // Public Overrided Properties
194 public override int AttributeCount {
197 if (NodeType == XmlNodeType.Element)
198 return attributeCount;
202 return reader.AttributeCount;
204 return nonDefaultAttributeCount + defaultAttributes.Length;
208 public override string BaseURI {
209 get { return reader.BaseURI; }
212 // If this class is used to implement XmlValidatingReader,
213 // it should be left to DTDValidatingReader. In other cases,
214 // it depends on the reader's ability.
215 public override bool CanResolveEntity {
216 get { return reader.CanResolveEntity; }
219 public override int Depth {
221 if (currentDefaultAttribute < 0)
223 if (this.defaultAttributeConsumed)
224 return reader.Depth + 2;
225 return reader.Depth + 1;
229 public override bool EOF {
230 get { return reader.EOF; }
233 public override bool HasValue {
235 if (currentDefaultAttribute < 0)
236 return reader.HasValue;
241 public override bool IsDefault {
243 if (currentDefaultAttribute < 0)
244 return reader.IsDefault;
249 public override bool IsEmptyElement {
251 if (currentDefaultAttribute < 0)
252 return reader.IsEmptyElement;
257 public override string this [int i] {
258 get { return GetAttribute (i); }
261 public override string this [string name] {
262 get { return GetAttribute (name); }
265 public override string this [string localName, string ns] {
266 get { return GetAttribute (localName, ns); }
269 int IXmlLineInfo.LineNumber {
270 get { return readerLineInfo != null ? readerLineInfo.LineNumber : 0; }
273 int IXmlLineInfo.LinePosition {
274 get { return readerLineInfo != null ? readerLineInfo.LinePosition : 0; }
277 public override string LocalName {
279 if (currentDefaultAttribute < 0)
280 return reader.LocalName;
281 if (defaultAttributeConsumed)
283 return defaultAttributes [currentDefaultAttribute].QualifiedName.Name;
287 public override string Name {
289 if (currentDefaultAttribute < 0)
291 if (defaultAttributeConsumed)
294 XmlQualifiedName qname = defaultAttributes [currentDefaultAttribute].QualifiedName;
295 string prefix = Prefix;
296 if (prefix == String.Empty)
299 return String.Concat (prefix, ":", qname.Name);
303 public override string NamespaceURI {
305 if (currentDefaultAttribute < 0)
306 return reader.NamespaceURI;
307 if (defaultAttributeConsumed)
309 return defaultAttributes [currentDefaultAttribute].QualifiedName.Namespace;
313 public override XmlNameTable NameTable {
314 get { return reader.NameTable; }
317 public override XmlNodeType NodeType {
319 if (currentDefaultAttribute < 0)
320 return reader.NodeType;
321 if (defaultAttributeConsumed)
322 return XmlNodeType.Text;
323 return XmlNodeType.Attribute;
327 public XmlParserContext ParserContext {
328 get { return XmlSchemaUtil.GetParserContext (reader); }
331 public override string Prefix {
333 if (currentDefaultAttribute < 0)
334 return reader.Prefix;
335 if (defaultAttributeConsumed)
337 XmlQualifiedName qname = defaultAttributes [currentDefaultAttribute].QualifiedName;
338 string prefix = this.ParserContext.NamespaceManager.LookupPrefix (qname.Namespace);
346 public override char QuoteChar {
347 get { return reader.QuoteChar; }
350 public override ReadState ReadState {
351 get { return reader.ReadState; }
354 public override string Value {
356 if (currentDefaultAttribute < 0)
358 return defaultAttributes [currentDefaultAttribute].ValidatedDefaultValue;
362 XmlQualifiedName qnameXmlLang = new XmlQualifiedName ("lang", XmlNamespaceManager.XmlnsXml);
364 public override string XmlLang {
366 string xmlLang = reader.XmlLang;
369 int idx = this.FindDefaultAttribute ("lang", XmlNamespaceManager.XmlnsXml);
372 return defaultAttributes [idx].ValidatedDefaultValue;
376 public override XmlSpace XmlSpace {
378 XmlSpace space = reader.XmlSpace;
379 if (space != XmlSpace.None)
381 int idx = this.FindDefaultAttribute ("space", XmlNamespaceManager.XmlnsXml);
383 return XmlSpace.None;
384 return (XmlSpace) Enum.Parse (typeof (XmlSpace), defaultAttributes [idx].ValidatedDefaultValue, false);
390 private XmlQualifiedName QualifyName (string name)
392 int colonAt = name.IndexOf (':');
394 return new XmlQualifiedName (name, null);
396 return new XmlQualifiedName (name.Substring (colonAt + 1),
397 LookupNamespace (name.Substring (0, colonAt)));
400 private void HandleError (string error)
402 HandleError (error, null);
405 private void HandleError (string error, Exception innerException)
407 if (reportNoValidationError) // extra quick check
410 XmlSchemaException schemaException = new XmlSchemaException (error,
411 this, this.BaseURI, null, innerException);
412 HandleError (schemaException);
415 private void HandleError (XmlSchemaException schemaException)
417 if (reportNoValidationError)
420 ValidationEventArgs e = new ValidationEventArgs (schemaException,
421 schemaException.Message, XmlSeverityType.Error);
423 if (this.ValidationEventHandler != null)
424 this.ValidationEventHandler (this, e);
425 else if (xvReader != null)
426 xvReader.OnValidationEvent (this, e);
429 this.xvReader.OnValidationEvent (this, e);
435 private XmlSchemaElement FindElement (string name, string ns)
437 foreach (XmlSchema target in schemas) {
438 XmlSchema matches = target.Schemas [reader.NamespaceURI];
439 if (matches != null) {
440 XmlSchemaElement result = target.Elements [new XmlQualifiedName (reader.LocalName, reader.NamespaceURI)] as XmlSchemaElement;
448 private XmlSchemaType FindType (XmlQualifiedName qname)
450 foreach (XmlSchema target in schemas) {
451 XmlSchemaType type = target.SchemaTypes [qname] as XmlSchemaType;
458 private void ValidateStartElementParticle ()
460 stateManager.CurrentElement = null;
461 context.ParticleState = context.ParticleState.EvaluateStartElement (reader.LocalName, reader.NamespaceURI);
462 if (context.ParticleState == XsdValidationState.Invalid)
463 HandleError ("Invalid start element: " + reader.NamespaceURI + ":" + reader.LocalName);
465 context.Element = stateManager.CurrentElement;
466 if (context.Element != null)
467 context.SchemaType = context.Element.ElementType;
470 private void ValidateEndElementParticle ()
472 if (childParticleState != null) {
473 if (!childParticleState.EvaluateEndElement ()) {
474 HandleError ("Invalid end element: " + reader.Name);
477 context.PopScope (reader.Depth);
480 // Utility for missing validation completion related to child items.
481 private void ValidateCharacters ()
483 // TODO: value context validation here.
484 if (xsiNilDepth >= 0 && xsiNilDepth < reader.Depth)
485 HandleError ("Element item appeared, while current element context is nil.");
487 storedCharacters.Append (reader.Value);
490 // Utility for missing validation completion related to child items.
491 private void ValidateEndCharacters ()
493 if (context.ActualType == null)
496 string value = storedCharacters.ToString ();
498 if (storedCharacters.Length == 0) {
499 // 3.3.4 Element Locally Valid (Element) 5.1.2
500 // TODO: check entire DefaultValid (3.3.6)
501 if (context.Element != null && context.Element.ValidatedDefaultValue != null)
502 value = context.Element.ValidatedDefaultValue;
505 XmlSchemaDatatype dt = context.ActualType as XmlSchemaDatatype;
506 XmlSchemaSimpleType st = context.ActualType as XmlSchemaSimpleType;
509 // if (st.Variety == XmlSchemaDerivationMethod.Restriction)
512 XmlSchemaComplexType ct = context.ActualType as XmlSchemaComplexType;
514 switch (ct.ContentType) {
515 case XmlSchemaContentType.ElementOnly:
516 case XmlSchemaContentType.Empty:
517 if (storedCharacters.Length > 0)
518 HandleError ("Character content not allowed.");
524 // 3.3.4 Element Locally Valid (Element) :: 5.2.2.2. Fixed value constraints
525 if (context.Element != null && context.Element.ValidatedFixedValue != null)
526 if (value != context.Element.ValidatedFixedValue)
527 HandleError ("Fixed value constraint was not satisfied.");
528 AssessStringValid (st, dt, value);
531 // Identity field value
532 while (this.currentKeyFieldConsumers.Count > 0) {
533 XsdKeyEntryField field = this.currentKeyFieldConsumers [0] as XsdKeyEntryField;
534 if (field.Identity != null)
535 HandleError ("Two or more identical field was found. Former value is '" + field.Identity + "' .");
536 object identity = null;
539 identity = dt.ParseValue (value, NameTable, ParserContext.NamespaceManager);
540 } catch (Exception ex) { // FIXME: This is bad manner ;-(
541 // FIXME: Such exception handling is not a good idea.
542 HandleError ("Identity value is invalid against its data type " + dt.TokenizedType, ex);
545 if (identity == null)
548 if (!field.SetIdentityField (identity, dt as XsdAnySimpleType, this))
549 HandleError ("Two or more identical key value was found: '" + value + "' .");
550 this.currentKeyFieldConsumers.RemoveAt (0);
553 shouldValidateCharacters = false;
556 // 3.14.4 String Valid
557 private void AssessStringValid (XmlSchemaSimpleType st,
558 XmlSchemaDatatype dt, string value)
560 XmlSchemaDatatype validatedDatatype = dt;
562 string normalized = validatedDatatype.Normalize (value);
564 XmlSchemaDatatype itemDatatype;
565 XmlSchemaSimpleType itemSimpleType;
566 switch (st.DerivedBy) {
567 case XmlSchemaDerivationMethod.List:
568 XmlSchemaSimpleTypeList listContent = st.Content as XmlSchemaSimpleTypeList;
569 values = normalized.Split (wsChars);
570 itemDatatype = listContent.ValidatedListItemType as XmlSchemaDatatype;
571 itemSimpleType = listContent.ValidatedListItemType as XmlSchemaSimpleType;
572 foreach (string each in values) {
573 if (each == String.Empty)
575 // validate against ValidatedItemType
576 if (itemDatatype != null) {
578 itemDatatype.ParseValue (each, NameTable, ParserContext.NamespaceManager);
579 } catch (Exception ex) { // FIXME: better exception handling ;-(
580 HandleError ("List type value contains one or more invalid values.", ex);
585 AssessStringValid (itemSimpleType, itemSimpleType.Datatype, each);
588 case XmlSchemaDerivationMethod.Union:
589 XmlSchemaSimpleTypeUnion union = st.Content as XmlSchemaSimpleTypeUnion;
590 // values = normalized.Split (wsChars);
592 string each = normalized;
593 // foreach (string each in values) {
594 // if (each == String.Empty)
596 // validate against ValidatedItemType
598 foreach (object eachType in union.ValidatedTypes) {
599 itemDatatype = eachType as XmlSchemaDatatype;
600 itemSimpleType = eachType as XmlSchemaSimpleType;
601 if (itemDatatype != null) {
603 itemDatatype.ParseValue (each, NameTable, ParserContext.NamespaceManager);
604 } catch (Exception) { // FIXME: better exception handling ;-(
610 AssessStringValid (itemSimpleType, itemSimpleType.Datatype, each);
611 } catch (XmlSchemaException) {
619 HandleError ("Union type value contains one or more invalid values.");
625 case XmlSchemaDerivationMethod.Restriction:
626 XmlSchemaSimpleTypeRestriction str = st.Content as XmlSchemaSimpleTypeRestriction;
629 if (!str.ValidateValueWithFacets (normalized, NameTable)) {
630 HandleError ("Specified value was invalid against the facets.");
634 validatedDatatype = st.Datatype;
638 if (validatedDatatype != null) {
640 validatedDatatype.ParseValue (value, NameTable, ParserContext.NamespaceManager);
641 } catch (Exception ex) { // FIXME: It is really bad design ;-P
642 HandleError ("Invalidly typed data was specified.", ex);
647 private object GetLocalTypeDefinition (string name)
649 object xsiType = null;
650 XmlQualifiedName typeQName = QualifyName (name);
651 if (typeQName.Namespace == XmlSchema.Namespace) {
652 if (typeQName.Name == "anyType")
653 xsiType = XmlSchemaComplexType.AnyType;
655 xsiType = XmlSchemaDatatype.FromName (typeQName);
658 xsiType = FindType (typeQName);
662 // It is common to ElementLocallyValid::4 and SchemaValidityAssessment::1.2.1.2.4
663 private void AssessLocalTypeDerivationOK (object xsiType, object baseType, XmlSchemaDerivationMethod flag)
665 XmlSchemaType xsiSchemaType = xsiType as XmlSchemaType;
666 XmlSchemaComplexType baseComplexType = baseType as XmlSchemaComplexType;
667 XmlSchemaComplexType xsiComplexType = xsiSchemaType as XmlSchemaComplexType;
668 if (xsiType != baseType) {
669 // Extracted (not extraneous) check for 3.4.6 TypeDerivationOK.
670 if (baseComplexType != null)
671 flag |= baseComplexType.BlockResolved;
672 if (flag == XmlSchemaDerivationMethod.All) {
673 HandleError ("Prohibited element type substitution.");
675 } else if (xsiSchemaType != null && (flag & xsiSchemaType.DerivedBy) != 0) {
676 HandleError ("Prohibited element type substitution.");
681 if (xsiComplexType != null)
683 xsiComplexType.ValidateTypeDerivationOK (baseType, null, null);
684 } catch (XmlSchemaException ex) {
685 // HandleError ("Locally specified schema complex type derivation failed. " + ex.Message, ex);
689 XmlSchemaSimpleType xsiSimpleType = xsiType as XmlSchemaSimpleType;
690 if (xsiSimpleType != null) {
692 xsiSimpleType.ValidateTypeDerivationOK (baseType, null, null, true);
693 } catch (XmlSchemaException ex) {
694 // HandleError ("Locally specified schema simple type derivation failed. " + ex.Message, ex);
698 else if (xsiType is XmlSchemaDatatype) {
702 HandleError ("Primitive data type cannot be derived type using xsi:type specification.");
706 // Section 3.3.4 of the spec.
707 private void AssessStartElementSchemaValidity ()
709 // If the reader is inside xsi:nil (and failed on validation),
710 // then simply skip its content.
711 if (xsiNilDepth >= 0 && xsiNilDepth < reader.Depth)
712 HandleError ("Element item appeared, while current element context is nil.");
714 context.Load (reader.Depth);
715 if (childParticleState != null) {
716 context.ParticleState = childParticleState;
717 childParticleState = null;
720 // If validation state exists, then first assess particle validity.
721 if (context.ParticleState != null) {
722 ValidateStartElementParticle ();
725 string xsiNilValue = GetAttribute ("nil", XmlSchema.InstanceNamespace);
726 if (xsiNilValue != null)
727 xsiNilValue = xsiNilValue.Trim (XmlChar.WhitespaceChars);
728 bool isXsiNil = xsiNilValue == "true";
729 if (isXsiNil && this.xsiNilDepth < 0)
730 xsiNilDepth = reader.Depth;
732 // [Schema Validity Assessment (Element) 1.2]
733 // Evaluate "local type definition" from xsi:type.
734 // (See spec 3.3.4 Schema Validity Assessment (Element) 1.2.1.2.3.
735 // Note that Schema Validity Assessment(Element) 1.2 takes
736 // precedence than 1.1 of that.
738 // FIXME: xsi:type value should be normalized.
739 string xsiTypeName = reader.GetAttribute ("type", XmlSchema.InstanceNamespace);
740 if (xsiTypeName != null) {
741 object xsiType = GetLocalTypeDefinition (xsiTypeName);
743 HandleError ("The instance type was not found: " + xsiTypeName + " .");
745 XmlSchemaType xsiSchemaType = xsiType as XmlSchemaType;
746 if (xsiSchemaType != null && this.context.Element != null) {
747 XmlSchemaType elemBaseType = context.Element.ElementType as XmlSchemaType;
748 if (elemBaseType != null && (xsiSchemaType.DerivedBy & elemBaseType.FinalResolved) != 0)
749 HandleError ("The instance type is prohibited by the type of the context element.");
750 if (elemBaseType != xsiType && (xsiSchemaType.DerivedBy & this.context.Element.BlockResolved) != 0)
751 HandleError ("The instance type is prohibited by the context element.");
753 XmlSchemaComplexType xsiComplexType = xsiType as XmlSchemaComplexType;
754 if (xsiComplexType != null && xsiComplexType.IsAbstract)
755 HandleError ("The instance type is abstract: " + xsiTypeName + " .");
757 // If current schema type exists, then this xsi:type must be
758 // valid extension of that type. See 1.2.1.2.4.
759 if (context.Element != null) {
760 // FIXME: supply *correct* base type
761 AssessLocalTypeDerivationOK (xsiType, context.Element.ElementType, context.Element.BlockResolved);
763 AssessStartElementLocallyValidType (xsiType); // 1.2.2:
764 context.LocalTypeDefinition = xsiType;
769 // Create Validation Root, if not exist.
770 // [Schema Validity Assessment (Element) 1.1]
771 if (context.Element == null)
772 context.Element = FindElement (reader.LocalName, reader.NamespaceURI);
773 if (context.Element != null) {
774 if (xsiTypeName == null) {
775 context.SchemaType = context.Element.ElementType;
776 AssessElementLocallyValidElement (context.Element, xsiNilValue); // 1.1.2
780 switch (stateManager.ProcessContents) {
781 case XmlSchemaContentProcessing.Skip:
783 case XmlSchemaContentProcessing.Lax:
785 schema = schemas [reader.NamespaceURI];
786 if (schema != null && !schema.missedSubComponents)
787 HandleError ("Element declaration for " + reader.LocalName + " is missing.");
791 schema = schemas [reader.NamespaceURI];
792 if (xsiTypeName == null && (schema == null || !schema.missedSubComponents))
793 HandleError ("Element declaration for " + reader.LocalName + " is missing.");
798 if (stateManager.ProcessContents == XmlSchemaContentProcessing.Skip)
799 skipValidationDepth = reader.Depth;
801 // Finally, create child particle state.
802 XmlSchemaComplexType xsComplexType = SchemaType as XmlSchemaComplexType;
803 if (xsComplexType != null)
804 childParticleState = stateManager.Create (xsComplexType.ContentTypeParticle);
805 else if (stateManager.ProcessContents == XmlSchemaContentProcessing.Lax)
806 childParticleState = stateManager.Create (XmlSchemaAny.AnyTypeContent);
808 childParticleState = stateManager.Create (XmlSchemaParticle.Empty);
810 AssessStartIdentityConstraints ();
812 context.PushScope (reader.Depth);
815 // 3.3.4 Element Locally Valid (Element)
816 private void AssessElementLocallyValidElement (XmlSchemaElement element, string xsiNilValue)
818 XmlQualifiedName qname = new XmlQualifiedName (reader.LocalName, reader.NamespaceURI);
821 HandleError ("Element declaration is required for " + qname);
823 if (element.actualIsAbstract)
824 HandleError ("Abstract element declaration was specified for " + qname);
826 if (!element.actualIsNillable && xsiNilValue != null)
827 HandleError ("This element declaration is not nillable: " + qname);
829 // Note that 3.2.1 xsi:nil constraints are to be validated in
830 else if (xsiNilValue == "true") {
831 // AssessElementSchemaValidity() and ValidateCharacters()
833 if (element.ValidatedFixedValue != null)
834 HandleError ("Schema instance nil was specified, where the element declaration for " + qname + "has fixed value constraints.");
837 string xsiType = reader.GetAttribute ("type", XmlSchema.InstanceNamespace);
838 if (xsiType != null) {
839 context.LocalTypeDefinition = GetLocalTypeDefinition (xsiType);
840 AssessLocalTypeDerivationOK (context.LocalTypeDefinition, element.ElementType, element.BlockResolved);
843 // 5 Not all things cannot be assessed here.
844 // It is common to 5.1 and 5.2
845 if (element.ElementType != null)
846 AssessStartElementLocallyValidType (SchemaType);
848 // 6. should be out from here.
849 // See invokation of AssessStartIdentityConstraints().
851 // 7 is going to be validated in Read() (in case of xmlreader's EOF).
854 // 3.3.4 Element Locally Valid (Type)
855 private void AssessStartElementLocallyValidType (object schemaType)
857 if (schemaType == null) { // 1.
858 HandleError ("Schema type does not exist.");
861 XmlSchemaComplexType cType = schemaType as XmlSchemaComplexType;
862 XmlSchemaSimpleType sType = schemaType as XmlSchemaSimpleType;
865 while (reader.MoveToNextAttribute ()) {
866 if (reader.NamespaceURI == XmlNamespaceManager.XmlnsXmlns)
868 if (reader.NamespaceURI != XmlSchema.InstanceNamespace)
869 HandleError ("Current simple type cannot accept attributes other than schema instance namespace.");
870 switch (reader.LocalName) {
873 case "schemaLocation":
874 case "noNamespaceSchemaLocation":
877 HandleError ("Unknown schema instance namespace attribute: " + reader.LocalName);
881 reader.MoveToElement ();
882 // 3.1.2 and 3.1.3 cannot be assessed here.
883 } else if (cType != null) {
884 if (cType.IsAbstract) { // 2.
885 HandleError ("Target complex type is abstract.");
889 AssessElementLocallyValidComplexType (cType);
893 // 3.4.4 Element Locally Valid (Complex Type)
894 // TODO ("wild IDs constraints.")
895 private void AssessElementLocallyValidComplexType (XmlSchemaComplexType cType)
898 if (cType.IsAbstract)
899 HandleError ("Target complex type is abstract.");
901 // 2 (xsi:nil and content prohibition)
902 // See AssessStartElementSchemaValidity() and ValidateCharacters()
904 string elementNs = reader.NamespaceURI;
905 // 3. attribute uses and
907 while (reader.MoveToNextAttribute ()) {
908 if (reader.NamespaceURI == "http://www.w3.org/2000/xmlns/")
910 else if (reader.NamespaceURI == XmlSchema.InstanceNamespace)
912 XmlQualifiedName qname = new XmlQualifiedName (reader.LocalName, reader.NamespaceURI);
913 object attMatch = FindAttributeDeclaration (cType, qname, elementNs);
914 if (attMatch == null)
915 HandleError ("Attribute declaration was not found for " + qname);
917 XmlSchemaAttribute attdecl = attMatch as XmlSchemaAttribute;
918 if (attdecl == null) { // i.e. anyAttribute
919 XmlSchemaAnyAttribute anyAttrMatch = attMatch as XmlSchemaAnyAttribute;
921 AssessAttributeLocallyValidUse (attdecl);
922 AssessAttributeLocallyValid (attdecl, true);
926 reader.MoveToElement ();
928 // Collect default attributes.
930 // FIXME: FixedValue check maybe extraneous.
931 foreach (XmlSchemaAttribute attr in cType.AttributeUses) {
932 if (reader [attr.QualifiedName.Name, attr.QualifiedName.Namespace] == null) {
933 if (attr.ValidatedUse == XmlSchemaUse.Required &&
934 attr.ValidatedFixedValue == null)
935 HandleError ("Required attribute " + attr.QualifiedName + " was not found.");
936 else if (attr.ValidatedDefaultValue != null)
937 defaultAttributesCache.Add (attr);
940 defaultAttributes = (XmlSchemaAttribute [])
941 defaultAttributesCache.ToArray (typeof (XmlSchemaAttribute));
942 context.DefaultAttributes = defaultAttributes;
943 defaultAttributesCache.Clear ();
944 // 5. wild IDs was already checked above.
947 // Spec 3.10.4 Item Valid (Wildcard)
948 private bool AttributeWildcardItemValid (XmlSchemaAnyAttribute anyAttr, XmlQualifiedName qname)
950 if (anyAttr.HasValueAny)
952 if (anyAttr.HasValueOther && (anyAttr.TargetNamespace == "" || reader.NamespaceURI != anyAttr.TargetNamespace))
954 if (anyAttr.HasValueTargetNamespace && reader.NamespaceURI == anyAttr.TargetNamespace)
956 if (anyAttr.HasValueLocal && reader.NamespaceURI == "")
958 foreach (string ns in anyAttr.ResolvedNamespaces)
959 if (ns == reader.NamespaceURI)
964 private XmlSchemaObject FindAttributeDeclaration (XmlSchemaComplexType cType,
965 XmlQualifiedName qname, string elementNs)
967 XmlSchemaObject result = cType.AttributeUses [qname];
970 if (cType.AttributeWildcard == null)
973 if (!AttributeWildcardItemValid (cType.AttributeWildcard, qname))
976 if (cType.AttributeWildcard.ProcessContents == XmlSchemaContentProcessing.Skip)
977 return cType.AttributeWildcard;
978 foreach (XmlSchema schema in schemas) {
979 foreach (XmlSchemaAttribute attr in schema.Attributes)
980 if (attr.QualifiedName == qname)
983 if (cType.AttributeWildcard.ProcessContents == XmlSchemaContentProcessing.Lax)
984 return cType.AttributeWildcard;
989 // 3.2.4 Attribute Locally Valid and 3.4.4 - 5.wildIDs
991 private void AssessAttributeLocallyValid (XmlSchemaAttribute attr, bool checkWildIDs)
994 switch (reader.NamespaceURI) {
995 case XmlNamespaceManager.XmlnsXml:
996 case XmlNamespaceManager.XmlnsXmlns:
997 case XmlSchema.InstanceNamespace:
1001 if (attr.AttributeType == null)
1002 HandleError ("Attribute type is missing for " + attr.QualifiedName);
1003 XmlSchemaDatatype dt = attr.AttributeType as XmlSchemaDatatype;
1005 dt = ((XmlSchemaSimpleType) attr.AttributeType).Datatype;
1006 // It is a bit heavy process, so let's omit as long as possible ;-)
1007 if (dt != XmlSchemaSimpleType.AnySimpleType || attr.ValidatedFixedValue != null) {
1008 string normalized = dt.Normalize (reader.Value);
1009 object parsedValue = null;
1011 dt.ParseValue (normalized, reader.NameTable, this.ParserContext.NamespaceManager);
1012 } catch (Exception ex) {
1013 // FIXME: Such exception handling is not a good idea.
1014 HandleError ("Attribute value is invalid against its data type " + dt.TokenizedType, ex);
1016 if (attr.ValidatedFixedValue != null && attr.ValidatedFixedValue != normalized)
1017 HandleError ("The value of the attribute " + attr.QualifiedName + " does not match with its fixed value.");
1018 // FIXME: this is extraneous checks in 3.2.4 Attribute Locally Valid.
1020 AssessEachAttributeIdentityConstraint (dt, normalized, parsedValue);
1024 private void AssessEachAttributeIdentityConstraint (XmlSchemaDatatype dt,
1025 string normalized, object parsedValue)
1027 // Get normalized value and (if required) parsedValue if missing.
1028 switch (dt.TokenizedType) {
1029 case XmlTokenizedType.IDREFS:
1030 if (normalized == null)
1031 normalized = dt.Normalize (reader.Value);
1032 if (parsedValue == null)
1033 parsedValue = dt.ParseValue (normalized, reader.NameTable, ParserContext.NamespaceManager);
1035 case XmlTokenizedType.ID:
1036 case XmlTokenizedType.IDREF:
1037 if (normalized == null)
1038 normalized = dt.Normalize (reader.Value);
1042 // Validate identity constraints.
1043 switch (dt.TokenizedType) {
1044 case XmlTokenizedType.ID:
1045 if (thisElementId != null)
1046 HandleError ("ID type attribute was already assigned in the containing element.");
1047 thisElementId = normalized;
1048 idList.Add (normalized);
1050 case XmlTokenizedType.IDREF:
1051 if (missingIDReferences.Contains (normalized))
1052 missingIDReferences.Remove (normalized);
1054 missingIDReferences.Add (normalized);
1056 case XmlTokenizedType.IDREFS:
1057 foreach (string id in (string []) parsedValue) {
1058 if (missingIDReferences.Contains (id))
1059 missingIDReferences.Remove (id);
1061 missingIDReferences.Add (id);
1068 private void AssessAttributeLocallyValidUse (XmlSchemaAttribute attr)
1070 // TODO: value constraint check
1071 // This is extra check than spec 3.5.4
1072 if (attr.ValidatedUse == XmlSchemaUse.Prohibited)
1073 HandleError ("Attribute " + attr.QualifiedName + " is prohibited in this context.");
1076 private void AssessEndElementSchemaValidity ()
1078 if (childParticleState == null)
1079 childParticleState = context.ParticleState;
1080 ValidateEndElementParticle (); // validate against childrens' state.
1082 context.Load (reader.Depth);
1084 // 3.3.4 Assess ElementLocallyValidElement 5: value constraints.
1085 // 3.3.4 Assess ElementLocallyValidType 3.1.3. = StringValid(3.14.4)
1086 // => ValidateEndCharacters().
1088 // Reset Identity constraints.
1089 for (int i = 0; i < keyTables.Count; i++) {
1090 XsdKeyTable keyTable = this.keyTables [i] as XsdKeyTable;
1091 if (keyTable.StartDepth == reader.Depth) {
1092 EndIdentityValidation (keyTable);
1094 for (int k = 0; k < keyTable.Entries.Count; k++) {
1095 XsdKeyEntry entry = keyTable.Entries [k] as XsdKeyEntry;
1096 // Remove finished (maybe key not found) entries.
1097 if (entry.StartDepth == reader.Depth) {
1099 keyTable.FinishedEntries.Add (entry);
1100 else if (entry.KeySequence.SourceSchemaIdentity is XmlSchemaKey)
1101 HandleError ("Key sequence is missing.");
1102 keyTable.Entries.RemoveAt (k);
1105 // Pop validated key depth to find two or more fields.
1107 foreach (XsdKeyEntryField kf in entry.KeyFields) {
1108 if (!kf.FieldFound && kf.FieldFoundDepth == reader.Depth) {
1109 kf.FieldFoundDepth = 0;
1110 kf.FieldFoundPath = null;
1117 for (int i = 0; i < keyTables.Count; i++) {
1118 XsdKeyTable keyseq = this.keyTables [i] as XsdKeyTable;
1119 if (keyseq.StartDepth == reader.Depth) {
1120 //Console.WriteLine ("Finishing table.");
1121 keyTables.RemoveAt (i);
1126 // Reset xsi:nil, if required.
1127 if (xsiNilDepth == reader.Depth)
1131 // 3.11.4 Identity Constraint Satisfied
1133 private void AssessStartIdentityConstraints ()
1135 tmpKeyrefPool.Clear ();
1136 if (context.Element != null && context.Element.Constraints.Count > 0) {
1137 // (a) Create new key sequences, if required.
1138 foreach (XmlSchemaIdentityConstraint ident in context.Element.Constraints) {
1139 XsdKeyTable seq = CreateNewKeyTable (ident);
1140 if (ident is XmlSchemaKeyref)
1141 tmpKeyrefPool.Add (seq);
1145 // (b) Evaluate current key sequences.
1146 foreach (XsdKeyTable seq in this.keyTables) {
1147 if (seq.SelectorMatches (this.elementQNameStack, reader) != null) {
1148 // creates and registers new entry.
1149 XsdKeyEntry entry = new XsdKeyEntry (seq, reader);
1150 seq./*NotFound*/Entries.Add (entry);
1154 // (c) Evaluate field paths.
1155 foreach (XsdKeyTable seq in this.keyTables) {
1156 // If possible, create new field entry candidates.
1157 for (int i = 0; i < seq./*NotFound*/Entries.Count; i++) {
1158 XsdKeyEntry entry = seq./*NotFound*/Entries [i] as XsdKeyEntry;
1159 // if (entry.KeyFound)
1160 // FIXME: it should not be skipped for multiple key check!!
1163 entry.FieldMatches (this.elementQNameStack, this);
1164 } catch (Exception ex) {
1165 // FIXME: Such exception handling is not a good idea.
1166 HandleError ("Identity field value is invalid against its data type.", ex);
1172 private XsdKeyTable CreateNewKeyTable (XmlSchemaIdentityConstraint ident)
1174 XsdKeyTable seq = new XsdKeyTable (ident, this);
1175 seq.StartDepth = reader.Depth;
1176 XmlSchemaKeyref keyref = ident as XmlSchemaKeyref;
1177 this.keyTables.Add (seq);
1181 private void EndIdentityValidation (XsdKeyTable seq)
1183 ArrayList errors = new ArrayList ();
1184 foreach (XsdKeyEntry entry in seq./*NotFound*/Entries) {
1187 if (seq.SourceSchemaIdentity is XmlSchemaKey)
1188 errors.Add ("line " + entry.SelectorLineNumber + "position " + entry.SelectorLinePosition);
1190 if (errors.Count > 0)
1191 HandleError ("Invalid identity constraints were found. Key was not found. "
1192 + String.Join (", ", errors.ToArray (typeof (string)) as string []));
1195 // Find reference target
1196 XmlSchemaKeyref xsdKeyref = seq.SourceSchemaIdentity as XmlSchemaKeyref;
1197 if (xsdKeyref != null) {
1198 for (int i = this.keyTables.Count - 1; i >= 0; i--) {
1199 XsdKeyTable target = this.keyTables [i] as XsdKeyTable;
1200 if (target.SourceSchemaIdentity == xsdKeyref.Target) {
1201 seq.ReferencedKey = target;
1202 foreach (XsdKeyEntry entry in seq.FinishedEntries) {
1203 foreach (XsdKeyEntry targetEntry in target.FinishedEntries) {
1204 if (entry.CompareIdentity (targetEntry)) {
1205 entry.KeyRefFound = true;
1212 if (seq.ReferencedKey == null)
1213 HandleError ("Target key was not found.");
1214 foreach (XsdKeyEntry entry in seq.FinishedEntries) {
1215 if (!entry.KeyRefFound)
1216 errors.Add (" line " + entry.SelectorLineNumber + ", position " + entry.SelectorLinePosition);
1218 if (errors.Count > 0)
1219 HandleError ("Invalid identity constraints were found. Referenced key was not found: "
1220 + String.Join (" / ", errors.ToArray (typeof (string)) as string []));
1224 // Overrided Methods
1226 public override void Close ()
1231 public override string GetAttribute (int i)
1233 switch (reader.NodeType) {
1234 case XmlNodeType.XmlDeclaration:
1235 case XmlNodeType.DocumentType:
1236 return reader.GetAttribute (i);
1239 if (reader.AttributeCount > i)
1240 reader.GetAttribute (i);
1241 int defIdx = i - nonDefaultAttributeCount;
1242 if (i < AttributeCount)
1243 return defaultAttributes [defIdx].DefaultValue;
1245 throw new ArgumentOutOfRangeException ("i", i, "Specified attribute index is out of range.");
1248 public override string GetAttribute (string name)
1250 switch (reader.NodeType) {
1251 case XmlNodeType.XmlDeclaration:
1252 case XmlNodeType.DocumentType:
1253 return reader.GetAttribute (name);
1256 string value = reader.GetAttribute (name);
1260 XmlQualifiedName qname = SplitQName (name);
1261 return GetDefaultAttribute (qname.Name, qname.Namespace);
1264 private XmlQualifiedName SplitQName (string name)
1266 if (!XmlChar.IsName (name))
1267 throw new ArgumentException ("Invalid name was specified.", "name");
1269 Exception ex = null;
1270 XmlQualifiedName qname = XmlSchemaUtil.ToQName (reader, name, out ex);
1272 return XmlQualifiedName.Empty;
1277 public override string GetAttribute (string localName, string ns)
1279 switch (reader.NodeType) {
1280 case XmlNodeType.XmlDeclaration:
1281 case XmlNodeType.DocumentType:
1282 return reader.GetAttribute (localName, ns);
1285 string value = reader.GetAttribute (localName, ns);
1289 return GetDefaultAttribute (localName, ns);
1292 private string GetDefaultAttribute (string localName, string ns)
1294 int idx = this.FindDefaultAttribute (localName, ns);
1296 return defaultAttributes [idx].ValidatedDefaultValue;
1301 private int FindDefaultAttribute (string localName, string ns)
1303 for (int i = 0; i < this.defaultAttributes.Length; i++) {
1304 XmlSchemaAttribute attr = defaultAttributes [i];
1305 if (attr.QualifiedName.Name == localName &&
1306 attr.QualifiedName.Namespace == ns)
1312 bool IXmlLineInfo.HasLineInfo ()
1314 return readerLineInfo != null && readerLineInfo.HasLineInfo ();
1317 public override string LookupNamespace (string prefix)
1319 return reader.LookupNamespace (prefix);
1322 public override void MoveToAttribute (int i)
1324 switch (reader.NodeType) {
1325 case XmlNodeType.XmlDeclaration:
1326 case XmlNodeType.DocumentType:
1327 reader.MoveToAttribute (i);
1331 currentQName = null;
1332 if (i < this.nonDefaultAttributeCount) {
1333 reader.MoveToAttribute (i);
1334 this.currentDefaultAttribute = -1;
1335 this.defaultAttributeConsumed = false;
1338 if (i < AttributeCount) {
1339 this.currentDefaultAttribute = i - nonDefaultAttributeCount;
1340 this.defaultAttributeConsumed = false;
1343 throw new ArgumentOutOfRangeException ("i", i, "Attribute index is out of range.");
1346 public override bool MoveToAttribute (string name)
1348 switch (reader.NodeType) {
1349 case XmlNodeType.XmlDeclaration:
1350 case XmlNodeType.DocumentType:
1351 return reader.MoveToAttribute (name);
1354 currentQName = null;
1355 bool b = reader.MoveToAttribute (name);
1357 this.currentDefaultAttribute = -1;
1358 this.defaultAttributeConsumed = false;
1362 XmlQualifiedName qname = SplitQName (name);
1363 return MoveToDefaultAttribute (qname.Name, qname.Namespace);
1366 public override bool MoveToAttribute (string localName, string ns)
1368 switch (reader.NodeType) {
1369 case XmlNodeType.XmlDeclaration:
1370 case XmlNodeType.DocumentType:
1371 return reader.MoveToAttribute (localName, ns);
1374 currentQName = null;
1375 bool b = reader.MoveToAttribute (localName, ns);
1377 this.currentDefaultAttribute = -1;
1378 this.defaultAttributeConsumed = false;
1382 return MoveToDefaultAttribute (localName, ns);
1385 private bool MoveToDefaultAttribute (string localName, string ns)
1387 int idx = this.FindDefaultAttribute (localName, ns);
1390 currentDefaultAttribute = idx;
1391 defaultAttributeConsumed = false;
1395 public override bool MoveToElement ()
1397 currentDefaultAttribute = -1;
1398 defaultAttributeConsumed = false;
1399 currentQName = null;
1400 return reader.MoveToElement ();
1403 public override bool MoveToFirstAttribute ()
1405 switch (reader.NodeType) {
1406 case XmlNodeType.XmlDeclaration:
1407 case XmlNodeType.DocumentType:
1408 return reader.MoveToFirstAttribute ();
1411 currentQName = null;
1412 if (this.nonDefaultAttributeCount > 0) {
1413 bool b = reader.MoveToFirstAttribute ();
1415 currentDefaultAttribute = -1;
1416 defaultAttributeConsumed = false;
1421 if (this.defaultAttributes.Length > 0) {
1422 currentDefaultAttribute = 0;
1423 defaultAttributeConsumed = false;
1430 public override bool MoveToNextAttribute ()
1432 switch (reader.NodeType) {
1433 case XmlNodeType.XmlDeclaration:
1434 case XmlNodeType.DocumentType:
1435 return reader.MoveToNextAttribute ();
1438 currentQName = null;
1439 if (currentDefaultAttribute >= 0) {
1440 if (defaultAttributes.Length == currentDefaultAttribute + 1)
1442 currentDefaultAttribute++;
1443 defaultAttributeConsumed = false;
1447 bool b = reader.MoveToNextAttribute ();
1449 currentDefaultAttribute = -1;
1450 defaultAttributeConsumed = false;
1454 if (defaultAttributes.Length > 0) {
1455 currentDefaultAttribute = 0;
1456 defaultAttributeConsumed = false;
1463 private void ExamineAdditionalSchema ()
1465 XmlSchema schema = null;
1466 string schemaLocation = reader.GetAttribute ("schemaLocation", XmlSchema.InstanceNamespace);
1467 if (schemaLocation != null) {
1468 string [] tmp = XmlSchemaDatatype.FromName ("NMTOKENS").ParseValue (schemaLocation, NameTable, null) as string [];
1469 if (tmp.Length % 2 != 0)
1470 HandleError ("Invalid schemaLocation attribute format.");
1471 for (int i = 0; i < tmp.Length; i += 2) {
1473 Uri absUri = new Uri ((this.BaseURI != "" ? new Uri (BaseURI) : null), tmp [i + 1]);
1474 XmlTextReader xtr = new XmlTextReader (absUri.ToString ());
1475 schema = XmlSchema.Read (xtr, null);
1476 } catch (Exception ex) {
1477 // FIXME: better exception handling...
1478 // HandleError ("Errors were occured when resolving schemaLocation specified schema document.", ex);
1481 if (schema.TargetNamespace == null)
1482 schema.TargetNamespace = tmp [i];
1483 else if (schema.TargetNamespace != tmp [i])
1484 HandleError ("Specified schema has different target namespace.");
1487 if (schema != null) {
1489 schemas.Add (schema);
1490 } catch (XmlSchemaException ex) {
1495 string noNsSchemaLocation = reader.GetAttribute ("noNamespaceSchemaLocation", XmlSchema.InstanceNamespace);
1496 if (noNsSchemaLocation != null) {
1498 Uri absUri = new Uri ((this.BaseURI != "" ? new Uri (BaseURI) : null), noNsSchemaLocation);
1499 XmlTextReader xtr = new XmlTextReader (absUri.ToString ());
1500 schema = XmlSchema.Read (xtr, null);
1501 } catch (Exception ex) {
1502 // FIXME: better exception handling...
1503 // HandleError ("Errors were occured when resolving schemaLocation specified schema document.", ex);
1505 if (schema != null && schema.TargetNamespace != null)
1506 HandleError ("Specified schema has different target namespace.");
1508 if (schema != null) {
1510 schemas.Add (schema);
1511 } catch (XmlSchemaException ex) {
1517 public override bool Read ()
1519 nonDefaultAttributeCount = 0;
1520 currentDefaultAttribute = -1;
1521 defaultAttributeConsumed = false;
1522 currentQName = null;
1523 thisElementId = null;
1524 defaultAttributes = new XmlSchemaAttribute [0];
1526 elementQNameStack.RemoveAt (elementQNameStack.Count - 1);
1530 bool result = reader.Read ();
1531 // 3.3.4 ElementLocallyValidElement 7 = Root Valid.
1532 if (!result && missingIDReferences.Count > 0)
1533 HandleError ("There are missing ID references: " +
1535 this.missingIDReferences.ToArray (typeof (string)) as string []));
1537 switch (reader.NodeType) {
1538 case XmlNodeType.Element:
1539 nonDefaultAttributeCount = reader.AttributeCount;
1541 if (reader.Depth == 0)
1542 ExamineAdditionalSchema ();
1544 this.elementQNameStack.Add (new XmlQualifiedName (reader.LocalName, reader.NamespaceURI));
1546 // If there is no schema information, then no validation is performed.
1547 if (schemas.Count == 0)
1550 // context.Load (reader.Depth);
1551 if (skipValidationDepth < 0 || reader.Depth <= skipValidationDepth) {
1552 if (shouldValidateCharacters) {
1553 ValidateEndCharacters ();
1554 shouldValidateCharacters = false;
1556 AssessStartElementSchemaValidity ();
1557 storedCharacters.Length = 0;
1562 if (reader.IsEmptyElement)
1563 goto case XmlNodeType.EndElement;
1565 shouldValidateCharacters = true;
1567 case XmlNodeType.EndElement:
1568 if (reader.Depth == skipValidationDepth) {
1569 skipValidationDepth = -1;
1572 // context.Load (reader.Depth);
1573 if (shouldValidateCharacters) {
1574 ValidateEndCharacters ();
1575 shouldValidateCharacters = false;
1577 AssessEndElementSchemaValidity ();
1579 storedCharacters.Length = 0;
1580 childParticleState = null;
1584 case XmlNodeType.CDATA:
1585 case XmlNodeType.SignificantWhitespace:
1586 case XmlNodeType.Text:
1587 XmlSchemaComplexType ct = context.ActualType as XmlSchemaComplexType;
1588 if (ct != null && storedCharacters.Length > 0) {
1589 switch (ct.ContentType) {
1590 case XmlSchemaContentType.ElementOnly:
1591 case XmlSchemaContentType.Empty:
1592 HandleError ("Not allowed character content was found.");
1597 ValidateCharacters ();
1604 public override bool ReadAttributeValue ()
1606 if (currentDefaultAttribute < 0)
1607 return reader.ReadAttributeValue ();
1609 if (this.defaultAttributeConsumed)
1612 defaultAttributeConsumed = true;
1617 public override string ReadInnerXml ()
1619 // MS.NET 1.0 has a serious bug here. It skips validation.
1620 return reader.ReadInnerXml ();
1623 public override string ReadOuterXml ()
1625 // MS.NET 1.0 has a serious bug here. It skips validation.
1626 return reader.ReadOuterXml ();
1630 // XmlReader.ReadString() should call derived this.Read().
1631 public override string ReadString ()
1634 return reader.ReadString ();
1636 return base.ReadString ();
1640 // This class itself does not have this feature.
1641 public override void ResolveEntity ()
1643 reader.ResolveEntity ();
1646 internal class XsdValidationContext
1648 Hashtable contextStack;
1650 public XsdValidationContext ()
1652 contextStack = new Hashtable ();
1655 // Some of them might be missing (See the spec section 5.3, and also 3.3.4).
1656 public XmlSchemaElement Element;
1657 public XsdValidationState ParticleState;
1658 public XmlSchemaAttribute [] DefaultAttributes;
1660 // Some of them might be missing (See the spec section 5.3).
1661 public object SchemaType;
1663 public object LocalTypeDefinition;
1665 public object ActualType {
1667 if (LocalTypeDefinition != null)
1668 return LocalTypeDefinition;
1674 public void Clear ()
1678 ParticleState = null;
1679 LocalTypeDefinition = null;
1682 public void PushScope (int depth)
1684 contextStack [depth] = this.MemberwiseClone ();
1687 public void PopScope (int depth)
1690 contextStack.Remove (depth + 1);
1693 public void Load (int depth)
1696 XsdValidationContext restored = (XsdValidationContext) contextStack [depth];
1697 if (restored != null) {
1698 this.Element = restored.Element;
1699 this.ParticleState = restored.ParticleState;
1700 this.SchemaType = restored.SchemaType;
1701 this.LocalTypeDefinition = restored.LocalTypeDefinition;
1707 internal class XsdValidityState
1709 ArrayList currentParticles = new ArrayList ();
1710 ArrayList occured = new ArrayList ();
1711 Hashtable xsAllConsumed = new Hashtable ();
1712 XmlSchemaParticle parciele;
1715 public XsdValidityState (XmlSchemaParticle particle)
1717 this.parciele = particle;
1718 currentParticles.Add (particle);