diff options
author | Atsushi Eno <atsushieno@gmail.com> | 2003-07-19 20:39:15 +0400 |
---|---|---|
committer | Atsushi Eno <atsushieno@gmail.com> | 2003-07-19 20:39:15 +0400 |
commit | 934b8c07bc88643b5e08630c16f9e89dab3a566e (patch) | |
tree | e7bfd232e95bf60a451d471acc4302f1f6e6aaa3 | |
parent | d670f3a599826fd835429d2af6a12f2d11a1e86e (diff) |
2003-07-19 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
* DTDValidatingReader.cs :
changed base class to XmlReader and implemented IXmlLineInfo members.
changed .ctor() argument from event handler to validating reader.
Removed some #if ... #else ... #endif blocks.
Added validation event support for Read() using HandleError().
* XmlValidatingReader.cs : added internal OnValidationEvent().
* XmlDocument.cs : ReadNode() now checks reader's state more strictly.
svn path=/trunk/mcs/; revision=16430
-rw-r--r-- | mcs/class/System.XML/System.Xml/ChangeLog | 10 | ||||
-rw-r--r-- | mcs/class/System.XML/System.Xml/DTDValidatingReader.cs | 235 | ||||
-rw-r--r-- | mcs/class/System.XML/System.Xml/XmlDocument.cs | 12 | ||||
-rw-r--r-- | mcs/class/System.XML/System.Xml/XmlValidatingReader.cs | 12 |
4 files changed, 149 insertions, 120 deletions
diff --git a/mcs/class/System.XML/System.Xml/ChangeLog b/mcs/class/System.XML/System.Xml/ChangeLog index 245f165b1fd..63d0fd667e0 100644 --- a/mcs/class/System.XML/System.Xml/ChangeLog +++ b/mcs/class/System.XML/System.Xml/ChangeLog @@ -1,5 +1,15 @@ 2003-07-19 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp> + * DTDValidatingReader.cs : + changed base class to XmlReader and implemented IXmlLineInfo members. + changed .ctor() argument from event handler to validating reader. + Removed some #if ... #else ... #endif blocks. + Added validation event support for Read() using HandleError(). + * XmlValidatingReader.cs : added internal OnValidationEvent(). + * XmlDocument.cs : ReadNode() now checks reader's state more strictly. + +2003-07-19 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp> + * XmlUrlResolver.cs : applied BenM's patch for file uri problem (bug #46610). diff --git a/mcs/class/System.XML/System.Xml/DTDValidatingReader.cs b/mcs/class/System.XML/System.Xml/DTDValidatingReader.cs index 834a4c9b99c..18faa35853b 100644 --- a/mcs/class/System.XML/System.Xml/DTDValidatingReader.cs +++ b/mcs/class/System.XML/System.Xml/DTDValidatingReader.cs @@ -6,7 +6,7 @@ using System.Xml.Schema; namespace Mono.Xml { - public class DTDValidatingReader : XmlValidatingReader, IXmlLineInfo + public class DTDValidatingReader : /*XmlValidatingReader*/XmlReader, IXmlLineInfo { public DTDValidatingReader (XmlReader reader) : this (reader, null) @@ -14,14 +14,14 @@ namespace Mono.Xml } public DTDValidatingReader (XmlReader reader, - ValidationEventHandler validationEventHandler) - : base (reader) + XmlValidatingReader validatingReader) +// : base (reader) { this.reader = reader; elementStack = new Stack (); automataStack = new Stack (); attributes = new StringCollection (); - this.validationEventHandler = validationEventHandler; + this.validatingReader = validatingReader; } XmlReader reader; @@ -36,7 +36,9 @@ namespace Mono.Xml DTDAutomata previousAutomata; bool isStandalone; StringCollection attributes; - ValidationEventHandler validationEventHandler; + + XmlValidatingReader validatingReader; + ValidationEventHandler handler; public DTDObjectModel DTD { get { return dtd; } @@ -55,7 +57,6 @@ namespace Mono.Xml if (NodeType != XmlNodeType.Element) return String.Empty; -#if true if (attributes.Count <= i) throw new IndexOutOfRangeException ("Specified index is out of range: " + i); if (reader.AttributeCount > i) @@ -64,12 +65,6 @@ namespace Mono.Xml DTDAttributeDefinition def = dtd.ElementDecls [currentElement] .Attributes [i] as DTDAttributeDefinition; return def.DefaultValue; -#else - DTDAttributeDefinition def = dtd.ElementDecls [currentElement] - .Attributes [i] as DTDAttributeDefinition; - string specified = reader.GetAttribute (def.Name); - return (specified != null) ? specified : def.DefaultValue; -#endif } public override string GetAttribute (string name) @@ -133,22 +128,12 @@ namespace Mono.Xml if (currentElement == null) return; -#if true if (attributes.Count > i) { currentAttribute = attributes [i]; consumedDefaultAttribute = false; return; } else throw new IndexOutOfRangeException ("The index is out of range."); -#else - DTDAttListDeclaration decl = dtd.ElementDecls [currentElement].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); -#endif } public override bool MoveToAttribute (string name) @@ -165,7 +150,6 @@ namespace Mono.Xml if (currentElement == null) return false; -#if true int idx = attributes.IndexOf (name); if (idx >= 0) { currentAttribute = name; @@ -173,15 +157,6 @@ namespace Mono.Xml return true; } return false; -#else - DTDAttributeDefinition def = dtd.ElementDecls [currentElement] - .Attributes [name] as DTDAttributeDefinition; - if (def == null) - return false; - reader.MoveToAttribute (name); - currentAttribute = name; - return true; -#endif } public override bool MoveToAttribute (string name, string ns) @@ -195,7 +170,6 @@ namespace Mono.Xml return b; } -#if true if (reader.MoveToAttribute (name, ns)) { currentAttribute = reader.Name; consumedDefaultAttribute = false; @@ -205,11 +179,6 @@ namespace Mono.Xml if (ns != String.Empty) throw new InvalidOperationException ("DTD validating reader does not support namespace."); return MoveToAttribute (name); -#else - if (ns != String.Empty) - throw new InvalidOperationException ("DTD validating reader does not support namespace."); - return MoveToAttribute (name); -#endif } public override bool MoveToElement () @@ -236,19 +205,13 @@ namespace Mono.Xml // It should access attributes by *defined* order. if (NodeType != XmlNodeType.Element) return false; -#if true + if (attributes.Count == 0) return false; reader.MoveToFirstAttribute (); currentAttribute = attributes [0]; consumedDefaultAttribute = false; return true; -#else - DTDAttListDeclaration decl = dtd.ElementDecls [this.Name].Attributes; - if (decl.Count == 0) - return false; - return reader.MoveToAttribute (decl [0].Name); -#endif } public override bool MoveToNextAttribute () @@ -264,7 +227,7 @@ namespace Mono.Xml if (currentAttribute == null) return false; -#if true + int idx = attributes.IndexOf (currentAttribute); if (idx + 1 < attributes.Count) { reader.MoveToNextAttribute (); @@ -273,20 +236,6 @@ namespace Mono.Xml return true; } else return false; -#else - DTDAttListDeclaration decl = dtd.ElementDecls [currentElement].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; -#endif } [MonoTODO] @@ -321,7 +270,6 @@ namespace Mono.Xml break; case XmlNodeType.DocumentType: -#if true XmlTextReader xmlTextReader = reader as XmlTextReader; if (xmlTextReader == null) { xmlTextReader = new XmlTextReader ("", XmlNodeType.Document, null); @@ -329,10 +277,6 @@ namespace Mono.Xml reader ["PUBLIC"], reader ["SYSTEM"], reader.Value); } this.dtd = xmlTextReader.DTD; -#else - // It will support external DTD reader in the future. - this.dtd = new DTDReader (reader).DTD; -#endif break; case XmlNodeType.Element: // startElementDeriv @@ -342,28 +286,43 @@ namespace Mono.Xml 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)); + if (currentAutomata == DTD.Invalid) { + HandleError (String.Format ("Invalid start element found: {0}", reader.Name), + XmlSeverityType.Error); + // FIXME: validation recovery code here. + currentAutomata = previousAutomata; + } DTDElementDeclaration decl = DTD.ElementDecls [reader.Name]; - if (decl == null) - throw new XmlException (reader as IXmlLineInfo, - String.Format ("Element {0} is not declared.", reader.Name)); + if (decl == null) { + HandleError (String.Format ("Element {0} is not declared.", reader.Name), + XmlSeverityType.Error); + // FIXME: validation recovery code here. + currentAutomata = previousAutomata; + } currentElement = Name; elementStack.Push (reader.Name); automataStack.Push (currentAutomata); - currentAutomata = decl.ContentModel.GetAutomata (); - - // 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)); + if (decl != null) { // i.e. not invalid + currentAutomata = decl.ContentModel.GetAutomata (); + + // check attributes + if (decl.Attributes == null) { + if (reader.HasAttributes) { + HandleError (String.Format ("Attributes are found on element {0} while it has no attribute definitions.",decl.Name), + XmlSeverityType.Error); + // FIXME: validation recovery code here. + } + } + else + ValidateAttributes (decl); + } else if (reader.MoveToFirstAttribute ()) { + // If it was invalid, simply add specified attributes. + do { + attributes.Add (reader.Name); + } while (reader.MoveToNextAttribute ()); + reader.MoveToElement (); } - else - ValidateAttributes (decl); // If it is empty element then directly check end element. if (reader.IsEmptyElement) @@ -376,16 +335,21 @@ namespace Mono.Xml break; decl = DTD.ElementDecls [reader.Name]; - if (decl == null) - throw new XmlException (reader as IXmlLineInfo, - String.Format ("Element {0} is not declared.", reader.Name)); + if (decl == null) { + HandleError (String.Format ("Element {0} is not declared.", reader.Name), + XmlSeverityType.Error); + // FIXME: validation recovery code here. + } 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)); + if (tmpAutomata == DTD.Invalid) { + HandleError (String.Format ("Invalid end element found: {0}", reader.Name), + XmlSeverityType.Error); + // FIXME: validation recovery code here. + currentAutomata = previousAutomata; + } elementStack.Pop (); currentAutomata = automataStack.Pop () as DTDAutomata; @@ -399,35 +363,63 @@ namespace Mono.Xml 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 ())); + if (!elem.IsMixedContent) { + HandleError (String.Format ("Current element {0} does not allow character data content.", elementStack.Peek () as string), + XmlSeverityType.Error); + // FIXME: validation recovery code here. + currentAutomata = previousAutomata; + } break; } return true; } + private void HandleError (string message, XmlSeverityType severity) + { + IXmlLineInfo info = this as IXmlLineInfo; + bool hasLine = info.HasLineInfo (); + XmlSchemaException ex = new XmlSchemaException ( + message, + hasLine ? info.LineNumber : 0, + hasLine ? info.LinePosition : 0, + null, + BaseURI, + null); + + if (validatingReader != null) + this.validatingReader.OnValidationEvent (this, + new ValidationEventArgs (ex, message, severity)); + else + throw ex; + } + private void ValidateAttributes (DTDElementDeclaration decl) { if (reader.MoveToFirstAttribute ()) { do { attributes.Add (reader.Name); DTDAttributeDefinition def = decl.Attributes [reader.Name]; - if (def == null) - throw new XmlException (this as IXmlLineInfo, - String.Format ("Attribute {0} is not declared.", reader.Name)); + if (def == null) { + HandleError (String.Format ("Attribute {0} is not declared.", reader.Name), + XmlSeverityType.Error); + // FIXME: validation recovery code here. + } switch (def.OccurenceType) { case DTDAttributeOccurenceType.Required: - if (reader.Value == String.Empty) - throw new XmlException (reader as IXmlLineInfo, - String.Format ("Required attribute {0} in element {1} not found .", - def.Name, decl.Name)); + if (reader.Value == String.Empty) { + HandleError (String.Format ("Required attribute {0} in element {1} not found .", + def.Name, decl.Name), + XmlSeverityType.Error); + // FIXME: validation recovery code here. + } break; case DTDAttributeOccurenceType.Fixed: - if (reader.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)); + if (reader.Value != def.DefaultValue) { + HandleError (String.Format ("Fixed attribute {0} in element {1} has invalid value {2}.", + def.Name, decl.Name, reader.Value), + XmlSeverityType.Error); + // FIXME: validation recovery code here. + } break; } } while (reader.MoveToNextAttribute ()); @@ -436,9 +428,11 @@ namespace Mono.Xml // if there is default values, then add them. foreach (DTDAttributeDefinition def in decl.Attributes.Definitions) if (!attributes.Contains (def.Name)) { - if (def.OccurenceType == DTDAttributeOccurenceType.Required) - throw new XmlException (reader as IXmlLineInfo, - String.Format ("Required attribute {0} was not found.", decl.Name)); + if (def.OccurenceType == DTDAttributeOccurenceType.Required) { + HandleError (String.Format ("Required attribute {0} was not found.", decl.Name), + XmlSeverityType.Error); + // FIXME: validation recovery code here. + } else if (def.DefaultValue != null) attributes.Add (def.Name); } @@ -475,21 +469,18 @@ namespace Mono.Xml return reader.ReadString (); } -// public override void ResolveEntity () -// { -// } + [MonoTODO] + public override void ResolveEntity () + { + throw new NotImplementedException (); + } public override int AttributeCount { get { if (dtd == null || !inContent) return reader.AttributeCount; -#if true + return attributes.Count; -#else - if (elementStack.Count == 0) - return 0; - return dtd.ElementDecls [currentElement].Attributes.Count; -#endif } } @@ -542,6 +533,20 @@ namespace Mono.Xml get { return GetAttribute (name, ns); } } + public int LineNumber { + get { + IXmlLineInfo info = reader as IXmlLineInfo; + return (info != null) ? info.LineNumber : 0; + } + } + + public int LinePosition { + get { + IXmlLineInfo info = reader as IXmlLineInfo; + return (info != null) ? info.LinePosition : 0; + } + } + public override string LocalName { get { return IsDefault ? currentAttribute : reader.LocalName; } } @@ -580,10 +585,6 @@ namespace Mono.Xml } } - public ValidationEventHandler ValidationEventHandler { - get { return validationEventHandler; } - } - public override string Value { get { if (IsDefault) { diff --git a/mcs/class/System.XML/System.Xml/XmlDocument.cs b/mcs/class/System.XML/System.Xml/XmlDocument.cs index 0b275e39f6b..20fd6d7bcc7 100644 --- a/mcs/class/System.XML/System.Xml/XmlDocument.cs +++ b/mcs/class/System.XML/System.Xml/XmlDocument.cs @@ -695,8 +695,15 @@ namespace System.Xml XmlNode newNode = null; XmlNode currentNode = null; - if (reader.ReadState == ReadState.Initial) + switch (reader.ReadState) { + case ReadState.Interactive: + break; + case ReadState.Initial: reader.Read (); + break; + default: + return null; + } int startDepth = reader.Depth; bool ignoredWhitespace; @@ -704,7 +711,7 @@ namespace System.Xml do { ignoredWhitespace = false; - if (reader.NodeType == XmlNodeType.None) + if (reader.ReadState != ReadState.Interactive) if (reachedEOF) throw new Exception ("XML Reader reached to end while reading node."); else @@ -812,6 +819,7 @@ namespace System.Xml ignoredWhitespace = true; break; } + // Read next, except for reading attribute node. if (!(newNode is XmlAttribute) && !reader.Read ()) break; } while (ignoredWhitespace || reader.Depth > startDepth || diff --git a/mcs/class/System.XML/System.Xml/XmlValidatingReader.cs b/mcs/class/System.XML/System.Xml/XmlValidatingReader.cs index 45b8b4e14d3..ab34aeec63a 100644 --- a/mcs/class/System.XML/System.Xml/XmlValidatingReader.cs +++ b/mcs/class/System.XML/System.Xml/XmlValidatingReader.cs @@ -333,7 +333,7 @@ namespace System.Xml { switch (ValidationType) { case ValidationType.Auto: case ValidationType.DTD: - validatingReader = new DTDValidatingReader (sourceReader); + validatingReader = new DTDValidatingReader (sourceReader, this); break; case ValidationType.None: case ValidationType.Schema: @@ -380,6 +380,16 @@ namespace System.Xml { throw new NotImplementedException (); } + // It should be "protected" as usual "event model" + // methods are, but validation event is not exposed, + // so it is no other way to make it "internal". + internal void OnValidationEvent (object o, ValidationEventArgs e) + { + if (ValidationEventHandler != null) + ValidationEventHandler (o, e); + else + throw e.Exception; + } #endregion // Methods #region Events and Delegates |