Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAtsushi Eno <atsushieno@gmail.com>2003-07-06 20:17:31 +0400
committerAtsushi Eno <atsushieno@gmail.com>2003-07-06 20:17:31 +0400
commitd6b7b632e3fa96bd4b2d773dda6103af7de9b763 (patch)
tree0ea09b5e3e03bd58376df26d6bfac0e36bc04d57
parent3f7e68b2751de7db455425dfcffb49bab4ece088 (diff)
2003-07-06 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
* XmlDocument.cs : Load(string filename) should close its stream. Small change for the latest DTDObjectModel change. * XmlTextReader.cs : Changed for the latest DTDObjectModel change (all changed methods are only related to DTD stuff). Now uses XmlSchemaDatatype for attribute type definition. * XmlValidatingReader : initial (limited) support for DTD validation. It can handle only XmlTextReader. * DTDObjectModel.cs : changed radically for initial validation support. * added DTDAutomata.cs and DTDValidatingReader.cs. svn path=/trunk/mcs/; revision=15983
-rw-r--r--mcs/class/System.XML/System.Xml/ChangeLog12
-rw-r--r--mcs/class/System.XML/System.Xml/DTDAutomata.cs322
-rw-r--r--mcs/class/System.XML/System.Xml/DTDObjectModel.cs438
-rw-r--r--mcs/class/System.XML/System.Xml/DTDValidatingReader.cs527
-rw-r--r--mcs/class/System.XML/System.Xml/XmlDocument.cs10
-rw-r--r--mcs/class/System.XML/System.Xml/XmlTextReader.cs72
-rw-r--r--mcs/class/System.XML/System.Xml/XmlValidatingReader.cs172
7 files changed, 1401 insertions, 152 deletions
diff --git a/mcs/class/System.XML/System.Xml/ChangeLog b/mcs/class/System.XML/System.Xml/ChangeLog
index 4f85c77b5df..7f7226eeb67 100644
--- a/mcs/class/System.XML/System.Xml/ChangeLog
+++ b/mcs/class/System.XML/System.Xml/ChangeLog
@@ -1,5 +1,17 @@
2003-07-06 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
+ * XmlDocument.cs : Load(string filename) should close its stream.
+ Small change for the latest DTDObjectModel change.
+ * XmlTextReader.cs : Changed for the latest DTDObjectModel change (all
+ changed methods are only related to DTD stuff).
+ Now uses XmlSchemaDatatype for attribute type definition.
+ * XmlValidatingReader : initial (limited) support for DTD validation.
+ It can handle only XmlTextReader.
+ * DTDObjectModel.cs : changed radically for initial validation support.
+ * added DTDAutomata.cs and DTDValidatingReader.cs.
+
+2003-07-06 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
+
* XmlElement.cs : Removed extraneous xmlns output support (it should
be done by XmlTextWriter).
* XmlNode.cs : InsertBefore() now checks validity of the newChild (and
diff --git a/mcs/class/System.XML/System.Xml/DTDAutomata.cs b/mcs/class/System.XML/System.Xml/DTDAutomata.cs
new file mode 100644
index 00000000000..2b5dd6a9c73
--- /dev/null
+++ b/mcs/class/System.XML/System.Xml/DTDAutomata.cs
@@ -0,0 +1,322 @@
+//
+// Mono.Xml.DTDAutomata
+//
+// Author:
+// Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
+//
+// (C)2003 Atsushi Enomoto
+//
+using System;
+using System.Collections;
+using System.Text;
+using System.Xml;
+using System.Xml.Schema;
+using Mono.Xml.Schema;
+
+namespace Mono.Xml
+{
+ public class DTDAutomataFactory
+ {
+ public DTDAutomataFactory (DTDObjectModel root)
+ {
+ this.root = root;
+ }
+
+ DTDObjectModel root;
+ Hashtable choiceTable = new Hashtable ();
+ Hashtable sequenceTable = new Hashtable ();
+
+ public DTDChoiceAutomata Choice (DTDAutomata left, DTDAutomata right)
+ {
+ Hashtable rightPool = choiceTable [left] as Hashtable;
+ if (rightPool == null) {
+ rightPool = new Hashtable ();
+ choiceTable [left] = rightPool;
+ }
+ DTDChoiceAutomata result = rightPool [right] as DTDChoiceAutomata;
+ if (result == null) {
+ result = new DTDChoiceAutomata (root, left, right);
+ rightPool [right] = result;
+ }
+ return result;
+ }
+
+ public DTDSequenceAutomata Sequence (DTDAutomata left, DTDAutomata right)
+ {
+ Hashtable rightPool = sequenceTable [left] as Hashtable;
+ if (rightPool == null) {
+ rightPool = new Hashtable ();
+ sequenceTable [left] = rightPool;
+ }
+ DTDSequenceAutomata result = rightPool [right] as DTDSequenceAutomata;
+ if (result == null) {
+ result = new DTDSequenceAutomata (root, left, right);
+ rightPool [right] = result;
+ }
+ return result;
+ }
+ }
+
+ public abstract class DTDAutomata
+ {
+ public DTDAutomata (DTDObjectModel root)
+ {
+ this.root = root;
+ }
+
+ private DTDObjectModel root;
+
+ public DTDObjectModel Root {
+ get { return root; }
+ }
+
+ public DTDAutomata MakeChoice (DTDAutomata other)
+ {
+ if (this == Root.Invalid)
+ return other;
+ if (other == Root.Invalid)
+ return this;
+ if (this == Root.Empty && other == Root.Empty)
+ return this;
+ if (this == Root.Any && other == Root.Any)
+ return this;
+ else if (other == Root.Empty)
+ return Root.Factory.Choice (other, this);
+ else
+ return Root.Factory.Choice (this, other);
+ }
+
+ public DTDAutomata MakeSequence (DTDAutomata other)
+ {
+ if (this == Root.Invalid || other == Root.Invalid)
+ return Root.Invalid;
+ if (this == Root.Empty)
+ return other;
+ if (other == Root.Empty)
+ return this;
+ else
+ return Root.Factory.Sequence (this, other);
+ }
+
+ public abstract DTDAutomata TryStartElement (string name);
+ public virtual DTDAutomata TryEndElement ()
+ {
+ return Root.Invalid;
+ }
+
+ public virtual bool Emptiable {
+ get { return false; }
+ }
+ }
+
+ public class DTDElementAutomata : DTDAutomata
+ {
+ public DTDElementAutomata (DTDObjectModel root, string name)
+ : base (root)
+ {
+ this.name = name;
+ }
+
+ private string name;
+
+ public string Name {
+ get { return name; }
+ }
+
+ public override DTDAutomata TryStartElement (string name)
+ {
+ if (name == Name)
+ return Root.Empty;
+ else
+ return Root.Invalid;
+ }
+ }
+
+ public class DTDChoiceAutomata : DTDAutomata
+ {
+ public DTDChoiceAutomata (DTDObjectModel root,
+ DTDAutomata left, DTDAutomata right)
+ : base (root)
+ {
+ this.left = left;
+ this.right = right;
+ }
+
+ private DTDAutomata left;
+ private DTDAutomata right;
+
+ public DTDAutomata Left {
+ get { return left; }
+ }
+
+ public DTDAutomata Right {
+ get { return right; }
+ }
+
+ public override DTDAutomata TryStartElement (string name)
+ {
+ return left.TryStartElement (name).MakeChoice (
+ right.TryStartElement (name));
+ }
+
+ public override DTDAutomata TryEndElement ()
+ {
+ if (left == Root.Empty)
+ return right;
+ if (right == Root.Empty)
+ return left;
+ else
+ return Root.Invalid;
+ }
+
+ bool hasComputedEmptiable;
+ bool cachedEmptiable;
+ public override bool Emptiable {
+ get {
+ if (!hasComputedEmptiable) {
+ cachedEmptiable = left.Emptiable ||
+ right.Emptiable;
+ hasComputedEmptiable = true;
+ }
+ return cachedEmptiable;
+ }
+ }
+ }
+
+ public class DTDSequenceAutomata : DTDAutomata
+ {
+ public DTDSequenceAutomata (DTDObjectModel root,
+ DTDAutomata left, DTDAutomata right)
+ : base (root)
+ {
+ this.left = left;
+ this.right = right;
+ }
+
+ private DTDAutomata left;
+ private DTDAutomata right;
+
+ public DTDAutomata Left {
+ get { return left; }
+ }
+
+ public DTDAutomata Right {
+ get { return right; }
+ }
+
+ public override DTDAutomata TryStartElement (string name)
+ {
+ DTDAutomata afterL = left.TryStartElement (name);
+ DTDAutomata afterR = right.TryStartElement (name);
+ if (afterL == Root.Invalid)
+ return (afterL.Emptiable) ? afterR : afterL;
+ // else
+ DTDAutomata whenLeftConsumed = afterL.MakeSequence (right);
+ if (left.Emptiable)
+ return afterR.MakeChoice (whenLeftConsumed);
+ else
+ return whenLeftConsumed;
+ }
+
+ bool hasComputedEmptiable;
+ bool cachedEmptiable;
+ public override bool Emptiable {
+ get {
+ if (!hasComputedEmptiable) {
+ cachedEmptiable = left.Emptiable &&
+ right.Emptiable;
+ hasComputedEmptiable = true;
+ }
+ return cachedEmptiable;
+ }
+ }
+ }
+
+ public class DTDOneOrMoreAutomata : DTDAutomata
+ {
+ public DTDOneOrMoreAutomata (DTDObjectModel root,
+ DTDAutomata children)
+ : base (root)
+ {
+ this.children = children;
+ }
+
+ private DTDAutomata children;
+
+ public DTDAutomata Children {
+ get { return children; }
+ }
+
+ public override DTDAutomata TryStartElement (string name)
+ {
+ DTDAutomata afterC = children.TryStartElement (name);
+ if (afterC != Root.Invalid)
+ return afterC.MakeSequence (
+ Root.Empty.MakeChoice (this));
+ else
+ return Root.Invalid;
+ }
+ }
+
+ public class DTDEmptyAutomata : DTDAutomata
+ {
+ public DTDEmptyAutomata (DTDObjectModel root)
+ : base (root)
+ {
+ }
+
+ public override DTDAutomata TryEndElement ()
+ {
+ return this;
+ }
+
+ public override DTDAutomata TryStartElement (string name)
+ {
+ return Root.Invalid;
+ }
+
+ public override bool Emptiable {
+ get { return true; }
+ }
+ }
+
+ public class DTDAnyAutomata : DTDAutomata
+ {
+ public DTDAnyAutomata (DTDObjectModel root)
+ : base (root)
+ {
+ }
+
+ public override DTDAutomata TryEndElement ()
+ {
+ return this;
+ }
+
+ public override DTDAutomata TryStartElement (string name)
+ {
+ return this;
+ }
+
+ public override bool Emptiable {
+ get { return true; }
+ }
+ }
+
+ public class DTDInvalidAutomata : DTDAutomata
+ {
+ public DTDInvalidAutomata (DTDObjectModel root)
+ : base (root)
+ {
+ }
+
+ public override DTDAutomata TryEndElement ()
+ {
+ return this;
+ }
+
+ public override DTDAutomata TryStartElement (string name)
+ {
+ return this;
+ }
+ }
+} \ No newline at end of file
diff --git a/mcs/class/System.XML/System.Xml/DTDObjectModel.cs b/mcs/class/System.XML/System.Xml/DTDObjectModel.cs
index f0acbf75d45..23267400737 100644
--- a/mcs/class/System.XML/System.Xml/DTDObjectModel.cs
+++ b/mcs/class/System.XML/System.Xml/DTDObjectModel.cs
@@ -8,25 +8,25 @@
//
using System;
using System.Collections;
+using System.Text;
using System.Xml;
+using System.Xml.Schema;
+using Mono.Xml.Schema;
namespace Mono.Xml
{
-
public class DTDObjectModel
{
- public DTDObjectModel ()
- {
- }
-
- internal Hashtable ElementDecls = new Hashtable ();
- internal Hashtable AttListDecls = new Hashtable ();
+ internal DTDElementDeclarationCollection elementDecls;
+ internal DTDAttListDeclarationCollection attListDecls;
internal Hashtable EntityDecls = new Hashtable ();
internal Hashtable NotationDecls = new Hashtable ();
- public string BaseURI {
- // XmlStreamParser.BaseURI
- get { return baseURI; }
+ public DTDObjectModel ()
+ {
+ elementDecls = new DTDElementDeclarationCollection (this);
+ attListDecls = new DTDAttListDeclarationCollection (this);
+ factory = new DTDAutomataFactory (this);
}
public string Name;
@@ -37,69 +37,312 @@ namespace Mono.Xml
public string InternalSubset;
- string baseURI;
- }
+ public string ResolveEntity (string name)
+ {
+ DTDEntityDeclaration decl = EntityDecls [name]
+ as DTDEntityDeclaration;
+ return decl.EntityValue;
+ }
- public enum DTDContentOrderType
- {
- None,
- Seq,
- Or
+ private DTDAutomataFactory factory;
+ public DTDAutomataFactory Factory {
+ get { return factory; }
+ }
+
+ public DTDElementDeclaration RootElement {
+ get { return ElementDecls [Name]; }
+ }
+
+ public DTDElementDeclarationCollection ElementDecls {
+ get { return elementDecls; }
+ }
+
+ public DTDAttListDeclarationCollection AttListDecls {
+ get { return attListDecls; }
+ }
+
+ DTDElementAutomata rootAutomata;
+ public DTDAutomata RootAutomata {
+ get {
+ if (rootAutomata == null)
+ rootAutomata = new DTDElementAutomata (this, this.Name);
+ return rootAutomata;
+ }
+ }
+
+ DTDEmptyAutomata emptyAutomata;
+ public DTDEmptyAutomata Empty {
+ get {
+ if (emptyAutomata == null)
+ emptyAutomata = new DTDEmptyAutomata (this);
+ return emptyAutomata;
+ }
+ }
+
+ DTDAnyAutomata anyAutomata;
+ public DTDAnyAutomata Any {
+ get {
+ if (anyAutomata == null)
+ anyAutomata = new DTDAnyAutomata (this);
+ return anyAutomata;
+ }
+ }
+
+ DTDInvalidAutomata invalidAutomata;
+ public DTDInvalidAutomata Invalid {
+ get {
+ if (invalidAutomata == null)
+ invalidAutomata = new DTDInvalidAutomata (this);
+ return invalidAutomata;
+ }
+ }
}
- public enum DTDAttributeType
+ public class DTDElementDeclarationCollection
{
- None,
- CData,
- Id,
- IdRef,
- IdRefs,
- Entity,
- Entities,
- NmToken,
- NmTokens,
- Notation
+ Hashtable elementDecls = new Hashtable ();
+ DTDObjectModel root;
+
+ public DTDElementDeclarationCollection (DTDObjectModel root)
+ {
+ this.root = root;
+ }
+
+ public DTDElementDeclaration this [string name] {
+ get { return elementDecls [name] as DTDElementDeclaration; }
+ }
+
+ public void Add (string name, DTDElementDeclaration decl)
+ {
+ if (elementDecls [name] != null)
+ throw new InvalidOperationException (String.Format (
+ "Element declaration for {0} was already added.",
+ name));
+ decl.SetRoot (root);
+ elementDecls.Add (name, decl);
+ }
+
+ public ICollection Keys {
+ get { return elementDecls.Keys; }
+ }
+
+ public ICollection Values {
+ get { return elementDecls.Values; }
+ }
}
- public enum DTDAttributeOccurenceType
+ public class DTDAttListDeclarationCollection
{
- None,
- Required,
- Optional,
- Fixed
+ Hashtable attListDecls = new Hashtable ();
+ DTDObjectModel root;
+
+ public DTDAttListDeclarationCollection (DTDObjectModel root)
+ {
+ this.root = root;
+ }
+
+ public DTDAttListDeclaration this [string name] {
+ get { return attListDecls [name] as DTDAttListDeclaration; }
+ }
+
+ public void Add (string name, DTDAttListDeclaration decl)
+ {
+ if (attListDecls [name] != null)
+ throw new InvalidOperationException (String.Format (
+ "AttList declaration for {0} was already added.",
+ name));
+ decl.SetRoot (root);
+ attListDecls.Add (name, decl);
+ }
+
+ public ICollection Keys {
+ get { return attListDecls.Keys; }
+ }
+
+ public ICollection Values {
+ get { return attListDecls.Values; }
+ }
}
public class DTDContentModel
{
+ private DTDObjectModel root;
+ DTDAutomata compiledAutomata;
+
+ private string ownerElementName;
public string ElementName;
public DTDContentOrderType OrderType = DTDContentOrderType.None;
- public ArrayList ChildModels = new ArrayList ();
- public decimal MinOccurs = 1;
- public decimal MaxOccurs = 1;
+ public DTDContentModelCollection ChildModels
+ = new DTDContentModelCollection ();
+ public DTDOccurence Occurence = DTDOccurence.One;
+
+ internal DTDContentModel (DTDObjectModel root, string ownerElementName)
+ {
+ this.root = root;
+ this.ownerElementName = ownerElementName;
+ }
+
+ public DTDElementDeclaration ElementDecl {
+ get {
+ return root.ElementDecls [ownerElementName];
+ }
+ }
+
+ public DTDAutomata GetAutomata ()
+ {
+ if (compiledAutomata == null)
+ Compile ();
+ return compiledAutomata;
+ }
+
+ public DTDAutomata Compile ()
+ {
+ compiledAutomata = CompileInternal ();
+ return compiledAutomata;
+ }
+
+ private DTDAutomata CompileInternal ()
+ {
+ if (ElementDecl.IsAny)
+ return root.Any;
+ if (ElementDecl.IsEmpty)
+ return root.Empty;
+
+ DTDAutomata basis = GetBasicContentAutomata ();
+ switch (Occurence) {
+ case DTDOccurence.One:
+ return basis;
+ case DTDOccurence.Optional:
+ return Choice (root.Empty, basis);
+ case DTDOccurence.OneOrMore:
+ return new DTDOneOrMoreAutomata (root, basis);
+ case DTDOccurence.ZeroOrMore:
+ return Choice (root.Empty, new DTDOneOrMoreAutomata (root, basis));
+ }
+ throw new InvalidOperationException ();
+ }
+
+ private DTDAutomata GetBasicContentAutomata ()
+ {
+ if (ElementName != null)
+ return new DTDElementAutomata (root, ElementName);
+ switch (ChildModels.Count) {
+ case 0:
+ return root.Empty;
+ case 1:
+ return ChildModels [0].GetAutomata ();
+ }
+
+ DTDAutomata current = null;
+ int childCount = ChildModels.Count;
+ switch (OrderType) {
+ case DTDContentOrderType.Seq:
+ current = Sequence (
+ ChildModels [childCount - 2].GetAutomata (),
+ ChildModels [childCount - 1].GetAutomata ());
+ for (int i = childCount - 2; i > 0; i--)
+ current = Sequence (
+ ChildModels [i - 1].GetAutomata (), current);
+ return current;
+ case DTDContentOrderType.Or:
+ current = Choice (
+ ChildModels [childCount - 2].GetAutomata (),
+ ChildModels [childCount - 1].GetAutomata ());
+ for (int i = childCount - 2; i > 0; i--)
+ current = Choice (
+ ChildModels [i - 1].GetAutomata (), current);
+ return current;
+ default:
+ throw new InvalidOperationException ("Invalid pattern specification");
+ }
+ }
+
+ private DTDAutomata Sequence (DTDAutomata l, DTDAutomata r)
+ {
+ return root.Factory.Sequence (l, r);
+ }
+
+ private DTDAutomata Choice (DTDAutomata l, DTDAutomata r)
+ {
+ return l.MakeChoice (r);
+ }
+
+ }
+
+ public class DTDContentModelCollection
+ {
+ ArrayList contentModel = new ArrayList ();
+
+ public DTDContentModelCollection ()
+ {
+ }
+
+ public DTDContentModel this [int i] {
+ get { return contentModel [i] as DTDContentModel; }
+ }
+
+ public int Count {
+ get { return contentModel.Count; }
+ }
- internal DTDContentModel () {}
+ public void Add (DTDContentModel model)
+ {
+ contentModel.Add (model);
+ }
}
- public class DTDElementDeclaration : ICloneable
+ public abstract class DTDNode
+ {
+ private DTDObjectModel root;
+
+ internal void SetRoot (DTDObjectModel root)
+ {
+ this.root = root;
+ }
+
+ protected DTDObjectModel Root {
+ get { return root; }
+ }
+ }
+
+ public class DTDElementDeclaration : DTDNode // : ICloneable
{
public string Name;
public bool IsEmpty;
public bool IsAny;
public bool IsMixedContent;
- public DTDContentModel ContentModel = new DTDContentModel ();
+ public DTDContentModel contentModel;
+ DTDObjectModel root;
- internal DTDElementDeclaration () {}
-
- public object Clone ()
+ internal DTDElementDeclaration (DTDObjectModel root)
{
- return this.MemberwiseClone ();
+ this.root = root;
}
+
+ public DTDContentModel ContentModel {
+ get {
+ if (contentModel == null)
+ contentModel = new DTDContentModel (root, Name);
+ return contentModel;
+ }
+ }
+
+ public DTDAttListDeclaration Attributes {
+ get {
+ return Root.AttListDecls [Name];
+ }
+ }
+
+// public object Clone ()
+// {
+// return this.MemberwiseClone ();
+// }
}
- public class DTDAttributeDefinition : ICloneable
+ public class DTDAttributeDefinition : DTDNode// : ICloneable
{
public string Name;
- public DTDAttributeType AttributeType = DTDAttributeType.None;
+ public XmlSchemaDatatype Datatype;
// entity reference inside enumerated values are not allowed,
// but on the other hand, they are allowed inside default value.
// Then I decided to use string ArrayList for enumerated values,
@@ -108,29 +351,93 @@ namespace Mono.Xml
public string UnresolvedDefaultValue = null;
public ArrayList EnumeratedNotations = new ArrayList();
public DTDAttributeOccurenceType OccurenceType = DTDAttributeOccurenceType.None;
+ private string resolvedDefaultValue;
internal DTDAttributeDefinition () {}
- public object Clone ()
+ public string DefaultValue {
+ get {
+ if (resolvedDefaultValue == null)
+ resolvedDefaultValue = ComputeDefaultValue ();
+ return resolvedDefaultValue;
+ }
+ }
+
+ private string ComputeDefaultValue ()
{
- return this.MemberwiseClone ();
+ StringBuilder sb = new StringBuilder ();
+ int pos = 0;
+ int next = 0;
+ while ((next = this.UnresolvedDefaultValue.IndexOf ('&', pos)) >= 0) {
+ sb.Append (this.UnresolvedDefaultValue.Substring (pos, next - 1));
+ int semicolon = this.UnresolvedDefaultValue.IndexOf (';', next);
+ string name = this.UnresolvedDefaultValue.Substring (pos + 1, semicolon - 1);
+ sb.Append (Root.ResolveEntity (name));
+ }
+ sb.Append (this.UnresolvedDefaultValue.Substring (pos));
+ string ret = sb.ToString ();
+ sb.Length = 0;
+ return ret;
}
+
+// public object Clone ()
+// {
+// return this.MemberwiseClone ();
+// }
}
- public class DTDAttListDeclaration : ICloneable
+ public class DTDAttListDeclaration : DTDNode// : ICloneable
{
public string Name;
- public Hashtable AttributeDefinitions = new Hashtable ();
internal DTDAttListDeclaration () {}
+ private Hashtable attributeOrders = new Hashtable ();
+ private Hashtable attributes = new Hashtable ();
+
+ public DTDAttributeDefinition this [int i] {
+ get { return Get (i); }
+ }
+
+ public DTDAttributeDefinition this [string name] {
+ get { return Get (name); }
+ }
+
+ public DTDAttributeDefinition Get (int i)
+ {
+ return attributes [i] as DTDAttributeDefinition;
+ }
- public object Clone ()
+ public DTDAttributeDefinition Get (string name)
{
- return this.MemberwiseClone ();
+ return attributes [name] as DTDAttributeDefinition;
}
+
+ public ICollection Definitions {
+ get { return attributes.Values; }
+ }
+
+ public void Add (DTDAttributeDefinition def)
+ {
+ if (attributes [def.Name] != null)
+ throw new InvalidOperationException (String.Format (
+ "Attribute definition for {0} was already added at element {1}.",
+ def.Name, this.Name));
+ def.SetRoot (Root);
+ attributes.Add (def.Name, def);
+ attributeOrders.Add (def.Name, attributeOrders.Count);
+ }
+
+ public int Count {
+ get { return attributeOrders.Count; }
+ }
+
+// public object Clone ()
+// {
+// return this.MemberwiseClone ();
+// }
}
- public class DTDEntityDeclaration
+ public class DTDEntityDeclaration : DTDNode
{
public string Name;
public string PublicId;
@@ -142,7 +449,7 @@ namespace Mono.Xml
internal DTDEntityDeclaration () {}
}
- public class DTDNotationDeclaration
+ public class DTDNotationDeclaration : DTDNode
{
public string Name;
public string LocalName;
@@ -153,7 +460,7 @@ namespace Mono.Xml
internal DTDNotationDeclaration () {}
}
- public class DTDParameterEntityDeclaration
+ public class DTDParameterEntityDeclaration : DTDNode
{
public string Name;
public string PublicId;
@@ -161,4 +468,27 @@ namespace Mono.Xml
public string BaseURI;
public string Value;
}
+
+ public enum DTDContentOrderType
+ {
+ None,
+ Seq,
+ Or
+ }
+
+ public enum DTDAttributeOccurenceType
+ {
+ None,
+ Required,
+ Optional,
+ Fixed
+ }
+
+ public enum DTDOccurence
+ {
+ One,
+ Optional,
+ ZeroOrMore,
+ OneOrMore
+ }
}
diff --git a/mcs/class/System.XML/System.Xml/DTDValidatingReader.cs b/mcs/class/System.XML/System.Xml/DTDValidatingReader.cs
new file mode 100644
index 00000000000..8a8bfc157ca
--- /dev/null
+++ b/mcs/class/System.XML/System.Xml/DTDValidatingReader.cs
@@ -0,0 +1,527 @@
+using System;
+using System.Collections;
+using System.Xml;
+using System.Xml.Schema;
+
+namespace Mono.Xml
+{
+ public class DTDValidatingReader : XmlValidatingReader, IXmlLineInfo
+ {
+ public DTDValidatingReader (XmlReader reader)
+ : base (reader)
+ {
+ this.reader = reader;
+ elementStack = new Stack ();
+ automataStack = new Stack ();
+ }
+
+ XmlReader reader;
+ DTDObjectModel dtd;
+ Stack elementStack;
+ Stack automataStack;
+ string currentAttribute;
+
+ public DTDObjectModel DTD {
+ get { return dtd; }
+ }
+
+ public override void Close ()
+ {
+ reader.Close ();
+ }
+
+ // We had already done attribute validation, so can ignore name.
+ public override string GetAttribute (int i)
+ {
+ if (dtd == null)
+ return reader.GetAttribute (i);
+
+ // It should access attributes by *defined* order.
+ if (elementStack.Count == 0)
+ return String.Empty;
+ DTDAttributeDefinition def = dtd.ElementDecls [elementStack.Peek () as string]
+ .Attributes [i] as DTDAttributeDefinition;
+ string specified = reader.GetAttribute (def.Name);
+ return (specified != null) ? specified : def.DefaultValue;
+ }
+
+ public override string GetAttribute (string name)
+ {
+ if (dtd == null)
+ return reader.GetAttribute (name);
+
+ if (elementStack.Count == 0)
+ return String.Empty;
+ string specified = reader.GetAttribute (name);
+ if (specified != null)
+ return specified;
+
+ DTDAttributeDefinition def = dtd.ElementDecls [elementStack.Peek () as string]
+ .Attributes [name] as DTDAttributeDefinition;
+ return def.DefaultValue;
+ }
+
+ public override string GetAttribute (string name, string ns)
+ {
+ if (dtd == null)
+ return reader.GetAttribute (name, ns);
+
+ if (ns != String.Empty)
+ throw new InvalidOperationException ("DTD validating reader does not support namespace.");
+ return GetAttribute (name);
+ }
+
+ bool IXmlLineInfo.HasLineInfo ()
+ {
+ IXmlLineInfo ixli = reader as IXmlLineInfo;
+ if (ixli != null)
+ return ixli.HasLineInfo ();
+ else
+ return false;
+ }
+
+ public override string LookupNamespace (string prefix)
+ {
+ // Does it mean anything with DTD?
+ return reader.LookupNamespace (prefix);
+ }
+
+ public override void MoveToAttribute (int i)
+ {
+ if (dtd == null) {
+ reader.MoveToAttribute (i);
+ currentAttribute = reader.Name;
+ return;
+ }
+
+ // It should access attributes by *defined* order.
+ if (elementStack.Count == 0)
+ return;
+
+ DTDAttListDeclaration decl = dtd.ElementDecls [elementStack.Peek () as string].Attributes;
+ if (decl.Count <= i)
+ throw new ArgumentOutOfRangeException ("i");
+ DTDAttributeDefinition def = decl [i] as DTDAttributeDefinition;
+ currentAttribute = def.Name;
+ // We can ignore return value here.
+ reader.MoveToAttribute (def.Name);
+ }
+
+ public override bool MoveToAttribute (string name)
+ {
+ if (dtd == null) {
+ bool b = reader.MoveToAttribute (name);
+ if (b)
+ currentAttribute = reader.Name;
+ return b;
+ }
+
+ if (elementStack.Count == 0)
+ return false;
+
+ DTDAttributeDefinition def = dtd.ElementDecls [elementStack.Peek () as string]
+ .Attributes [name] as DTDAttributeDefinition;
+ if (def == null)
+ return false;
+ reader.MoveToAttribute (name);
+ currentAttribute = name;
+ return true;
+ }
+
+ public override bool MoveToAttribute (string name, string ns)
+ {
+ if (dtd == null) {
+ bool b = reader.MoveToAttribute (name, ns);
+ if (b)
+ currentAttribute = reader.Name;
+ return b;
+ }
+
+ if (ns != String.Empty)
+ throw new InvalidOperationException ("DTD validating reader does not support namespace.");
+ return MoveToAttribute (name);
+ }
+
+ public override bool MoveToElement ()
+ {
+ bool b = reader.MoveToElement ();
+ if (!b)
+ return false;
+ currentAttribute = null;
+ return true;
+ }
+
+ public override bool MoveToFirstAttribute ()
+ {
+ if (dtd == null) {
+ bool b = reader.MoveToFirstAttribute ();
+ if (b)
+ currentAttribute = reader.Name;
+ return b;
+ }
+
+ // It should access attributes by *defined* order.
+ if (elementStack.Count == 0)
+ return false;
+
+ DTDAttListDeclaration decl = dtd.ElementDecls [elementStack.Peek () as string].Attributes;
+ if (decl.Count == 0)
+ return false;
+ return reader.MoveToAttribute (decl [0].Name);
+ }
+
+ public override bool MoveToNextAttribute ()
+ {
+ if (dtd == null) {
+ bool b = reader.MoveToNextAttribute ();
+ if (b)
+ currentAttribute = reader.Name;
+ return b;
+ }
+
+ if (currentAttribute == null)
+ return false;
+
+ DTDAttListDeclaration decl = dtd.ElementDecls [elementStack.Peek () as string].Attributes;
+ int pos = 0;
+ for (; pos < decl.Count; pos++) {
+ if (decl [pos].Name == currentAttribute)
+ break;
+ }
+ if (pos == decl.Count)
+ return false;
+
+ currentAttribute = decl [pos].Name;
+ reader.MoveToAttribute (currentAttribute);
+ return true;
+ }
+
+ bool inContent;
+ DTDAutomata currentAutomata;
+ DTDAutomata previousAutomata;
+ bool isStandalone;
+
+ [MonoTODO]
+ public override bool Read ()
+ {
+ MoveToElement ();
+
+ bool b = reader.Read ();
+
+ if (!inContent && reader.NodeType == XmlNodeType.Element) {
+ inContent = true;
+ if (dtd == null)
+ currentAutomata = null;
+ else
+ currentAutomata = dtd.RootAutomata;
+ }
+
+ if (!b) {
+ if (elementStack.Count != 0)
+ throw new InvalidOperationException ("Unexpected end of XmlReader.");
+ return false;
+ }
+
+ switch (reader.NodeType) {
+ case XmlNodeType.XmlDeclaration:
+ if (GetAttribute ("standalone") == "yes")
+ isStandalone = true;
+ break;
+
+ case XmlNodeType.DocumentType:
+#if true
+ XmlTextReader xmlTextReader = reader as XmlTextReader;
+ this.dtd = xmlTextReader.currentSubset;
+#else
+ // It will support external DTD reader in the future.
+ this.dtd = new DTDReader (reader).DTD;
+#endif
+ break;
+
+ case XmlNodeType.Element: // startElementDeriv
+ // If no schema specification, then skip validation.
+ if (currentAutomata == null)
+ break;
+
+ previousAutomata = currentAutomata;
+ currentAutomata = currentAutomata.TryStartElement (reader.Name);
+ if (currentAutomata == DTD.Invalid)
+ throw new XmlException (reader as IXmlLineInfo,
+ String.Format ("Invalid start element found: {0}", reader.Name));
+ DTDElementDeclaration decl = DTD.ElementDecls [reader.Name];
+ if (decl == null)
+ throw new XmlException (reader as IXmlLineInfo,
+ String.Format ("Element {0} is not declared.", reader.Name));
+ elementStack.Push (reader.Name);
+ automataStack.Push (currentAutomata);
+ currentAutomata = decl.ContentModel.GetAutomata ();
+
+ // TODO: check attributes
+ if (decl.Attributes == null) {
+ if (reader.HasAttributes)
+ throw new XmlException (reader as IXmlLineInfo,
+ String.Format ("Attributes are found on element {0} while it has no attribute definitions.",
+ decl.Name));
+ }
+ else
+ ValidateAttributes (decl);
+
+ // If it is empty element then directly check end element.
+ if (reader.IsEmptyElement)
+ goto case XmlNodeType.EndElement;
+ break;
+
+ case XmlNodeType.EndElement: // endTagDeriv
+ // If no schema specification, then skip validation.
+ if (currentAutomata == null)
+ break;
+
+ decl = DTD.ElementDecls [reader.Name];
+ if (decl == null)
+ throw new XmlException (reader as IXmlLineInfo,
+ String.Format ("Element {0} is not declared.", reader.Name));
+
+ previousAutomata = currentAutomata;
+ // Don't let currentAutomata
+ DTDAutomata tmpAutomata = currentAutomata.TryEndElement ();
+ if (tmpAutomata == DTD.Invalid)
+ throw new XmlException (reader as IXmlLineInfo,
+ String.Format ("Invalid end element found: {0}", reader.Name));
+
+ elementStack.Pop ();
+ currentAutomata = automataStack.Pop () as DTDAutomata;
+ break;
+
+ case XmlNodeType.CDATA:
+ case XmlNodeType.SignificantWhitespace:
+ case XmlNodeType.Text:
+ // If no schema specification, then skip validation.
+ if (currentAutomata == null)
+ break;
+
+ DTDElementDeclaration elem = dtd.ElementDecls [elementStack.Peek () as string];
+ if (!elem.IsMixedContent)
+ throw new XmlException (reader as IXmlLineInfo,
+ String.Format ("Current element {0} does not allow character data content.", elementStack.Peek ()));
+ break;
+ }
+ return true;
+ }
+
+ private void ValidateAttributes (DTDElementDeclaration decl)
+ {
+ Hashtable atts = new Hashtable ();
+ if (reader.MoveToFirstAttribute ()) {
+ do {
+ atts.Add (reader.Name, reader.Value);
+ } while (reader.MoveToNextAttribute ());
+ }
+ foreach (DTDAttributeDefinition def in decl.Attributes.Definitions) {
+ string value = atts [def.Name] as string;
+ switch (def.OccurenceType) {
+ case DTDAttributeOccurenceType.Required:
+ if (value == null)
+ throw new XmlException (reader as IXmlLineInfo,
+ String.Format ("Required attribute {0} in element {1} not found .",
+ def.Name, decl.Name));
+ break;
+ case DTDAttributeOccurenceType.Fixed:
+ if (value != def.DefaultValue)
+ throw new XmlException (reader as IXmlLineInfo,
+ String.Format ("Fixed attribute {0} in element {1} has invalid value {2}.",
+ def.Name, decl.Name, reader.Value));
+ break;
+ }
+ atts.Remove (def.Name);
+ }
+ if (atts.Count > 0) {
+ string [] extraneous = new string [atts.Count];
+ int i=0;
+ foreach (string attribute in atts.Keys)
+ extraneous [i++] = attribute;
+ throw new XmlException (reader as IXmlLineInfo,
+ String.Format ("These attributes are not declared in element {0}: {1}",
+ decl.Name, String.Join (",", extraneous)));
+ }
+ reader.MoveToElement ();
+ }
+
+ public override bool ReadAttributeValue ()
+ {
+ return reader.ReadAttributeValue ();
+ }
+
+ public override string ReadInnerXml ()
+ {
+ // MS.NET 1.0 has a serious bug here. It skips validation.
+ return reader.ReadInnerXml ();
+ }
+
+ public override string ReadOuterXml ()
+ {
+ // MS.NET 1.0 has a serious bug here. It skips validation.
+ return reader.ReadOuterXml ();
+ }
+
+ public override string ReadString ()
+ {
+ // It seems to be the same as ReadInnerXml().
+ return reader.ReadString ();
+ }
+
+// public override void ResolveEntity ()
+// {
+// }
+
+ public override int AttributeCount {
+ get {
+ if (dtd == null || !inContent)
+ return reader.AttributeCount;
+
+ if (elementStack.Count == 0)
+ return 0;
+ return dtd.ElementDecls [elementStack.Peek () as string]
+ .Attributes.Count;
+ }
+ }
+
+ [MonoTODO ("Should consider general entities.")]
+ public override string BaseURI {
+ get {
+ return reader.BaseURI;
+ }
+ }
+
+ public override bool CanResolveEntity {
+ get { return true; }
+ }
+
+ [MonoTODO ("Should consider general entities' depth")]
+ public override int Depth {
+ get {
+ return (currentAttribute != null
+ || reader.NodeType != XmlNodeType.Attribute) ?
+ reader.Depth : reader.Depth + 1;
+ }
+ }
+
+ [MonoTODO]
+ public override bool EOF {
+ get { return reader.EOF; }
+ }
+
+ public override bool HasValue {
+ get {
+ return (currentAttribute != null
+ || reader.NodeType != XmlNodeType.Attribute) ?
+ reader.HasValue : true;
+ }
+ }
+
+ public override bool IsDefault {
+ get {
+ if (currentAttribute == null)
+ return false;
+ return reader.GetAttribute (currentAttribute) != null;
+ }
+ }
+
+ public override bool IsEmptyElement {
+ get { return reader.IsEmptyElement; }
+ }
+
+ public override string this [int i] {
+ get { return GetAttribute (i); }
+ }
+
+ public override string this [string name] {
+ get { return GetAttribute (name); }
+ }
+
+ public override string this [string name, string ns] {
+ get { return GetAttribute (name, ns); }
+ }
+
+ public override string LocalName {
+ get {
+ return (currentAttribute != null
+ || reader.NodeType != XmlNodeType.Attribute) ?
+ reader.LocalName : currentAttribute;
+ }
+ }
+
+ public override string Name {
+ get {
+ return (currentAttribute != null
+ || reader.NodeType != XmlNodeType.Attribute) ?
+ reader.Name : currentAttribute;
+ }
+ }
+
+ public override string NamespaceURI {
+ get {
+ if (currentAttribute != null)
+ return String.Empty;
+ return reader.NamespaceURI;
+ }
+ }
+
+ public override XmlNameTable NameTable {
+ get { return reader.NameTable; }
+ }
+
+ public override XmlNodeType NodeType {
+ get {
+ return (currentAttribute != null
+ || reader.NodeType != XmlNodeType.Attribute) ?
+ reader.NodeType : XmlNodeType.Attribute;
+ }
+ }
+
+ public override string Prefix {
+ get {
+ if (currentAttribute != null) {
+ int colon = currentAttribute.IndexOf (':');
+ return colon < 0 ?
+ currentAttribute :
+ currentAttribute.Substring (0, colon - 1);
+ }
+ else
+ return reader.Prefix;
+ }
+ }
+
+ public override char QuoteChar {
+ get {
+ // If it is not actually on an attribute, then it returns
+ // undefined value or '"'.
+ return reader.QuoteChar;
+ }
+ }
+
+ public override ReadState ReadState {
+ get {
+ return reader.ReadState;
+ }
+ }
+
+ public override string Value {
+ get {
+ if (currentAttribute != null || reader.NodeType != XmlNodeType.Attribute)
+ return reader.Value;
+ return reader.GetAttribute (currentAttribute);
+ }
+ }
+
+ [MonoTODO ("Should consider default xml:lang values.")]
+ public override string XmlLang {
+ get { return reader.XmlLang; }
+ }
+
+ [MonoTODO ("Should consider default xml:space values.")]
+ public override XmlSpace XmlSpace {
+ get { return reader.XmlSpace; }
+ }
+
+ }
+}
diff --git a/mcs/class/System.XML/System.Xml/XmlDocument.cs b/mcs/class/System.XML/System.Xml/XmlDocument.cs
index 3d555860527..8b710ac813e 100644
--- a/mcs/class/System.XML/System.Xml/XmlDocument.cs
+++ b/mcs/class/System.XML/System.Xml/XmlDocument.cs
@@ -284,7 +284,7 @@ namespace System.Xml
return new XmlEntityReference (name, this);
}
- internal virtual XPathNavigator CreateNavigator (XmlNode node)
+ protected internal virtual XPathNavigator CreateNavigator (XmlNode node)
{
return new XmlDocumentNavigator (node);
}
@@ -547,7 +547,9 @@ namespace System.Xml
public virtual void Load (string filename)
{
- Load (new XmlTextReader (filename));
+ XmlReader xr = new XmlTextReader (filename);
+ Load (xr);
+ xr.Close ();
}
public virtual void Load (TextReader txtReader)
@@ -849,10 +851,10 @@ namespace System.Xml
doctype.notations.Nodes.Add (n);
}
foreach (DTDElementDeclaration decl in subset.ElementDecls.Values) {
- doctype.elementDecls.Add (decl.Name, decl.Clone ());
+ doctype.elementDecls.Add (decl.Name, decl);
}
foreach (DTDAttListDeclaration decl in subset.AttListDecls.Values) {
- doctype.attListDecls.Add (decl.Name, decl.Clone ());
+ doctype.attListDecls.Add (decl.Name, decl);
}
return doctype;
}
diff --git a/mcs/class/System.XML/System.Xml/XmlTextReader.cs b/mcs/class/System.XML/System.Xml/XmlTextReader.cs
index 697e7a601b1..33e4aa5ae5d 100644
--- a/mcs/class/System.XML/System.Xml/XmlTextReader.cs
+++ b/mcs/class/System.XML/System.Xml/XmlTextReader.cs
@@ -25,6 +25,7 @@ using System;
using System.Collections;
using System.IO;
using System.Text;
+using System.Xml.Schema;
using Mono.Xml;
using Mono.Xml.Native;
@@ -1563,6 +1564,7 @@ namespace System.Xml
// now compile DTD
currentSubset = new DTDObjectModel (); // merges both internal and external subsets in the meantime,
+ currentSubset.Name = doctypeName;
int originalParserDepth = parserInputStack.Count;
if (intSubsetStartLine > 0) {
XmlParserInput original = currentInput;
@@ -1900,7 +1902,7 @@ namespace System.Xml
case 'A':
Expect ("TTLIST");
DTDAttListDeclaration atl = ReadAttListDecl ();
- if (currentSubset.AttListDecls.ContainsKey (atl.Name))
+// if (currentSubset.AttListDecls.ContainsKey (atl.Name))
currentSubset.AttListDecls.Add (atl.Name, atl);
break;
case 'N':
@@ -1962,7 +1964,7 @@ namespace System.Xml
// The reader is positioned on the head of the name.
private DTDElementDeclaration ReadElementDecl ()
{
- DTDElementDeclaration decl = new DTDElementDeclaration ();
+ DTDElementDeclaration decl = new DTDElementDeclaration (currentSubset);
SkipWhitespace ();
TryExpandPERef ();
decl.Name = ReadName ();
@@ -1993,7 +1995,7 @@ namespace System.Xml
SkipWhitespace ();
TryExpandPERef ();
if(PeekChar () == '#') {
- // Mixed Contents
+ // Mixed Contents. "#PCDATA" must appear first.
decl.IsMixedContent = true;
Expect ("#PCDATA");
SkipWhitespace ();
@@ -2004,16 +2006,20 @@ namespace System.Xml
SkipWhitespace ();
TryExpandPERef ();
SkipWhitespace ();
- model.ChildModels.Add (ReadName ());
+ DTDContentModel elem = new DTDContentModel (currentSubset, decl.Name);
+ model.ElementName = ReadName ();
+ model.ChildModels.Add (elem);
SkipWhitespace ();
TryExpandPERef ();
}
Expect (')');
- if(PeekChar () == '*')
- ReadChar (); // ZeroOrMore
+ if (model.ChildModels.Count > 0) {
+ Expect ('*');
+ model.Occurence = DTDOccurence.ZeroOrMore;
+ }
} else {
// Non-Mixed Contents
- model.ChildModels.Add (ReadCP ());
+ model.ChildModels.Add (ReadCP (decl));
SkipWhitespace ();
do { // copied from ReadCP() ...;-)
@@ -2024,7 +2030,7 @@ namespace System.Xml
model.OrderType = DTDContentOrderType.Or;
ReadChar ();
SkipWhitespace ();
- model.ChildModels.Add (ReadCP ());
+ model.ChildModels.Add (ReadCP (decl));
SkipWhitespace ();
}
else if(PeekChar () == ',')
@@ -2033,7 +2039,7 @@ namespace System.Xml
model.OrderType = DTDContentOrderType.Seq;
ReadChar ();
SkipWhitespace ();
- model.ChildModels.Add (ReadCP ());
+ model.ChildModels.Add (ReadCP (decl));
SkipWhitespace ();
}
else
@@ -2045,16 +2051,15 @@ namespace System.Xml
switch(PeekChar ())
{
case '?':
- model.MinOccurs = 0;
+ model.Occurence = DTDOccurence.Optional;
ReadChar ();
break;
case '*':
- model.MinOccurs = 0;
- model.MaxOccurs = decimal.MaxValue;
+ model.Occurence = DTDOccurence.ZeroOrMore;
ReadChar ();
break;
case '+':
- model.MaxOccurs = decimal.MaxValue;
+ model.Occurence = DTDOccurence.OneOrMore;
ReadChar ();
break;
}
@@ -2066,14 +2071,15 @@ namespace System.Xml
}
// Read 'cp' (BNF) of contentdecl (BNF)
- private DTDContentModel ReadCP ()
+ private DTDContentModel ReadCP (DTDElementDeclaration elem)
{
- DTDContentModel model = new DTDContentModel ();
+ DTDContentModel model = null;
TryExpandPERef ();
if(PeekChar () == '(') {
+ model = new DTDContentModel (currentSubset, elem.Name);
ReadChar ();
SkipWhitespace ();
- model.ChildModels.Add (ReadCP ());
+ model.ChildModels.Add (ReadCP (elem));
SkipWhitespace ();
do {
TryExpandPERef ();
@@ -2083,7 +2089,7 @@ namespace System.Xml
model.OrderType = DTDContentOrderType.Or;
ReadChar ();
SkipWhitespace ();
- model.ChildModels.Add (ReadCP ());
+ model.ChildModels.Add (ReadCP (elem));
SkipWhitespace ();
}
else if(PeekChar () == ',') {
@@ -2091,7 +2097,7 @@ namespace System.Xml
model.OrderType = DTDContentOrderType.Seq;
ReadChar ();
SkipWhitespace ();
- model.ChildModels.Add (ReadCP ());
+ model.ChildModels.Add (ReadCP (elem));
SkipWhitespace ();
}
else
@@ -2103,21 +2109,21 @@ namespace System.Xml
}
else {
TryExpandPERef ();
+ model = new DTDContentModel (currentSubset, elem.Name);
model.ElementName = ReadName ();
}
switch(PeekChar ()) {
case '?':
- model.MinOccurs = 0;
+ model.Occurence = DTDOccurence.Optional;
ReadChar ();
break;
case '*':
- model.MinOccurs = 0;
- model.MaxOccurs = decimal.MaxValue;
+ model.Occurence = DTDOccurence.ZeroOrMore;
ReadChar ();
break;
case '+':
- model.MaxOccurs = decimal.MaxValue;
+ model.Occurence = DTDOccurence.OneOrMore;
ReadChar ();
break;
}
@@ -2290,8 +2296,8 @@ namespace System.Xml
while (XmlConstructs.IsName ((char) PeekChar ())) {
DTDAttributeDefinition def = ReadAttributeDefinition ();
- if (decl.AttributeDefinitions [def.Name] == null)
- decl.AttributeDefinitions.Add (def.Name, def);
+ if (decl [def.Name] == null)
+ decl.Add (def);
SkipWhitespace ();
TryExpandPERef ();
SkipWhitespace ();
@@ -2315,7 +2321,7 @@ namespace System.Xml
switch(PeekChar ()) {
case 'C': // CDATA
Expect ("CDATA");
- def.AttributeType = DTDAttributeType.CData;
+ def.Datatype = XmlSchemaDatatype.FromName ("normalizedString");
break;
case 'I': // ID, IDREF, IDREFS
Expect ("ID");
@@ -2324,23 +2330,23 @@ namespace System.Xml
if(PeekChar () == 'S') {
// IDREFS
ReadChar ();
- def.AttributeType = DTDAttributeType.IdRefs;
+ def.Datatype = XmlSchemaDatatype.FromName ("IDREFS");
}
else // IDREF
- def.AttributeType = DTDAttributeType.IdRef;
+ def.Datatype = XmlSchemaDatatype.FromName ("IDREF");
}
else // ID
- def.AttributeType = DTDAttributeType.Id;
+ def.Datatype = XmlSchemaDatatype.FromName ("ID");
break;
case 'E': // ENTITY, ENTITIES
Expect ("ENTIT");
switch(ReadChar ()) {
case 'Y': // ENTITY
- def.AttributeType = DTDAttributeType.Entity;
+ def.Datatype = XmlSchemaDatatype.FromName ("ENTITY");
break;
case 'I': // ENTITIES
Expect ("ES");
- def.AttributeType = DTDAttributeType.Entities;
+ def.Datatype = XmlSchemaDatatype.FromName ("ENTITIES");
break;
}
break;
@@ -2351,14 +2357,14 @@ namespace System.Xml
Expect ("MTOKEN");
if(PeekChar ()=='S') { // NMTOKENS
ReadChar ();
- def.AttributeType = DTDAttributeType.NmTokens;
+ def.Datatype = XmlSchemaDatatype.FromName ("NMTOKENS");
}
else // NMTOKEN
- def.AttributeType = DTDAttributeType.NmToken;
+ def.Datatype = XmlSchemaDatatype.FromName ("NMTOKEN");
break;
case 'O':
Expect ("OTATION");
- def.AttributeType = DTDAttributeType.Notation;
+ def.Datatype = XmlSchemaDatatype.FromName ("NOTATION");
SkipWhitespace ();
Expect ('(');
SkipWhitespace ();
diff --git a/mcs/class/System.XML/System.Xml/XmlValidatingReader.cs b/mcs/class/System.XML/System.Xml/XmlValidatingReader.cs
index 330793f55ad..45b8b4e14d3 100644
--- a/mcs/class/System.XML/System.Xml/XmlValidatingReader.cs
+++ b/mcs/class/System.XML/System.Xml/XmlValidatingReader.cs
@@ -3,13 +3,16 @@
//
// Author:
// Tim Coleman (tim@timcoleman.com)
+// Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
//
// Copyright (C) Tim Coleman, 2002
+// (C)2003 Atsushi Enomoto
//
using System.IO;
using System.Text;
using System.Xml.Schema;
+using Mono.Xml;
namespace System.Xml {
public class XmlValidatingReader : XmlReader, IXmlLineInfo {
@@ -17,8 +20,9 @@ namespace System.Xml {
#region Fields
EntityHandling entityHandling;
- bool namespaces;
- XmlReader reader;
+ XmlReader sourceReader;
+ XmlReader validatingReader;
+ XmlResolver resolver;
ValidationType validationType;
#endregion // Fields
@@ -29,23 +33,18 @@ namespace System.Xml {
public XmlValidatingReader (XmlReader reader)
: base ()
{
- if (!(reader is XmlTextReader))
- throw new ArgumentException ();
-
- this.reader = reader;
+ this.sourceReader = reader;
entityHandling = EntityHandling.ExpandEntities;
- namespaces = true;
validationType = ValidationType.Auto;
}
- [MonoTODO]
public XmlValidatingReader (Stream xmlFragment, XmlNodeType fragType, XmlParserContext context)
- : this (new XmlTextReader (xmlFragment))
+ : this (new XmlTextReader (xmlFragment, fragType, context))
{
}
public XmlValidatingReader (string xmlFragment, XmlNodeType fragType, XmlParserContext context)
- : this (new XmlTextReader (xmlFragment))
+ : this (new XmlTextReader (xmlFragment, fragType, context))
{
}
@@ -55,21 +54,21 @@ namespace System.Xml {
public override int AttributeCount {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? 0 : validatingReader.AttributeCount; }
}
public override string BaseURI {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? String.Empty : validatingReader.BaseURI; }
}
public override bool CanResolveEntity {
- get { return true; }
+ get { return validatingReader == null ? false : validatingReader.CanResolveEntity; }
}
public override int Depth {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? 0 : validatingReader.Depth; }
}
public Encoding Encoding {
@@ -77,103 +76,129 @@ namespace System.Xml {
get { throw new NotImplementedException (); }
}
+ [MonoTODO]
public EntityHandling EntityHandling {
get { return entityHandling; }
- set { entityHandling = value; }
+ set {
+ throw new NotImplementedException ();
+// entityHandling = value;
+ }
}
public override bool EOF {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? false : validatingReader.EOF; }
}
public override bool HasValue {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? false : validatingReader.HasValue; }
}
public override bool IsDefault {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? false : validatingReader.IsDefault; }
}
public override bool IsEmptyElement {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? false : validatingReader.IsEmptyElement; }
}
public override string this [int i] {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader [i]; }
}
public override string this [string name] {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? String.Empty : validatingReader [name]; }
}
public override string this [string localName, string namespaceName] {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? String.Empty : validatingReader [localName, namespaceName]; }
}
int IXmlLineInfo.LineNumber {
- [MonoTODO]
- get { throw new NotImplementedException (); }
+ get {
+ IXmlLineInfo info = validatingReader as IXmlLineInfo;
+ return info != null ? info.LineNumber : 0;
+ }
}
int IXmlLineInfo.LinePosition {
- [MonoTODO]
- get { throw new NotImplementedException (); }
+ get {
+ IXmlLineInfo info = validatingReader as IXmlLineInfo;
+ return info != null ? info.LinePosition : 0;
+ }
}
public override string LocalName {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? String.Empty : validatingReader.LocalName; }
}
public override string Name {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? String.Empty : validatingReader.Name; }
}
+ [MonoTODO]
public bool Namespaces {
- get { return namespaces; }
- set { namespaces = value; }
+ get {
+ XmlTextReader xtr = sourceReader as XmlTextReader;
+ if (xtr != null)
+ return xtr.Namespaces;
+ else
+ throw new NotImplementedException ();
+ }
+ set {
+ XmlTextReader xtr = sourceReader as XmlTextReader;
+ if (xtr != null)
+ xtr.Namespaces = value;
+ else
+ throw new NotImplementedException ();
+ }
}
public override string NamespaceURI {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? String.Empty : validatingReader.NamespaceURI; }
}
public override XmlNameTable NameTable {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? null : validatingReader.NameTable; }
}
public override XmlNodeType NodeType {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? XmlNodeType.None : validatingReader.NodeType; }
}
public override string Prefix {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? String.Empty : validatingReader.Prefix; }
}
public override char QuoteChar {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? '"' : validatingReader.QuoteChar; }
}
+ [MonoTODO ("confirm which reader should be returned.")]
public XmlReader Reader {
- get { return reader; }
+ get { return sourceReader; }
}
public override ReadState ReadState {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get {
+ if (validatingReader == null)
+ return ReadState.Initial;
+ return validatingReader.ReadState;
+ }
}
public XmlSchemaCollection Schemas {
@@ -186,30 +211,43 @@ namespace System.Xml {
get { throw new NotImplementedException (); }
}
+ [MonoTODO]
public ValidationType ValidationType {
get { return validationType; }
- [MonoTODO ("Need to check for exception.")]
- set { validationType = value; }
+ set {
+ if (ReadState != ReadState.Initial)
+ throw new InvalidOperationException ("ValidationType cannot be set after the first call to Read method.");
+ switch (validationType) {
+ case ValidationType.Auto:
+ case ValidationType.DTD:
+ validationType = value;
+ break;
+ case ValidationType.None:
+ case ValidationType.Schema:
+ case ValidationType.XDR:
+ throw new NotImplementedException ();
+ }
+ }
}
public override string Value {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? String.Empty : validatingReader.Value; }
}
public override string XmlLang {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? null : validatingReader.XmlLang; }
}
public XmlResolver XmlResolver {
[MonoTODO]
- set { throw new NotImplementedException (); }
+ set { resolver = value; }
}
public override XmlSpace XmlSpace {
[MonoTODO]
- get { throw new NotImplementedException (); }
+ get { return validatingReader == null ? XmlSpace.None : validatingReader.XmlSpace; }
}
#endregion // Properties
@@ -219,103 +257,115 @@ namespace System.Xml {
[MonoTODO]
public override void Close ()
{
- throw new NotImplementedException ();
+ validatingReader.Close ();
}
[MonoTODO]
public override string GetAttribute (int i)
{
- throw new NotImplementedException ();
+ return validatingReader.GetAttribute (i);
}
[MonoTODO]
public override string GetAttribute (string name)
{
- throw new NotImplementedException ();
+ return validatingReader.GetAttribute (name);
}
[MonoTODO]
public override string GetAttribute (string localName, string namespaceName)
{
- throw new NotImplementedException ();
+ return validatingReader.GetAttribute (localName, namespaceName);
}
- [MonoTODO]
bool IXmlLineInfo.HasLineInfo ()
{
- throw new NotImplementedException ();
+ IXmlLineInfo info = validatingReader as IXmlLineInfo;
+ return info != null ? info.HasLineInfo () : false;
}
[MonoTODO]
public override string LookupNamespace (string prefix)
{
- throw new NotImplementedException ();
+ return validatingReader.LookupNamespace (prefix);
}
[MonoTODO]
public override void MoveToAttribute (int i)
{
- throw new NotImplementedException ();
+ validatingReader.MoveToAttribute (i);
}
[MonoTODO]
public override bool MoveToAttribute (string name)
{
- throw new NotImplementedException ();
+ return validatingReader.MoveToAttribute (name);
}
[MonoTODO]
public override bool MoveToAttribute (string localName, string namespaceName)
{
- throw new NotImplementedException ();
+ return validatingReader.MoveToAttribute (localName, namespaceName);
}
[MonoTODO]
public override bool MoveToElement ()
{
- throw new NotImplementedException ();
+ return validatingReader.MoveToElement ();
}
[MonoTODO]
public override bool MoveToFirstAttribute ()
{
- throw new NotImplementedException ();
+ return validatingReader.MoveToFirstAttribute ();
}
[MonoTODO]
public override bool MoveToNextAttribute ()
{
- throw new NotImplementedException ();
+ return validatingReader.MoveToNextAttribute ();
}
[MonoTODO]
public override bool Read ()
{
- throw new NotImplementedException ();
+ if (ReadState == ReadState.Initial) {
+ switch (ValidationType) {
+ case ValidationType.Auto:
+ case ValidationType.DTD:
+ validatingReader = new DTDValidatingReader (sourceReader);
+ break;
+ case ValidationType.None:
+ case ValidationType.Schema:
+ case ValidationType.XDR:
+ throw new NotImplementedException ();
+ }
+ }
+ return validatingReader.Read ();
}
[MonoTODO]
public override bool ReadAttributeValue ()
{
- throw new NotImplementedException ();
+ return validatingReader.ReadAttributeValue ();
}
[MonoTODO]
public override string ReadInnerXml ()
{
- throw new NotImplementedException ();
+ return validatingReader.ReadInnerXml ();
}
[MonoTODO]
public override string ReadOuterXml ()
{
- throw new NotImplementedException ();
+ return validatingReader.ReadOuterXml ();
}
[MonoTODO]
public override string ReadString ()
{
- throw new NotImplementedException ();
+ return validatingReader.ReadString ();
}
[MonoTODO]