Don't add IDREFs to set of missing IDs multiple times
[mono.git] / mcs / class / System.XML / Mono.Xml.Schema / XsdValidatingReader.cs
index c36d86f20085a81039eee945e1fff1b30d0364d0..8eea3d30a2aa07cfed6f729da274dd2dc59f5487 100644 (file)
@@ -468,7 +468,7 @@ namespace Mono.Xml.Schema
                        if (Context.IsInvalid)
                                HandleError ("Invalid start element: " + reader.NamespaceURI + ":" + reader.LocalName);
 
-                       Context.SetElement (state.CurrentElement);
+                       Context.PushCurrentElement (state.CurrentElement);
                }
 
                private void ValidateEndElementParticle ()
@@ -478,6 +478,7 @@ namespace Mono.Xml.Schema
                                        HandleError ("Invalid end element: " + reader.Name);
                                }
                        }
+                       Context.PopCurrentElement ();
                        state.PopContext ();
                }
 
@@ -525,10 +526,13 @@ namespace Mono.Xml.Schema
                                        dt = ct.Datatype;
                                        switch (ct.ContentType) {
                                        case XmlSchemaContentType.ElementOnly:
-                                       case XmlSchemaContentType.Empty:
                                                if (value.Length > 0 && !XmlChar.IsWhitespace (value))
                                                        HandleError ("Character content not allowed.");
                                                break;
+                                       case XmlSchemaContentType.Empty:
+                                               if (value.Length > 0)
+                                                       HandleError ("Character content not allowed.");
+                                               break;
                                        }
                                }
                        }
@@ -555,6 +559,20 @@ namespace Mono.Xml.Schema
                        XsDatatype validatedDatatype = dt;
                        if (st != null) {
                                string normalized = validatedDatatype.Normalize (value);
+                               ValidateRestrictedSimpleTypeValue (st, ref validatedDatatype, normalized);
+                       }
+                       if (validatedDatatype != null) {
+                               try {
+                                       validatedDatatype.ParseValue (value, NameTable, NamespaceManager);
+                               } catch (Exception ex) {        // FIXME: (wishlist) It is bad manner ;-(
+                                       HandleError ("Invalidly typed data was specified.", ex);
+                               }
+                       }
+               }
+
+               void ValidateRestrictedSimpleTypeValue (SimpleType st, ref XsDatatype dt, string normalized)
+               {
+                       {
                                string [] values;
                                XsDatatype itemDatatype;
                                SimpleType itemSimpleType;
@@ -624,24 +642,17 @@ namespace Mono.Xml.Schema
                                                 // mmm, will check later.
                                                SimpleType baseType = st.BaseXmlSchemaType as SimpleType;
                                                if (baseType != null) {
-                                                        AssessStringValid(baseType, dt, value);
+                                                        AssessStringValid(baseType, dt, normalized);
                                                }
-                                               if (!str.ValidateValueWithFacets (value, NameTable)) {
+                                               if (!str.ValidateValueWithFacets (normalized, NameTable, NamespaceManager)) {
                                                        HandleError ("Specified value was invalid against the facets.");
                                                        break;
                                                }
                                        }
-                                       validatedDatatype = st.Datatype;
+                                       dt = st.Datatype;
                                        break;
                                }
                        }
-                       if (validatedDatatype != null) {
-                               try {
-                                       validatedDatatype.ParseValue (value, NameTable, NamespaceManager);
-                               } catch (Exception ex) {        // FIXME: (wishlist) It is bad manner ;-(
-                                       HandleError ("Invalidly typed data was specified.", ex);
-                               }
-                       }
                }
 
                private object GetXsiType (string name)
@@ -758,7 +769,7 @@ namespace Mono.Xml.Schema
                        // [Schema Validity Assessment (Element) 1.1]
                        if (Context.Element == null) {
                                state.CurrentElement = FindElement (reader.LocalName, reader.NamespaceURI);
-                               Context.SetElement (state.CurrentElement);
+                               Context.PushCurrentElement (state.CurrentElement);
                        }
                        if (Context.Element != null) {
                                if (Context.XsiType == null) {
@@ -954,12 +965,20 @@ namespace Mono.Xml.Schema
                        if (dt != SimpleType.AnySimpleType || attr.ValidatedFixedValue != null) {
                                string normalized = dt.Normalize (reader.Value);
                                object parsedValue = null;
+
+                               // check part of 3.14.4 StringValid
+                               SimpleType st = attr.AttributeType as SimpleType;
+                               if (st != null)
+                                       ValidateRestrictedSimpleTypeValue (st, ref dt, normalized);
+
                                try {
                                        parsedValue = dt.ParseValue (normalized, reader.NameTable, NamespaceManager);
                                } catch (Exception ex) { // FIXME: (wishlist) It is bad manner ;-(
                                        HandleError ("Attribute value is invalid against its data type " + dt.TokenizedType, ex);
                                }
-                               if (attr.ValidatedFixedValue != null && attr.ValidatedFixedValue != normalized) {
+
+                               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, reader.NameTable, NamespaceManager);
                                }
@@ -982,10 +1001,10 @@ namespace Mono.Xml.Schema
 
                private void AssessEndElementSchemaValidity ()
                {
-                       ValidateEndElementParticle ();  // validate against childrens' state.
-
                        ValidateEndSimpleContent ();
 
+                       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().
@@ -1469,7 +1488,7 @@ namespace Mono.Xml.Schema
 
                private void ExamineAdditionalSchema ()
                {
-                       if (resolver == null)
+                       if (resolver == null || ValidationType == ValidationType.None)
                                return;
                        XmlSchema schema = null;
                        string schemaLocation = reader.GetAttribute ("schemaLocation", XmlSchema.InstanceNamespace);
@@ -1589,7 +1608,7 @@ namespace Mono.Xml.Schema
 
                                if (reader.IsEmptyElement)
                                        goto case XmlNodeType.EndElement;
-                               else
+                               else if (xsiNilDepth < reader.Depth)
                                        shouldValidateCharacters = true;
                                break;
                        case XmlNodeType.EndElement:
@@ -1606,14 +1625,18 @@ namespace Mono.Xml.Schema
                        case XmlNodeType.SignificantWhitespace:
                        case XmlNodeType.Whitespace:
                        case XmlNodeType.Text:
-                               // FIXME: does this check make sense?
+                               if (skipValidationDepth >= 0 && reader.Depth > skipValidationDepth)
+                                       break;
+
                                ComplexType ct = Context.ActualType as ComplexType;
-                               if (ct != null && storedCharacters.Length > 0) {
+                               if (ct != null) {
                                        switch (ct.ContentType) {
                                        case XmlSchemaContentType.ElementOnly:
-                                       case XmlSchemaContentType.Empty:
                                                if (reader.NodeType != XmlNodeType.Whitespace)
-                                                       HandleError ("Not allowed character content was found.");
+                                                       HandleError (String.Format ("Not allowed character content is found (current content model '{0}' is element-only).", ct.QualifiedName));
+                                               break;
+                                       case XmlSchemaContentType.Empty:
+                                               HandleError (String.Format ("Not allowed character content is found (current element content model '{0}' is empty).", ct.QualifiedName));
                                                break;
                                        }
                                }
@@ -1674,14 +1697,32 @@ namespace Mono.Xml.Schema
                {
                }
 
-               // Some of them might be missing (See the spec section 5.3, and also 3.3.4).
-               public XsElement Element;
-               public object XsiType; // xsi:type
+               object xsi_type;
+               public object XsiType { get { return xsi_type; } set { xsi_type = value; } } // xsi:type
                internal XsdValidationState State;
+               Stack element_stack = new Stack ();
+
+               // Some of them might be missing (See the spec section 5.3, and also 3.3.4).
+               public XsElement Element {
+                       get { return element_stack.Count > 0 ? element_stack.Peek () as XsElement : null; }
+               }
+
+               public void PushCurrentElement (XsElement element)
+               {
+                       element_stack.Push (element);
+               }
+
+               public void PopCurrentElement ()
+               {
+                       element_stack.Pop ();
+               }
 
                // Note that it represents current element's type.
                public object ActualType {
                        get {
+                               // FIXME: actually this should also be stacked
+                               if (element_stack.Count == 0)
+                                       return null;
                                if (XsiType != null)
                                        return XsiType;
                                else
@@ -1723,11 +1764,6 @@ namespace Mono.Xml.Schema
                {
                        return State.EvaluateEndElement ();
                }
-
-               public void SetElement (XsElement element)
-               {
-                       Element = element;
-               }
        }
 
        internal class XsdIDManager
@@ -1773,14 +1809,14 @@ namespace Mono.Xml.Schema
                                        MissingIDReferences.Remove (str);
                                break;
                        case XmlTokenizedType.IDREF:
-                               if (!idList.Contains (str))
+                               if (!idList.Contains (str) && !MissingIDReferences.Contains (str))
                                        MissingIDReferences.Add (str);
                                break;
                        case XmlTokenizedType.IDREFS:
                                string [] idrefs = (string []) parsedValue;
                                for (int i = 0; i < idrefs.Length; i++) {
                                        string id = idrefs [i];
-                                       if (!idList.Contains (id))
+                                       if (!idList.Contains (id) && !MissingIDReferences.Contains (str))
                                                MissingIDReferences.Add (id);
                                }
                                break;