diff options
author | Atsushi Eno <atsushieno@gmail.com> | 2003-07-06 20:17:31 +0400 |
---|---|---|
committer | Atsushi Eno <atsushieno@gmail.com> | 2003-07-06 20:17:31 +0400 |
commit | d6b7b632e3fa96bd4b2d773dda6103af7de9b763 (patch) | |
tree | 0ea09b5e3e03bd58376df26d6bfac0e36bc04d57 /mcs/class/System.XML/System.Xml/DTDObjectModel.cs | |
parent | 3f7e68b2751de7db455425dfcffb49bab4ece088 (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
Diffstat (limited to 'mcs/class/System.XML/System.Xml/DTDObjectModel.cs')
-rw-r--r-- | mcs/class/System.XML/System.Xml/DTDObjectModel.cs | 438 |
1 files changed, 384 insertions, 54 deletions
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 + } } |