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
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[].
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);
+ 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 ()
}
// 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);
string attributeValue,
XmlSchemaInfo info)
{
- return ValidateAttribute (localName, ns,
- delegate () { return info.SchemaType.Datatype.ParseValue (attributeValue, nameTable, nsResolver); },
- 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,
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);
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;
}
string schemaLocation,
string noNsSchemaLocation)
{
+ if (localName == null)
+ throw new ArgumentNullException ("localName");
+ if (ns == null)
+ throw new ArgumentNullException ("ns");
+
CheckState (Transition.Content);
transition = Transition.StartTag;
// represented by current simple content type. (try passing
// some kind of object to this method to check the behavior.)
// EndTagDeriv
- [MonoTODO ("Handle 'var' parameter.")]
+ [MonoTODO] // FIXME: Handle 'var' parameter.
public object ValidateEndElement (XmlSchemaInfo info,
object var)
{
if (schemas.Count == 0)
return;
- AssessCloseStartElementSchemaValidity (info);
+ if (skipValidationDepth < 0 || depth <= skipValidationDepth)
+ AssessCloseStartElementSchemaValidity (info);
+ depth++;
} finally {
occuredAtts.Clear ();
}
// or content type validation errors.
public void ValidateText (string value)
{
+ if (value == null)
+ throw new ArgumentNullException ("value");
ValidateText (delegate () { return value; });
}
// 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;
}
}
public void ValidateWhitespace (string value)
{
+ if (value == null)
+ throw new ArgumentNullException ("value");
ValidateWhitespace (delegate () { return value; });
}
- // TextDeriv...?
- [MonoTODO]
+ // TextDeriv. It should do the same as ValidateText() in our actual implementation (whitespaces are conditioned).
public void ValidateWhitespace (XmlValueGetter getter)
{
- CheckState (Transition.Content);
- if (schemas.Count == 0)
- return;
-
-// throw new NotImplementedException ();
+ ValidateText (getter);
}
#endregion
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));
}
if (Context.IsInvalid)
HandleError ("Invalid start element: " + ns + ":" + localName);
- Context.SetElement (state.CurrentElement);
+ Context.PushCurrentElement (state.CurrentElement);
}
private void AssessOpenStartElementSchemaValidity (
// [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
next = state.Create (XmlSchemaParticle.Empty);
}
Context.State = next;
-
- depth++;
}
// It must be invoked after xsi:nil turned out not to be in
if (dt != SimpleType.AnySimpleType || attr.ValidatedFixedValue != null) {
object parsedValue = null;
try {
+ CurrentAttributeType = dt;
parsedValue = getter ();
} catch (Exception ex) { // It is inevitable and bad manner.
- HandleError ("Attribute value is invalid against its data type " + dt.TokenizedType, ex);
+ HandleError (String.Format ("Attribute value is invalid against its data type {0}", dt != null ? dt.TokenizedType : default (XmlTokenizedType)), ex);
}
- XmlSchemaType type = info != null ? info.SchemaType : null;
+
+ // 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.IsSchemaDatatypeEquals (
- attr.AttributeSchemaType.Datatype as XsdAnySimpleType, attr.ValidatedFixedTypedValue, type != null ? type.Datatype as XsdAnySimpleType : null, parsedValue)) {
- HandleError ("The value of the attribute " + attr.QualifiedName + " does not match with its fixed value.");
+ !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
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 ().
HandleError ("Invalid end element. There are still required content items.");
}
}
+ Context.PopCurrentElement ();
state.PopContext ();
}
if (xsiNilDepth >= 0 && xsiNilDepth < depth)
HandleError ("Element item appeared, while current element context is nil.");
- if (shouldValidateCharacters)
+ if (shouldValidateCharacters) {
+ CurrentAttributeType = null;
storedCharacters.Append (getter ());
+ }
}
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;
}
}
if (baseType != null) {
ret = AssessStringValid (baseType, dt, value);
}
- if (!str.ValidateValueWithFacets (value, nameTable)) {
+ if (!str.ValidateValueWithFacets (value, nameTable, nsResolver)) {
HandleError ("Specified value was invalid against the facets.");
break;
}
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
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,
}
}
- private void ProcessKeyEntryOne (XsdKeyEntry entry, bool isAttr, bool isNil, object schemaType, string attrName, string attrNs, XmlValueGetter getter)
- {
- }
-
private void ValidateEndElementKeyConstraints ()
{
// Reset Identity constraints.