Ver Fonte

2003-04-27 Atsushi Enomoto <[email protected]>

	* XmlAttribute.cs : fixed WriteTo() and WriteContentTo() to write
	  content EntityReference correctly.
	* XmlNodeReader.cs : many fix for EndElement handling (AttributeCount,
	  HasAttributes, indexers, MoveTo*Attribute() and Read() ).
	  Modified Skip() to call Read () explicitly.
	* XmlTextReader.cs :
	  Fixed ReadInnerXml() which ignored EndElement token in certain cases.
	  Implemented MoveToAttribute (local, ns), and modified GetAttribute()
	  in relation to this change.
	  Attributes for XmlDeclaration are now correctly set.
	* XmlTextWriter.cs : WriteRaw() is now different from WriteString().
	  Simplified WriteAttributes() for XmlDeclaration.

svn path=/trunk/mcs/; revision=14030
Atsushi Eno há 23 anos atrás
pai
commit
5ffc7747ea

+ 15 - 0
mcs/class/System.XML/System.Xml/ChangeLog

@@ -1,3 +1,18 @@
+2003-04-27  Atsushi Enomoto <[email protected]>
+
+	* XmlAttribute.cs : fixed WriteTo() and WriteContentTo() to write
+	  content EntityReference correctly.
+	* XmlNodeReader.cs : many fix for EndElement handling (AttributeCount,
+	  HasAttributes, indexers, MoveTo*Attribute() and Read() ).
+	  Modified Skip() to call Read () explicitly.
+	* XmlTextReader.cs :
+	  Fixed ReadInnerXml() which ignored EndElement token in certain cases.
+	  Implemented MoveToAttribute (local, ns), and modified GetAttribute()
+	  in relation to this change.
+	  Attributes for XmlDeclaration are now correctly set.
+	* XmlTextWriter.cs : WriteRaw() is now different from WriteString().
+	  Simplified WriteAttributes() for XmlDeclaration.
+
 2003-04-26  Atsushi Enomoto <[email protected]>
 
 	* XmlTextReader.cs : fixed ReadInnerXml(). it was inconsistent with

+ 5 - 2
mcs/class/System.XML/System.Xml/XmlAttribute.cs

@@ -224,12 +224,15 @@ namespace System.Xml
 
 		public override void WriteContentTo (XmlWriter w)
 		{
-			w.WriteString (Value);
+			foreach (XmlNode n in ChildNodes)
+				n.WriteTo (w);
 		}
 
 		public override void WriteTo (XmlWriter w)
 		{
-			w.WriteAttributeString (prefix, localName, namespaceURI, Value);
+			w.WriteStartAttribute (prefix, localName, namespaceURI);
+			WriteContentTo (w);
+			w.WriteEndAttribute ();
 		}
 
 		#endregion

+ 36 - 23
mcs/class/System.XML/System.Xml/XmlNodeReader.cs

@@ -18,8 +18,6 @@ namespace System.Xml
 {
 	public class XmlNodeReader : XmlReader
 	{
-		#region Constructor
-
 		XmlNode startNode;
 		XmlNode current;
 		ReadState state = ReadState.Initial;
@@ -30,6 +28,8 @@ namespace System.Xml
 		bool alreadyRead;
 		StringBuilder valueBuilder = new StringBuilder ();
 
+		#region Constructor
+
 		public XmlNodeReader (XmlNode node)
 		{
 			startNode = node;
@@ -44,7 +44,7 @@ namespace System.Xml
 
 		public override int AttributeCount {
 			get {
-				if (current == null || current.Attributes == null)
+				if (isEndElement || current == null || current.Attributes == null)
 					return 0;
 
 				return current.Attributes.Count;
@@ -79,7 +79,7 @@ namespace System.Xml
 
 		public override bool HasAttributes {
 			get {
-				if (current == null)
+				if (isEndElement || current == null)
 					return false;
 
 				if (current.Attributes == null ||
@@ -138,7 +138,8 @@ namespace System.Xml
 
 		public override string this [int i] {
 			get {
-				if (current == null)
+				// This is MS.NET bug which returns attributes in spite of EndElement.
+				if (isEndElement || current == null)
 					return null;
 
 				if (i < 0 || i > AttributeCount)
@@ -150,7 +151,8 @@ namespace System.Xml
 
 		public override string this [string name] {
 			get {
-				if (current == null)
+				// This is MS.NET bug which returns attributes in spite of EndElement.
+				if (isEndElement || current == null)
 					return null;
 
 				XmlAttribute attr = current.Attributes [name];
@@ -164,7 +166,8 @@ namespace System.Xml
 
 		public override string this [string name, string namespaceURI] {
 			get {
-				if (current == null)
+				// This is MS.NET bug which returns attributes in spite of EndElement.
+				if (isEndElement || current == null)
 					return null;
 
 				XmlAttribute attr = current.Attributes [name, namespaceURI];
@@ -226,8 +229,8 @@ namespace System.Xml
 		public override XmlNameTable NameTable {
 			get {
 				XmlDocument doc = 
-					current.NodeType == XmlNodeType.Document ?
-					current as XmlDocument : current.OwnerDocument;
+					startNode.NodeType == XmlNodeType.Document ?
+					startNode as XmlDocument : startNode.OwnerDocument;
 				return doc.NameTable;
 			}
 		}
@@ -315,7 +318,7 @@ namespace System.Xml
 
 		public override void MoveToAttribute (int attributeIndex)
 		{
-			if (attributeIndex < 0 || attributeIndex > AttributeCount)
+			if (isEndElement || attributeIndex < 0 || attributeIndex > AttributeCount)
 				throw new ArgumentOutOfRangeException ();
 			
 			state = ReadState.Interactive;
@@ -324,6 +327,9 @@ namespace System.Xml
 
 		public override bool MoveToAttribute (string name)
 		{
+			if (isEndElement || current == null)
+				return false;
+
 			if (GetAttribute (name) == null)
 				return false;
 			else {
@@ -334,6 +340,9 @@ namespace System.Xml
 
 		public override bool MoveToAttribute (string name, string namespaceURI)
 		{
+			if (isEndElement || current == null)
+				return false;
+
 			if (GetAttribute (name, namespaceURI) == null)
 				return false;
 			else {
@@ -342,8 +351,9 @@ namespace System.Xml
 			}
 		}
 
-		private void MoveToEndElement ()
+		private void MoveToParentElement ()
 		{
+			// This is buggy. It is not only the case when EndElement = true.
 			isEndElement = true;
 			depth--;
 			current = current.ParentNode;
@@ -396,7 +406,7 @@ namespace System.Xml
 			if (nextIsEndElement) {
 				// nextIsEndElement is set only by ReadString.
 				nextIsEndElement = false;
-				MoveToEndElement ();
+				MoveToParentElement ();
 			} else if (alreadyRead) {
 				alreadyRead = false;
 				return current != null;
@@ -405,9 +415,14 @@ namespace System.Xml
 				isEndElement = false;
 				current = current.NextSibling;
 			} else {
-				MoveToEndElement ();
+				MoveToParentElement ();
 			}
-			return current != null;
+			if (current == null) {
+				state = ReadState.EndOfFile;
+				return false;
+			}
+			else
+				return true;
 		}
 
 		[MonoTODO("Entity handling is not supported.")]
@@ -465,14 +480,14 @@ namespace System.Xml
 				return current != null;
 			}
 
-			// hmm... here may be unnecessary codes. plz check anyone ;)
 			if (!isEndElement && current.FirstChild != null) {
 				isEndElement = false;
 				current = current.FirstChild;
 				depth++;
-			} else if (depth == 0) {
-				state = ReadState.EndOfFile;
-				return false;
+			} else if (current.NodeType == XmlNodeType.Element) {
+				isEndElement = true;
+				if (current.FirstChild != null)
+					depth--;
 			} else
 				MoveToNextSibling ();
 
@@ -587,11 +602,9 @@ namespace System.Xml
 		[MonoTODO("test it.")]
 		public override void Skip ()
 		{
-			MoveToElement ();
-			if(current.ChildNodes.Count > 0)
-				MoveToNextSibling ();
-			else
-				Read ();
+			// Why is this overriden? Such skipping might raise
+			// (or ignore) unexpected validation error.
+			base.Skip ();
 		}
 		#endregion
 	}

+ 55 - 20
mcs/class/System.XML/System.Xml/XmlTextReader.cs

@@ -300,7 +300,6 @@ namespace System.Xml
 
 		#region Methods
 
-		[MonoTODO]
 		public override void Close ()
 		{
 			readState = ReadState.Closed;
@@ -323,11 +322,11 @@ namespace System.Xml
 				UnescapeAttributeValue (attributes [name] as string) : String.Empty;
 		}
 
-		public override string GetAttribute (string localName, string namespaceURI)
+		private int GetIndexOfQualifiedAttribute (string localName, string namespaceURI)
 		{
-			foreach (DictionaryEntry entry in attributes)
+			for(int i = 0; i < orderedAttributes.Count; i++)
 			{
-				string thisName = entry.Key as string;
+				string thisName = (string) orderedAttributes [i];
 
 				int indexOfColon = thisName.IndexOf (':');
 
@@ -339,15 +338,20 @@ namespace System.Xml
 						string thisNamespaceURI = LookupNamespace (thisPrefix);
 
 						if (namespaceURI == thisNamespaceURI)
-							return attributes.ContainsKey (thisName) ?
-								UnescapeAttributeValue (attributes [thisName] as string) : String.Empty;
+							return i;
 					}
 				} else if (localName == "xmlns" && namespaceURI == "http://www.w3.org/2000/xmlns/" && thisName == "xmlns")
-					return attributes.ContainsKey (thisName) ? 
-						UnescapeAttributeValue (attributes [thisName] as string) : String.Empty;
+					return i;
 			}
+			return -1;
+		}
 
-			return String.Empty;
+		public override string GetAttribute (string localName, string namespaceURI)
+		{
+			int idx = this.GetIndexOfQualifiedAttribute (localName, namespaceURI);
+			if (idx < 0)
+				return String.Empty;
+			return UnescapeAttributeValue (attributes [orderedAttributes [idx]] as string);
 		}
 
 		[MonoTODO]
@@ -420,10 +424,18 @@ namespace System.Xml
 			return match;
 		}
 
-		[MonoTODO]
 		public override bool MoveToAttribute (string localName, string namespaceName)
 		{
-			throw new NotImplementedException ();
+			MoveToElement ();
+
+			if (attributes == null)
+				return false;
+
+			int idx = GetIndexOfQualifiedAttribute (localName, namespaceName);
+			if (idx < 0)
+				return false;
+			MoveToAttribute (idx);
+			return true;
 		}
 
 		public override bool MoveToElement ()
@@ -608,10 +620,9 @@ namespace System.Xml
 					Read ();
 					if (NodeType ==XmlNodeType.None)
 						throw new XmlException ("unexpected end of xml.");
-					else if (NodeType == XmlNodeType.EndElement) {
-						if (depth == startDepth)
+					else if (NodeType == XmlNodeType.EndElement && depth == startDepth)
 							loop = false;
-					} else
+					else
 						innerXmlBuilder.Append (currentTag);
 				} while (loop);
 				string xml = innerXmlBuilder.ToString ();
@@ -1059,7 +1070,7 @@ namespace System.Xml
 			ClearAttributes ();
 
 			if (XmlConstructs.IsNameStart (PeekChar ()))
-				ReadAttributes ();
+				ReadAttributes (false);
 
 			if (PeekChar () == '/') {
 				ReadChar ();
@@ -1297,8 +1308,9 @@ namespace System.Xml
 
 		// The reader is positioned on the first character of
 		// the attribute name.
-		private void ReadAttributes ()
+		private void ReadAttributes (bool allowPIEnd)
 		{
+			int peekChar = -1;
 			do {
 				string name = ReadName ();
 				SkipWhitespace ();
@@ -1313,7 +1325,10 @@ namespace System.Xml
 					parserContext.NamespaceManager.AddNamespace (name.Substring (6), UnescapeAttributeValue (value));
 
 				AddAttribute (name, value);
-			} while (PeekChar () != '/' && PeekChar () != '>' && PeekChar () != -1);
+				peekChar = PeekChar ();
+				if (peekChar == '?' && allowPIEnd)
+					break;
+			} while (peekChar != '/' && peekChar != '>' && peekChar != -1);
 		}
 
 		// The reader is positioned on the quote character.
@@ -1353,11 +1368,15 @@ namespace System.Xml
 		// The reader is positioned on the first character
 		// of the target.
 		//
-		// Now it also reads XmlDeclaration, this method name became improper...
+		// It may be xml declaration or processing instruction.
 		private void ReadProcessingInstruction ()
 		{
 			string target = ReadName ();
 			SkipWhitespace ();
+			if (target == "xml") {
+				ReadXmlDeclaration ();
+				return;
+			}
 
 			valueLength = 0;
 
@@ -1373,8 +1392,6 @@ namespace System.Xml
 			}
 
 			SetProperties (
-				target == "xml" ?
-				XmlNodeType.XmlDeclaration :
 				XmlNodeType.ProcessingInstruction, // nodeType
 				target, // name
 				false, // isEmptyElement
@@ -1383,6 +1400,24 @@ namespace System.Xml
 			);
 		}
 
+		// The reader is positioned after "<?xml "
+		private void ReadXmlDeclaration ()
+		{
+			ClearAttributes ();
+
+			if (XmlConstructs.IsNameStart (PeekChar ()))
+				ReadAttributes (true);
+			Expect ("?>");
+
+			SetProperties (
+				XmlNodeType.XmlDeclaration, // nodeType
+				"xml", // name
+				false, // isEmptyElement
+				currentInput.CurrentMarkup.ToString (6, currentInput.CurrentMarkup.Length - 6), // value
+				false // clearAttributes
+			);
+		}
+
 		// The reader is positioned on the first character after
 		// the leading '<!'.
 		private void ReadDeclaration ()

+ 13 - 3
mcs/class/System.XML/System.Xml/XmlTextWriter.cs

@@ -501,14 +501,24 @@ namespace System.Xml
 		}
 		public override void WriteRaw (string data)
 		{
+//			WriteRawInternal (data);
 			WriteStringInternal (data, false);
 		}
 
 		public override void WriteRaw (char[] buffer, int index, int count)
 		{
+//			WriteRawInternal (new string (buffer, index, count));
 			WriteStringInternal (new string (buffer, index, count), false);
 		}
 
+		private void WriteRawInternal (string text)
+		{
+			if (text == null)
+				return;
+
+			w.Write (text);
+		}
+
 		public override void WriteStartAttribute (string prefix, string localName, string ns)
 		{
 			if ((prefix == "xml") && (localName == "lang"))
@@ -601,7 +611,7 @@ namespace System.Xml
 
 			string encodingFormatting = "";
 
-			if (!nullEncoding && w.Encoding.WebName != "utf-16" && w.Encoding.WebName != "utf-8") 
+			if (!nullEncoding) 
 				encodingFormatting = String.Format (" encoding={0}{1}{0}", quoteChar, w.Encoding.WebName);
 
 			w.Write("<?xml version={0}1.0{0}{1}{2}?>", quoteChar, encodingFormatting, standaloneFormatting);
@@ -665,8 +675,7 @@ namespace System.Xml
 			if (text == null)
 				text = String.Empty;
 
-			if (text != String.Empty) 
-			{
+			if (text != String.Empty) {
 				CheckState ();
 
 				if (entitize)
@@ -689,6 +698,7 @@ namespace System.Xml
 					IndentingOverriden = true;
 					CloseStartElement ();
 				}
+
 				if (!openXmlLang && !openXmlSpace)
 					w.Write (text);
 				else