2008-12-08 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml.Schema / XmlSchemaValidator.cs
old mode 100755 (executable)
new mode 100644 (file)
index 7225017..a1d4e9d
@@ -80,7 +80,7 @@ using ValException = System.Xml.Schema.XmlSchemaValidationException;
 
 namespace System.Xml.Schema
 {
-       public class XmlSchemaValidator
+       public sealed class XmlSchemaValidator
        {
                enum Transition {
                        None,
@@ -153,8 +153,11 @@ namespace System.Xml.Schema
                int xsiNilDepth = -1;
                int skipValidationDepth = -1;
 
-               SOMObject currentType;
-
+               // LAMESPEC: XmlValueGetter is bogus by design because there
+               // is no way to get associated schema type for current value.
+               // Here XmlSchemaValidatingReader needs "current type"
+               // information to validate attribute values.
+               internal XmlSchemaDatatype CurrentAttributeType;
 
                #endregion
 
@@ -181,11 +184,8 @@ namespace System.Xml.Schema
                        set { xmlResolver = value; }
                }
 
-               [MonoTODO]
                public Uri SourceUri {
                        get { return sourceUri; }
-                       // FIXME: actually there seems no setter, but then
-                       // it will never make sense.
                        set { sourceUri = value; }
                }
                #endregion
@@ -202,12 +202,12 @@ namespace System.Xml.Schema
 
                private bool IgnoreWarnings {
                        get { return (options & ValidationFlags
-                               .IgnoreValidationWarnings) != 0; }
+                               .ReportValidationWarnings) == 0; }
                }
 
                private bool IgnoreIdentity {
                        get { return (options & ValidationFlags
-                               .IgnoreIdentityConstraints) != 0; }
+                               .ProcessIdentityConstraints) == 0; }
                }
 
                #endregion
@@ -241,7 +241,7 @@ namespace System.Xml.Schema
                                al.Add (p);
                }
 
-               [MonoTODO ("Need some tests.")]
+               [MonoTODO] // Need some tests.
                // Its behavior is not obvious. For example, it does not
                // contain groups (xs:sequence/xs:choice/xs:all). Since it
                // might contain xs:any, it could not be of type element[].
@@ -258,46 +258,47 @@ namespace System.Xml.Schema
                                typeof (XmlSchemaParticle));
                }
 
-               public void GetUnspecifiedDefaultAttributes (ArrayList list)
+               public void GetUnspecifiedDefaultAttributes (ArrayList defaultAttributeList)
                {
+                       if (defaultAttributeList == null)
+                               throw new ArgumentNullException ("defaultAttributeList");
+
                        if (transition != Transition.StartTag)
                                throw new InvalidOperationException ("Method 'GetUnsoecifiedDefaultAttributes' works only when the validator state is inside a start tag.");
                        foreach (XmlSchemaAttribute attr
                                in GetExpectedAttributes ())
                                if (attr.ValidatedDefaultValue != null || attr.ValidatedFixedValue != null)
-                                       list.Add (attr);
+                                       defaultAttributeList.Add (attr);
 
-                       list.AddRange (defaultAttributes);
-               }
-
-               public object FindID (string name)
-               {
-                       // It looks returning the element's local name (string)
-                       return idManager.FindID (name);
+                       defaultAttributeList.AddRange (defaultAttributes);
                }
 
                // State Controller
 
                public void AddSchema (XmlSchema schema)
                {
+                       if (schema == null)
+                               throw new ArgumentNullException ("schema");
                        schemas.Add (schema);
                        schemas.Compile ();
                }
 
                public void Initialize ()
                {
-                       Initialize (null);
-               }
-
-               public void Initialize (SOMObject startType)
-               {
-                       this.startType = startType;
                        transition = Transition.Content;
                        state = new XsdParticleStateManager ();
                        if (!schemas.IsCompiled)
                                schemas.Compile ();
                }
 
+               public void Initialize (SOMObject partialValidationType)
+               {
+                       if (partialValidationType == null)
+                               throw new ArgumentNullException ("partialValidationType");
+                       this.startType = partialValidationType;
+                       Initialize ();
+               }
+
                // It must be called at the end of the validation (to check
                // identity constraints etc.).
                public void EndValidation ()
@@ -318,7 +319,7 @@ namespace System.Xml.Schema
                }
 
                // I guess it is for validation error recovery
-               [MonoTODO ("Find out how XmlSchemaInfo is used.")]
+               [MonoTODO] // FIXME: Find out how XmlSchemaInfo is used.
                public void SkipToEndElement (XmlSchemaInfo info)
                {
                        CheckState (Transition.Content);
@@ -327,11 +328,22 @@ namespace System.Xml.Schema
                        state.PopContext ();
                }
 
+               public object ValidateAttribute (
+                       string localName,
+                       string ns,
+                       string attributeValue,
+                       XmlSchemaInfo info)
+               {
+                       if (attributeValue == null)
+                               throw new ArgumentNullException ("attributeValue");
+                       return ValidateAttribute (localName, ns, delegate () { return attributeValue; }, info);
+               }
+
                // I guess this weird XmlValueGetter is for such case that
                // value might not be required (and thus it improves 
                // performance in some cases. Doh).
 
-               // The return value is typed primitive, is possible.
+               // The return value is typed primitive, if possible.
                // AttDeriv
                public object ValidateAttribute (
                        string localName,
@@ -339,6 +351,13 @@ namespace System.Xml.Schema
                        XmlValueGetter attributeValue,
                        XmlSchemaInfo info)
                {
+                       if (localName == null)
+                               throw new ArgumentNullException ("localName");
+                       if (ns == null)
+                               throw new ArgumentNullException ("ns");
+                       if (attributeValue == null)
+                               throw new ArgumentNullException ("attributeValue");
+
                        CheckState (Transition.StartTag);
 
                        QName qname = new QName (localName, ns);
@@ -352,11 +371,14 @@ namespace System.Xml.Schema
                        if (schemas.Count == 0)
                                return null;
 
-                       // 3.3.4 Element Locally Valid (Type) - attribute
-                       if (Context.ActualType is ComplexType)
-                               return AssessAttributeElementLocallyValidType (localName, ns, attributeValue, info);
-                       else
-                               HandleError ("Current simple type cannot accept attributes other than schema instance namespace.");
+                       if (Context.Element != null && Context.XsiType == null) {
+
+                               // 3.3.4 Element Locally Valid (Type) - attribute
+                               if (Context.ActualType is ComplexType)
+                                       return AssessAttributeElementLocallyValidType (localName, ns, attributeValue, info);
+                               else
+                                       HandleError ("Current simple type cannot accept attributes other than schema instance namespace.");
+                       }
                        return null;
                }
 
@@ -378,6 +400,11 @@ namespace System.Xml.Schema
                        string schemaLocation,
                        string noNsSchemaLocation)
                {
+                       if (localName == null)
+                               throw new ArgumentNullException ("localName");
+                       if (ns == null)
+                               throw new ArgumentNullException ("ns");
+
                        CheckState (Transition.Content);
                        transition = Transition.StartTag;
 
@@ -423,9 +450,9 @@ namespace System.Xml.Schema
                        }
                }
 
-               public object ValidateEndElement (XmlSchemaInfo schemaInfo)
+               public object ValidateEndElement (XmlSchemaInfo info)
                {
-                       return ValidateEndElement (schemaInfo, null);
+                       return ValidateEndElement (info, null);
                }
 
                // The return value is typed primitive, if supplied.
@@ -433,10 +460,15 @@ namespace System.Xml.Schema
                // represented by current simple content type. (try passing
                // some kind of object to this method to check the behavior.)
                // EndTagDeriv
-               [MonoTODO ("Handle 'var' parameter.")]
-               public object ValidateEndElement (XmlSchemaInfo schemaInfo,
+               [MonoTODO] // FIXME: Handle 'var' parameter.
+               public object ValidateEndElement (XmlSchemaInfo info,
                        object var)
                {
+                       // If it is going to validate an empty element, then
+                       // first validate end of attributes.
+                       if (transition == Transition.StartTag)
+                               ValidateEndOfAttributes (info);
+
                        CheckState (Transition.Content);
 
                        elementQNameStack.RemoveAt (elementQNameStack.Count - 1);
@@ -452,12 +484,13 @@ namespace System.Xml.Schema
                        if (depth == skipValidationDepth)
                                skipValidationDepth = -1;
                        else if (skipValidationDepth < 0 || depth <= skipValidationDepth)
-                               ret = AssessEndElementSchemaValidity (schemaInfo);
+                               ret = AssessEndElementSchemaValidity (info);
                        return ret;
                }
 
                // StartTagCloseDeriv
-               public void ValidateEndOfAttributes ()
+               // FIXME: fill validity inside this invocation.
+               public void ValidateEndOfAttributes (XmlSchemaInfo info)
                {
                        try {
                                CheckState (Transition.StartTag);
@@ -465,42 +498,63 @@ namespace System.Xml.Schema
                                if (schemas.Count == 0)
                                        return;
 
-                               AssessCloseStartElementSchemaValidity ();
+                               if (skipValidationDepth < 0 || depth <= skipValidationDepth)
+                                       AssessCloseStartElementSchemaValidity (info);
+                               depth++;
                        } finally {
                                occuredAtts.Clear ();
                        }
                }
 
+               // LAMESPEC: It should also receive XmlSchemaInfo so that
+               // a validator application can receive simple type or
+               // or content type validation errors.
+               public void ValidateText (string value)
+               {
+                       if (value == null)
+                               throw new ArgumentNullException ("value");
+                       ValidateText (delegate () { return value; });
+               }
+
                // TextDeriv ... without text. Maybe typed check is done by
                // ValidateAtomicValue().
                public void ValidateText (XmlValueGetter getter)
                {
+                       if (getter == null)
+                               throw new ArgumentNullException ("getter");
+
                        CheckState (Transition.Content);
                        if (schemas.Count == 0)
                                return;
 
                        ComplexType ct = Context.ActualType as ComplexType;
-                       if (ct != null && storedCharacters.Length > 0) {
+                       if (ct != null) {
                                switch (ct.ContentType) {
-                               case XmlSchemaContentType.ElementOnly:
                                case XmlSchemaContentType.Empty:
                                        HandleError ("Not allowed character content was found.");
                                        break;
+                               case XmlSchemaContentType.ElementOnly:
+                                       string s = storedCharacters.ToString ();
+                                       if (s.Length > 0 && !XmlChar.IsWhitespace (s))
+                                               HandleError ("Not allowed character content was found.");
+                                       break;
                                }
                        }
 
                        ValidateCharacters (getter);
                }
 
-               // TextDeriv...?
-               [MonoTODO]
-               public void ValidateWhitespace (XmlValueGetter getter)
+               public void ValidateWhitespace (string value)
                {
-                       CheckState (Transition.Content);
-                       if (schemas.Count == 0)
-                               return;
+                       if (value == null)
+                               throw new ArgumentNullException ("value");
+                       ValidateWhitespace (delegate () { return value; });
+               }
 
-//                     throw new NotImplementedException ();
+               // TextDeriv. It should do the same as ValidateText() in our actual implementation (whitespaces are conditioned).
+               public void ValidateWhitespace (XmlValueGetter getter)
+               {
+                       ValidateText (getter);
                }
 
                #endregion
@@ -560,7 +614,7 @@ namespace System.Xml.Schema
                                        throw new InvalidOperationException ("Initialize() must be called before processing validation.");
                                else
                                        throw new InvalidOperationException (
-                                               String.Format ("Unexpected attempt to validation state transition from {0} to {1} was happened.",
+                                               String.Format ("Unexpected attempt to validate state transition from {0} to {1}.",
                                                        transition,
                                                        expected));
                        }
@@ -590,7 +644,7 @@ namespace System.Xml.Schema
                        if (Context.IsInvalid)
                                HandleError ("Invalid start element: " + ns + ":" + localName);
 
-                       Context.SetElement (state.CurrentElement);
+                       Context.PushCurrentElement (state.CurrentElement);
                }
 
                private void AssessOpenStartElementSchemaValidity (
@@ -607,7 +661,7 @@ namespace System.Xml.Schema
                        // [Schema Validity Assessment (Element) 1.1]
                        if (Context.Element == null) {
                                state.CurrentElement = FindElement (localName, ns);
-                               Context.SetElement (state.CurrentElement);
+                               Context.PushCurrentElement (state.CurrentElement);
                        }
 
 #region Key Constraints
@@ -618,16 +672,16 @@ namespace System.Xml.Schema
 #endregion
                }
 
-               private void AssessCloseStartElementSchemaValidity ()
+               private void AssessCloseStartElementSchemaValidity (XmlSchemaInfo info)
                {
                        if (Context.XsiType != null)
-                               AssessCloseStartElementLocallyValidType ();
+                               AssessCloseStartElementLocallyValidType (info);
                        else if (Context.Element != null) {
                                // element locally valid is checked only when
                                // xsi:type does not exist.
                                AssessElementLocallyValidElement ();
                                if (Context.Element.ElementType != null)
-                                       AssessCloseStartElementLocallyValidType ();
+                                       AssessCloseStartElementLocallyValidType (info);
                        }
 
                        if (Context.Element == null) {
@@ -664,8 +718,6 @@ namespace System.Xml.Schema
                                        next = state.Create (XmlSchemaParticle.Empty);
                        }
                        Context.State = next;
-
-                       depth++;
                }
 
                // It must be invoked after xsi:nil turned out not to be in
@@ -684,7 +736,7 @@ namespace System.Xml.Schema
                }
 
                // 3.3.4 Element Locally Valid (Type)
-               private void AssessCloseStartElementLocallyValidType ()
+               private void AssessCloseStartElementLocallyValidType (XmlSchemaInfo info)
                {
                        object schemaType = Context.ActualType;
                        if (schemaType == null) {       // 1.
@@ -698,12 +750,13 @@ namespace System.Xml.Schema
                                // Attributes are checked in ValidateAttribute().
                        } else if (cType != null) {
                                // 3.2. Also, 2. is checked there.
-                               AssessCloseStartElementLocallyValidComplexType (cType);
+                               AssessCloseStartElementLocallyValidComplexType (cType, info);
                        }
                }
 
                // 3.4.4 Element Locally Valid (Complex Type)
-               private void AssessCloseStartElementLocallyValidComplexType (ComplexType cType)
+               // FIXME: use SchemaInfo for somewhere (? it is passed to ValidateEndOfAttributes() for some reason)
+               private void AssessCloseStartElementLocallyValidComplexType (ComplexType cType, XmlSchemaInfo info)
                {
                        // 1.
                        if (cType.IsAbstract) {
@@ -747,13 +800,13 @@ namespace System.Xml.Schema
                        XsAttribute attdecl = attMatch as XsAttribute;
                        if (attdecl != null) {
                                AssessAttributeLocallyValidUse (attdecl);
-                               return AssessAttributeLocallyValid (attdecl, getter);
+                               return AssessAttributeLocallyValid (attdecl, info, getter);
                        } // otherwise anyAttribute or null.
                        return null;
                }
 
                // 3.2.4 Attribute Locally Valid and 3.4.4
-               private object AssessAttributeLocallyValid (XsAttribute attr, XmlValueGetter getter)
+               private object AssessAttributeLocallyValid (XsAttribute attr, XmlSchemaInfo info, XmlValueGetter getter)
                {
                        // 2. - 4.
                        if (attr.AttributeType == null)
@@ -763,16 +816,24 @@ namespace System.Xml.Schema
                                dt = ((SimpleType) attr.AttributeType).Datatype;
                        // It is a bit heavy process, so let's omit as long as possible ;-)
                        if (dt != SimpleType.AnySimpleType || attr.ValidatedFixedValue != null) {
-                               string normalized = dt.Normalize (getter ());
                                object parsedValue = null;
                                try {
-                                       parsedValue = dt.ParseValue (normalized, nameTable, nsResolver);
-                               } catch (Exception ex) { // FIXME: (wishlist) It is bad manner ;-(
-                                       HandleError ("Attribute value is invalid against its data type " + dt.TokenizedType, ex);
+                                       CurrentAttributeType = dt;
+                                       parsedValue = getter ();
+                               } catch (Exception ex) { // It is inevitable and bad manner.
+                                       HandleError (String.Format ("Attribute value is invalid against its data type {0}", dt != null ? dt.TokenizedType : default (XmlTokenizedType)), ex);
                                }
-                               if (attr.ValidatedFixedValue != null && attr.ValidatedFixedValue != normalized) {
-                                       HandleError ("The value of the attribute " + attr.QualifiedName + " does not match with its fixed value.");
-                                       parsedValue = dt.ParseValue (attr.ValidatedFixedValue, nameTable, nsResolver);
+
+                               // check part of 3.14.4 StringValid
+                               SimpleType st = attr.AttributeType as SimpleType;
+                               if (st != null)
+                                       ValidateRestrictedSimpleTypeValue (st, ref dt, new XmlAtomicValue (parsedValue, attr.AttributeSchemaType).Value);
+
+                               if (attr.ValidatedFixedValue != null && 
+                                       !XmlSchemaUtil.AreSchemaDatatypeEqual (
+                                       attr.AttributeSchemaType.Datatype as XsdAnySimpleType, attr.ValidatedFixedTypedValue, dt as XsdAnySimpleType, parsedValue)) {
+                                       HandleError (String.Format ("The value of the attribute {0} does not match with its fixed value '{1}' in the space of type {2}", attr.QualifiedName, attr.ValidatedFixedValue, dt));
+                                       parsedValue = attr.ValidatedFixedTypedValue;
                                }
 #region ID Constraints
                                if (!IgnoreIdentity) {
@@ -808,10 +869,10 @@ namespace System.Xml.Schema
                private object AssessEndElementSchemaValidity (
                        XmlSchemaInfo info)
                {
-                       ValidateEndElementParticle ();  // validate against childrens' state.
-
                        object ret = ValidateEndSimpleContent (info);
 
+                       ValidateEndElementParticle ();  // validate against childrens' state.
+
                        // 3.3.4 Assess ElementLocallyValidElement 5: value constraints.
                        // 3.3.4 Assess ElementLocallyValidType 3.1.3. = StringValid(3.14.4)
                        // => ValidateEndSimpleContent ().
@@ -834,6 +895,7 @@ namespace System.Xml.Schema
                                        HandleError ("Invalid end element. There are still required content items.");
                                }
                        }
+                       Context.PopCurrentElement ();
                        state.PopContext ();
                }
 
@@ -843,8 +905,10 @@ namespace System.Xml.Schema
                        if (xsiNilDepth >= 0 && xsiNilDepth < depth)
                                HandleError ("Element item appeared, while current element context is nil.");
 
-                       if (shouldValidateCharacters)
+                       if (shouldValidateCharacters) {
+                               CurrentAttributeType = null;
                                storedCharacters.Append (getter ());
+                       }
                }
 
 
@@ -885,9 +949,12 @@ namespace System.Xml.Schema
                                        dt = ct.Datatype;
                                        switch (ct.ContentType) {
                                        case XmlSchemaContentType.ElementOnly:
+                                               if (value.Length > 0 && !XmlChar.IsWhitespace (value))
+                                                       HandleError ("Character content not allowed in an elementOnly model.");
+                                               break;
                                        case XmlSchemaContentType.Empty:
                                                if (value.Length > 0)
-                                                       HandleError ("Character content not allowed.");
+                                                       HandleError ("Character content not allowed in an empty model.");
                                                break;
                                        }
                                }
@@ -910,8 +977,8 @@ namespace System.Xml.Schema
                        if (info != null) {
                                info.IsNil = xsiNilDepth >= 0;
                                info.SchemaElement = null;
-                               info.SchemaType = st;
-                               if (st == null)
+                               info.SchemaType = Context.ActualType as XmlSchemaType;
+                               if (info.SchemaType == null)
                                        info.SchemaType = XmlSchemaType.GetBuiltInSimpleType (dt.TypeCode);
                                info.SchemaAttribute = null;
                                info.IsDefault = false; // FIXME: might be true
@@ -954,7 +1021,7 @@ namespace System.Xml.Schema
                                                if (itemDatatype != null) {
                                                        try {
                                                                retValues [vi] = itemDatatype.ParseValue (each, nameTable, nsResolver);
-                                                       } catch (Exception ex) { // FIXME: (wishlist) better exception handling ;-(
+                                                       } catch (Exception ex) { // It is inevitable and bad manner.
                                                                HandleError ("List type value contains one or more invalid values.", ex);
                                                                break;
                                                        }
@@ -976,7 +1043,7 @@ namespace System.Xml.Schema
                                                        if (itemDatatype != null) {
                                                                try {
                                                                        ret = itemDatatype.ParseValue (each, nameTable, nsResolver);
-                                                               } catch (Exception) { // FIXME: (wishlist) better exception handling ;-(
+                                                               } catch (Exception) { // It is inevitable and bad manner.
                                                                        continue;
                                                                }
                                                        }
@@ -1007,9 +1074,9 @@ namespace System.Xml.Schema
                                                 // mmm, will check later.
                                                SimpleType baseType = st.BaseXmlSchemaType as SimpleType;
                                                if (baseType != null) {
-                                                        ret = AssessStringValid (baseType, dt, normalized);
+                                                        ret = AssessStringValid (baseType, dt, value);
                                                }
-                                               if (!str.ValidateValueWithFacets (normalized, nameTable)) {
+                                               if (!str.ValidateValueWithFacets (value, nameTable, nsResolver)) {
                                                        HandleError ("Specified value was invalid against the facets.");
                                                        break;
                                                }
@@ -1021,13 +1088,98 @@ namespace System.Xml.Schema
                        if (validatedDatatype != null) {
                                try {
                                        ret = validatedDatatype.ParseValue (value, nameTable, nsResolver);
-                               } catch (Exception ex) {        // FIXME: (wishlist) It is bad manner ;-(
+                               } catch (Exception ex) { // It is inevitable and bad manner.
                                        HandleError (String.Format ("Invalidly typed data was specified."), ex);
                                }
                        }
                        return ret;
                }
 
+               private void ValidateRestrictedSimpleTypeValue (SimpleType st, ref XsDatatype dt, string normalized)
+               {
+                       {
+                               string [] values;
+                               XsDatatype itemDatatype;
+                               SimpleType itemSimpleType;
+                               switch (st.DerivedBy) {
+                               case XmlSchemaDerivationMethod.List:
+                                       SimpleTypeList listContent = st.Content as SimpleTypeList;
+                                       values = normalized.Split (XmlChar.WhitespaceChars);
+                                       itemDatatype = listContent.ValidatedListItemType as XsDatatype;
+                                       itemSimpleType = listContent.ValidatedListItemType as SimpleType;
+                                       for (int vi = 0; vi < values.Length; vi++) {
+                                               string each = values [vi];
+                                               if (each == String.Empty)
+                                                       continue;
+                                               // validate against ValidatedItemType
+                                               if (itemDatatype != null) {
+                                                       try {
+                                                               itemDatatype.ParseValue (each, nameTable, nsResolver);
+                                                       } catch (Exception ex) { // FIXME: (wishlist) better exception handling ;-(
+                                                               HandleError ("List type value contains one or more invalid values.", ex);
+                                                               break;
+                                                       }
+                                               }
+                                               else
+                                                       AssessStringValid (itemSimpleType, itemSimpleType.Datatype, each);
+                                       }
+                                       break;
+                               case XmlSchemaDerivationMethod.Union:
+                                       SimpleTypeUnion union = st.Content as SimpleTypeUnion;
+                                       {
+                                               string each = normalized;
+                                               // validate against ValidatedItemType
+                                               bool passed = false;
+                                               foreach (object eachType in union.ValidatedTypes) {
+                                                       itemDatatype = eachType as XsDatatype;
+                                                       itemSimpleType = eachType as SimpleType;
+                                                       if (itemDatatype != null) {
+                                                               try {
+                                                                       itemDatatype.ParseValue (each, nameTable, nsResolver);
+                                                               } catch (Exception) { // FIXME: (wishlist) better exception handling ;-(
+                                                                       continue;
+                                                               }
+                                                       }
+                                                       else {
+                                                               try {
+                                                                       AssessStringValid (itemSimpleType, itemSimpleType.Datatype, each);
+                                                               } catch (ValException) {
+                                                                       continue;
+                                                               }
+                                                       }
+                                                       passed = true;
+                                                       break;
+                                               }
+                                               if (!passed) {
+                                                       HandleError ("Union type value contains one or more invalid values.");
+                                                       break;
+                                               }
+                                       }
+                                       break;
+                               case XmlSchemaDerivationMethod.Restriction:
+                                       SimpleTypeRest str = st.Content as SimpleTypeRest;
+                                       // facet validation
+                                       if (str != null) {
+                                               /* Don't forget to validate against inherited type's facets 
+                                                * Could we simplify this by assuming that the basetype will also
+                                                * be restriction?
+                                                * */
+                                                // mmm, will check later.
+                                               SimpleType baseType = st.BaseXmlSchemaType as SimpleType;
+                                               if (baseType != null) {
+                                                        AssessStringValid(baseType, dt, normalized);
+                                               }
+                                               if (!str.ValidateValueWithFacets (normalized, nameTable, nsResolver)) {
+                                                       HandleError ("Specified value was invalid against the facets.");
+                                                       break;
+                                               }
+                                       }
+                                       dt = st.Datatype;
+                                       break;
+                               }
+                       }
+               }
+
                #endregion
 
                #region Key Constraints Validation
@@ -1075,6 +1227,7 @@ namespace System.Xml.Schema
                                XsdKeyTable seq  = (XsdKeyTable) keyTables [i];
                                // If possible, create new field entry candidates.
                                for (int j = 0; j < seq.Entries.Count; j++) {
+                                       CurrentAttributeType = null;
                                        try {
                                                seq.Entries [j].ProcessMatch (
                                                        isAttr,
@@ -1100,10 +1253,6 @@ namespace System.Xml.Schema
                        }
                }
 
-               private void ProcessKeyEntryOne (XsdKeyEntry entry, bool isAttr, bool isNil, object schemaType, string attrName, string attrNs, XmlValueGetter getter)
-               {
-               }
-
                private void ValidateEndElementKeyConstraints ()
                {
                        // Reset Identity constraints.
@@ -1205,7 +1354,7 @@ namespace System.Xml.Schema
                                        if (dt != null) {
                                                try {
                                                        identity = dt.ParseValue (value, nameTable, nsResolver);
-                                               } catch (Exception ex) { // FIXME: (wishlist) This is bad manner ;-(
+                                               } catch (Exception ex) { // It is inevitable and bad manner.
                                                        HandleError ("Identity value is invalid against its data type " + dt.TokenizedType, ex);
                                                }
                                        }
@@ -1367,7 +1516,7 @@ namespace System.Xml.Schema
                        for (int i = 0; i < tmp.Length; i += 2) {
                                try {
                                        schema = ReadExternalSchema (tmp [i + 1]);
-                               } catch (Exception ex) { // FIXME: (wishlist) It is bad manner ;-(
+                               } catch (Exception ex) { // It is inevitable and bad manner.
                                        HandleError ("Could not resolve schema location URI: " + schemaLocation, ex, true);
                                        continue;
                                }
@@ -1396,7 +1545,7 @@ namespace System.Xml.Schema
 
                        try {
                                schema = ReadExternalSchema (noNsSchemaLocation);
-                       } catch (Exception ex) { // FIXME: (wishlist) It is bad manner ;-(
+                       } catch (Exception ex) { // It is inevitable and bad manner.
                                HandleError ("Could not resolve schema location URI: " + noNsSchemaLocation, ex, true);
                        }
                        if (schema != null && schema.TargetNamespace != null)