//
// (C)2003 Atsushi Enomoto
//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
using System;
using System.Collections;
using System.Xml;
namespace Mono.Xml.Schema
{
- public enum XsdParticleEvaluationResult
- {
- Matched = 1, // Matched one of its components.
- Passed = 2, // Did not match, but it successfully passed the whole components.
- InvalidIncomplete = 3, // It had incomplete validation state, and in fact it failed to pass.
- Mismatched = 4 // Dis not match,
- }
-
- public class XsdValidationStateManager
+ internal class XsdParticleStateManager
{
Hashtable table;
- XmlSchemaElement currentElement;
XmlSchemaContentProcessing processContents;
- public XsdValidationStateManager ()
+ public XsdParticleStateManager ()
{
table = new Hashtable ();
- processContents = XmlSchemaContentProcessing.Strict;
+ processContents = XmlSchemaContentProcessing.Strict; // not Lax
}
- public XmlSchemaElement CurrentElement {
- get { return currentElement; }
- set { currentElement = value; }
+ public XmlSchemaElement CurrentElement;
+
+ public Stack ContextStack = new Stack ();
+
+ public XsdValidationContext Context
+ = new XsdValidationContext ();
+
+ public XmlSchemaContentProcessing ProcessContents {
+ get { return processContents; }
}
- internal void SetCurrentElement (XmlSchemaElement elt)
+ public void PushContext ()
{
- this.currentElement = elt;
+ ContextStack.Push (Context.Clone ());
}
- public XmlSchemaContentProcessing ProcessContents {
- get { return processContents; }
+ public void PopContext ()
+ {
+ Context = (XsdValidationContext) ContextStack.Pop ();
}
internal void SetProcessContents (XmlSchemaContentProcessing value)
switch (typeName) {
case "XmlSchemaElement":
return AddElement ((XmlSchemaElement) xsobj);
- case "XmlSchemaGroupRef":
- return AddGroup ((XmlSchemaGroupRef) xsobj);
case "XmlSchemaSequence":
return AddSequence ((XmlSchemaSequence) xsobj);
case "XmlSchemaChoice":
return AddAll ((XmlSchemaAll) xsobj);
case "XmlSchemaAny":
return AddAny ((XmlSchemaAny) xsobj);
- case "EmptyParticle": // Microsoft.NET
- case "XmlSchemaParticleEmpty": // Mono
+ case "EmptyParticle":
return AddEmpty ();
default:
- throw new NotImplementedException ();
+ // GroupRef should not appear
+ throw new InvalidOperationException ("Should not occur.");
}
}
private XsdElementValidationState AddElement (XmlSchemaElement element)
{
XsdElementValidationState got = new XsdElementValidationState (element, this);
-// table [element] = got;
- return got;
- }
-
- private XsdGroupValidationState AddGroup (XmlSchemaGroupRef groupRef)
- {
- XsdGroupValidationState got = new XsdGroupValidationState (groupRef, this);
-// table [groupRef] = got;
return got;
}
private XsdSequenceValidationState AddSequence (XmlSchemaSequence sequence)
{
XsdSequenceValidationState got = new XsdSequenceValidationState (sequence, this);
-// table [sequence] = got;
return got;
}
private XsdChoiceValidationState AddChoice (XmlSchemaChoice choice)
{
XsdChoiceValidationState got = new XsdChoiceValidationState (choice, this);
-// table [choice] = got;
return got;
}
private XsdAllValidationState AddAll (XmlSchemaAll all)
{
XsdAllValidationState got = new XsdAllValidationState (all, this);
-// table [all] = got;
return got;
}
private XsdAnyValidationState AddAny (XmlSchemaAny any)
{
XsdAnyValidationState got = new XsdAnyValidationState (any, this);
-// table [any] = got;
return got;
}
}
}
- public abstract class XsdValidationState
+ internal abstract class XsdValidationState
{
// Static members
// Dynamic members
int occured;
- string message;
- XsdValidationStateManager manager;
+ readonly XsdParticleStateManager manager;
- public XsdValidationState (XsdValidationStateManager manager)
+ public XsdValidationState (XsdParticleStateManager manager)
{
this.manager = manager;
}
- // Normally checks MaxOccurs boundary
+ // Normally checks Max Occurs boundary
public abstract XsdValidationState EvaluateStartElement (string localName, string ns);
- // Normally checks MinOccurs boundary
+ // Normally checks Min Occurs boundary
public abstract bool EvaluateEndElement ();
internal abstract bool EvaluateIsEmptiable ();
- public XsdValidationStateManager Manager {
- get { return manager; }
- }
-
- public string Message {
- get { return message; }
- }
+ public abstract void GetExpectedParticles (ArrayList al);
- public string MessageInternal {
- get { return message; }
- set { message = value; }
+ public XsdParticleStateManager Manager {
+ get { return manager; }
}
public int Occured {
}
}
- public class XsdElementValidationState : XsdValidationState
+ internal class XsdElementValidationState : XsdValidationState
{
- public XsdElementValidationState (XmlSchemaElement element, XsdValidationStateManager manager)
+ public XsdElementValidationState (XmlSchemaElement element, XsdParticleStateManager manager)
: base (manager)
{
this.element = element;
- name = element.QualifiedName.Name;
- ns = element.QualifiedName.Namespace;
}
// final fields
- XmlSchemaElement element;
- string name;
- string ns;
+ readonly XmlSchemaElement element;
+
+ string Name {
+ get { return element.QualifiedName.Name; }
+ }
+
+ string NS {
+ get { return element.QualifiedName.Namespace; }
+ }
// Methods
-
+ public override void GetExpectedParticles (ArrayList al)
+ {
+ XmlSchemaElement copy = (XmlSchemaElement) MemberwiseClone ();
+ decimal mo = element.ValidatedMinOccurs - Occured;
+ copy.MinOccurs = mo > 0 ? mo : 0;
+ if (element.ValidatedMaxOccurs == decimal.MaxValue)
+ copy.MaxOccursString = "unbounded";
+ else
+ copy.MaxOccurs = element.ValidatedMaxOccurs - Occured;
+ al.Add (copy);
+ }
+
public override XsdValidationState EvaluateStartElement (string name, string ns)
{
- if (this.name == name && this.ns == ns && !element.IsAbstract) {
+ if (this.Name == name && this.NS == ns && !element.IsAbstract) {
return this.CheckOccurence (element);
} else {
- foreach (XmlSchemaElement subst in element.SubstitutingElements) {
+ for (int i = 0; i < element.SubstitutingElements.Count; i++) {
+ XmlSchemaElement subst = (XmlSchemaElement) element.SubstitutingElements [i];
if (subst.QualifiedName.Name == name &&
subst.QualifiedName.Namespace == ns) {
return this.CheckOccurence (subst);
private XsdValidationState CheckOccurence (XmlSchemaElement maybeSubstituted)
{
OccuredInternal++;
- Manager.SetCurrentElement (maybeSubstituted);
+ Manager.CurrentElement = maybeSubstituted;
if (Occured > element.ValidatedMaxOccurs) {
- MessageInternal = "Element occurence excess.";
return XsdValidationState.Invalid;
} else if (Occured == element.ValidatedMaxOccurs) {
return Manager.Create (XmlSchemaParticle.Empty);
}
}
- public class XsdGroupValidationState : XsdValidationState
+ internal class XsdSequenceValidationState : XsdValidationState
{
- public XsdGroupValidationState (XmlSchemaGroupRef groupRef, XsdValidationStateManager manager)
- : base (manager)
- {
- this.groupRef = groupRef;
- }
-
- XmlSchemaGroupRef groupRef;
-
- // Methods
-
- public override XsdValidationState EvaluateStartElement (string name, string ns)
- {
- XsdValidationState xa = Manager.Create (groupRef.Particle);
- XsdValidationState result = xa.EvaluateStartElement (name, ns);
- if (result == XsdValidationState.Invalid)
- return result;
-
- OccuredInternal++;
- if (OccuredInternal > groupRef.MaxOccurs)
- return XsdValidationState.Invalid;
- return Manager.MakeSequence (result, this);
- }
-
- public override bool EvaluateEndElement ()
- {
- if (groupRef.ValidatedMinOccurs > Occured + 1)
- return false;
- else if (groupRef.ValidatedMinOccurs <= Occured)
- return true;
- return Manager.Create (groupRef.Particle).EvaluateIsEmptiable ();
- }
-
- internal override bool EvaluateIsEmptiable ()\r
- {\r
- return (groupRef.ValidatedMinOccurs <= Occured);\r
- }\r
- }
-
- public class XsdSequenceValidationState : XsdValidationState
- {
- XmlSchemaSequence seq;
+ readonly XmlSchemaSequence seq;
int current;
XsdValidationState currentAutomata;
bool emptiable;
- decimal minOccurs;
- decimal maxOccurs;
- public XsdSequenceValidationState (XmlSchemaSequence sequence, XsdValidationStateManager manager)
- : this (sequence, manager, sequence.ValidatedMinOccurs, sequence.ValidatedMaxOccurs, -1)
+ public XsdSequenceValidationState (XmlSchemaSequence sequence, XsdParticleStateManager manager)
+ : base (manager)
{
+ seq = sequence;
+ this.current = -1;
}
- public XsdSequenceValidationState (XmlSchemaSequence sequence, XsdValidationStateManager manager,
- decimal minOccurs, decimal maxOccurs, int current)
- : base (manager)
+ public override void GetExpectedParticles (ArrayList al)
{
- seq = sequence;
- this.minOccurs = minOccurs;
- this.maxOccurs = maxOccurs;
- this.current = current;
+ // if not started, then just collect all items from seq.
+ if (currentAutomata == null) {
+ foreach (XmlSchemaParticle p in seq.CompiledItems) {
+ al.Add (p);
+ if (!p.ValidateIsEmptiable ())
+ break;
+ }
+ return;
+ }
+
+ // automata for ongoing iteration
+ if (currentAutomata != null) {
+ currentAutomata.GetExpectedParticles (al);
+ if (!currentAutomata.EvaluateIsEmptiable ())
+ return;
+
+ // remaining items after currentAutomata
+ for (int i = current + 1; i < seq.CompiledItems.Count; i++) {
+ XmlSchemaParticle p = seq.CompiledItems [i] as XmlSchemaParticle;
+ al.Add (p);
+ if (!p.ValidateIsEmptiable ())
+ break;
+ }
+ }
+
+ // itself
+ if (Occured + 1 == seq.ValidatedMaxOccurs)
+ return;
+
+ {
+ for (int i = 0; i <= current; i++)
+ al.Add (seq.CompiledItems [i]);
+ }
}
public override XsdValidationState EvaluateStartElement (string name, string ns)
}
if (xa is XsdEmptyValidationState &&
seq.CompiledItems.Count == idx + 1 &&
- Occured == maxOccurs) {
+ Occured == seq.ValidatedMaxOccurs) {
return XsdValidationState.Invalid;
} else {
XsdValidationState result = xa.EvaluateStartElement (name, ns);
currentAutomata = result;
if (increment) {
OccuredInternal++;
- if (Occured > maxOccurs)
+ if (Occured > seq.ValidatedMaxOccurs)
return XsdValidationState.Invalid;
}
// current++;
xa = null;
}
}
- return XsdValidationState.Invalid;
}
public override bool EvaluateEndElement ()
{
- if (minOccurs > Occured + 1)
+ if (seq.ValidatedMinOccurs > Occured + 1)
return false;
if (seq.CompiledItems.Count == 0)
return true;
- if (currentAutomata == null && minOccurs <= Occured)
+ if (currentAutomata == null && seq.ValidatedMinOccurs <= Occured)
return true;
int idx = current < 0 ? 0 : current;
if (current < 0)
OccuredInternal++;
- return minOccurs <= Occured && maxOccurs >= Occured;
+ return seq.ValidatedMinOccurs <= Occured && seq.ValidatedMaxOccurs >= Occured;
}
internal override bool EvaluateIsEmptiable ()\r
{\r
- if (minOccurs > Occured + 1)\r
+ if (seq.ValidatedMinOccurs > Occured + 1)\r
return false;\r
- if (minOccurs == 0 && currentAutomata == null)\r
+ if (seq.ValidatedMinOccurs == 0 && currentAutomata == null)\r
return true;\r
\r
if (emptiable)\r
}
- public class XsdChoiceValidationState : XsdValidationState
+ internal class XsdChoiceValidationState : XsdValidationState
{
- XmlSchemaChoice choice;
+ readonly XmlSchemaChoice choice;
bool emptiable;
bool emptiableComputed;
- public XsdChoiceValidationState (XmlSchemaChoice choice, XsdValidationStateManager manager)
+ public XsdChoiceValidationState (XmlSchemaChoice choice, XsdParticleStateManager manager)
: base (manager)
{
this.choice = choice;
}
+ public override void GetExpectedParticles (ArrayList al)
+ {
+ if (Occured < choice.ValidatedMaxOccurs)
+ foreach (XmlSchemaParticle p in choice.CompiledItems)
+ al.Add (p);
+ }
+
public override XsdValidationState EvaluateStartElement (string localName, string ns)
{
emptiableComputed = false;
- foreach (XmlSchemaParticle xsobj in choice.CompiledItems) {
+ for (int i = 0; i < choice.CompiledItems.Count; i++) {
+ XmlSchemaParticle xsobj = (XmlSchemaParticle) choice.CompiledItems [i];
XsdValidationState xa = Manager.Create (xsobj);
XsdValidationState result = xa.EvaluateStartElement (localName, ns);
if (result != XsdValidationState.Invalid) {
else if (choice.ValidatedMinOccurs <= Occured)
return true;
- foreach (XmlSchemaParticle p in choice.CompiledItems)
+ for (int i = 0; i < choice.CompiledItems.Count; i++) {
+ XmlSchemaParticle p = (XmlSchemaParticle) choice.CompiledItems [i];
if (Manager.Create (p).EvaluateIsEmptiable ())
return true;
+ }
return false;
}
\r
for (int i = Occured; i < choice.ValidatedMinOccurs; i++) {\r
bool next = false;\r
- foreach (XmlSchemaParticle p in choice.CompiledItems) {\r
+ for (int pi = 0; pi < choice.CompiledItems.Count; pi++) {
+ XmlSchemaParticle p = (XmlSchemaParticle) choice.CompiledItems [pi];\r
if (Manager.Create (p).EvaluateIsEmptiable ()) {
next = true;
break;
}\r
}
- public class XsdAllValidationState : XsdValidationState
+ internal class XsdAllValidationState : XsdValidationState
{
- XmlSchemaAll all;
+ readonly XmlSchemaAll all;
ArrayList consumed = new ArrayList ();
- public XsdAllValidationState (XmlSchemaAll all, XsdValidationStateManager manager)
+ public XsdAllValidationState (XmlSchemaAll all, XsdParticleStateManager manager)
: base (manager)
{
this.all = all;
}
+ public override void GetExpectedParticles (ArrayList al)
+ {
+ foreach (XmlSchemaParticle p in all.CompiledItems)
+ if (!consumed.Contains (p))
+ al.Add (p);
+ }
+
public override XsdValidationState EvaluateStartElement (string localName, string ns)
{
if (all.CompiledItems.Count == 0)
// We don't have to keep element validation state, since
// it must occur only 0 or 1.
- foreach (XmlSchemaElement xsElem in all.CompiledItems) {
+ for (int i = 0; i < all.CompiledItems.Count; i++) {
+ XmlSchemaElement xsElem = (XmlSchemaElement) all.CompiledItems [i];
if (xsElem.QualifiedName.Name == localName &&
xsElem.QualifiedName.Namespace == ns) {
if (consumed.Contains (xsElem))
return XsdValidationState.Invalid;
consumed.Add (xsElem);
- Manager.SetCurrentElement (xsElem);
+ Manager.CurrentElement = xsElem;
OccuredInternal = 1; // xs:all also occurs 0 or 1 always.
return this;
}
return false;
if (all.CompiledItems.Count == consumed.Count)
return true;
- foreach (XmlSchemaElement el in all.CompiledItems)
- if (el.MinOccurs > 0 && !consumed.Contains (el))
+ for (int i = 0; i < all.CompiledItems.Count; i++) {
+ XmlSchemaElement el = (XmlSchemaElement) all.CompiledItems [i];
+ if (el.ValidatedMinOccurs > 0 && !consumed.Contains (el))
return false;
+ }
return true;
}
{\r
if (all.Emptiable || all.ValidatedMinOccurs == 0)
return true;
- foreach (XmlSchemaElement el in all.CompiledItems)
- if (el.MinOccurs > 0 && !consumed.Contains (el))
+ for (int i = 0; i < all.CompiledItems.Count; i++) {
+ XmlSchemaElement el = (XmlSchemaElement) all.CompiledItems [i];
+ if (el.ValidatedMinOccurs > 0 && !consumed.Contains (el))
return false;
+ }
return true;
}\r
}
- public class XsdAnyValidationState : XsdValidationState
+ internal class XsdAnyValidationState : XsdValidationState
{
- XmlSchemaAny any;
+ readonly XmlSchemaAny any;
- public XsdAnyValidationState (XmlSchemaAny any, XsdValidationStateManager manager)
+ public XsdAnyValidationState (XmlSchemaAny any, XsdParticleStateManager manager)
: base (manager)
{
this.any = any;
}
// Methods
+ public override void GetExpectedParticles (ArrayList al)
+ {
+ al.Add (any);
+ }
+
public override XsdValidationState EvaluateStartElement (string name, string ns)
{
if (!MatchesNamespace (ns))
return XsdValidationState.Invalid;
OccuredInternal++;
- Manager.SetProcessContents (any.ProcessContents);
+ Manager.SetProcessContents (any.ResolvedProcessContents);
if (Occured > any.ValidatedMaxOccurs)
return XsdValidationState.Invalid;
else if (Occured == any.ValidatedMaxOccurs)
return true;
if (any.HasValueTargetNamespace && any.TargetNamespace == ns)
return true;
- foreach (string iter in any.ResolvedNamespaces)
- if (iter == ns)
+ for (int i = 0; i < any.ResolvedNamespaces.Count; i++)
+ if (any.ResolvedNamespaces [i] == ns)
return true;
return false;
}
}\r
}
- public class XsdAppendedValidationState : XsdValidationState
+ internal class XsdAppendedValidationState : XsdValidationState
{
- public XsdAppendedValidationState (XsdValidationStateManager manager,
+ public XsdAppendedValidationState (XsdParticleStateManager manager,
XsdValidationState head, XsdValidationState rest)
: base (manager)
{
XsdValidationState rest;
// Methods
+ public override void GetExpectedParticles (ArrayList al)
+ {
+ head.GetExpectedParticles (al);
+ rest.GetExpectedParticles (al);
+ }
+
public override XsdValidationState EvaluateStartElement (string name, string ns)
{
XsdValidationState afterHead = head.EvaluateStartElement (name, ns);
}\r
}
- public class XsdEmptyValidationState : XsdValidationState
+ internal class XsdEmptyValidationState : XsdValidationState
{
- public XsdEmptyValidationState (XsdValidationStateManager manager)
+ public XsdEmptyValidationState (XsdParticleStateManager manager)
: base (manager)
{
}
// Methods
+
+ public override void GetExpectedParticles (ArrayList al)
+ {
+ // do nothing
+ }
+
public override XsdValidationState EvaluateStartElement (string name, string ns)
{
return XsdValidationState.Invalid;
\r
}
- public class XsdInvalidValidationState : XsdValidationState
+ internal class XsdInvalidValidationState : XsdValidationState
{
- internal XsdInvalidValidationState (XsdValidationStateManager manager)
+ internal XsdInvalidValidationState (XsdParticleStateManager manager)
: base (manager)
{
}
// Methods
+
+ public override void GetExpectedParticles (ArrayList al)
+ {
+ // do nothing
+ }
+
public override XsdValidationState EvaluateStartElement (string name, string ns)
{
return this;