Explorar el Código

2003-06-30 Atsushi Enomoto <[email protected]>

	* XmlDocumentNavigator.cs : Implemented MoveTo*Namespace() and
	  essentially changed most of the property handling (e.g. removed attribute
	  enumerator and it now became really cloneable).
	* XmlNodeReader.cs : ReadInnerXml() changes its state as error
	  when the method is called at Initial state.

svn path=/trunk/mcs/; revision=15773
Atsushi Eno hace 22 años
padre
commit
60ce78b476

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

@@ -1,3 +1,11 @@
+2003-06-30  Atsushi Enomoto <[email protected]>
+
+	* XmlDocumentNavigator.cs : Implemented MoveTo*Namespace() and 
+	  essentially changed most of the property handling (e.g. removed attribute 
+	  enumerator and it now became really cloneable).
+	* XmlNodeReader.cs : ReadInnerXml() changes its state as error
+	  when the method is called at Initial state.
+
 2003-06-25  Atsushi Enomoto <[email protected]>
 
 	* XmlDocumentNavigator.cs : Fixed IsEmptyElement. It treats <foo></foo>

+ 215 - 64
mcs/class/System.XML/System.Xml/XmlDocumentNavigator.cs

@@ -1,39 +1,44 @@
 //
 // System.Xml.XmlDocumentNavigator
 //
-// Author:
+// Authors:
 //   Jason Diamond <[email protected]>
+//   Atsushi Enomoto <[email protected]>
 //
 // (C) 2002 Jason Diamond
+// (C) 2003 Atsushi Enomoto
 //
-
-using System;
-using System.Collections;
-using System.Xml;
-using System.Xml.XPath;
-
-namespace System.Xml
-{
-	internal class XmlDocumentNavigator : XPathNavigator, IHasXmlNode
-	{
-		#region Constructors
-
-		internal XmlDocumentNavigator(XmlNode node)
-		{
-			this.node = node;
-			this.document = node.NodeType == XmlNodeType.Document ?
-				node as XmlDocument : node.OwnerDocument;
-		}
-
-		#endregion
-
-		#region Fields
-
-		private XmlNode node;
-		private XmlDocument document;
-		private IEnumerator attributesEnumerator;
-
-		#endregion
+
+using System;
+using System.Collections;
+using System.Xml;
+using System.Xml.XPath;
+
+namespace System.Xml
+{
+	internal class XmlDocumentNavigator : XPathNavigator, IHasXmlNode
+	{
+		#region Constructors
+
+		internal XmlDocumentNavigator(XmlNode node)
+		{
+			this.node = node;
+			this.document = node.NodeType == XmlNodeType.Document ?
+				node as XmlDocument : node.OwnerDocument;
+		}
+
+		#endregion
+
+		#region Fields
+		private const string Xmlns = "http://www.w3.org/2000/xmlns/";
+		private const string XmlnsXML = "http://www.w3.org/XML/1998/namespace";
+
+		private XmlNode node;
+		private XmlDocument document;
+		// Current namespace node (ancestor's attribute of current node).
+		private XmlNode nsNode;
+
+		#endregion
 
 		#region Properties
 
@@ -45,9 +50,12 @@ namespace System.Xml
 
 		public override bool HasAttributes {
 			get {
+				if (nsNode != null)
+					return false;
+
 				if (node.Attributes != null)
 					foreach (XmlAttribute attribute in node.Attributes)
-						if (attribute.NamespaceURI != "http://www.w3.org/2000/xmlns/")
+						if (attribute.NamespaceURI != Xmlns)
 							return true;
 				return false;
 			}
@@ -55,6 +63,9 @@ namespace System.Xml
 
 		public override bool HasChildren {
 			get {
+				if (nsNode != null)
+					return false;
+
 				XPathNodeType nodeType = NodeType;
 				bool canHaveChildren = nodeType == XPathNodeType.Root || nodeType == XPathNodeType.Element;
 				return canHaveChildren && node.FirstChild != null;
@@ -63,6 +74,9 @@ namespace System.Xml
 
 		public override bool IsEmptyElement {
 			get {
+				if (nsNode != null)
+					return false;
+
 				return node.NodeType == XmlNodeType.Element 
 					&& ((XmlElement) node).IsEmpty;
 			}
@@ -70,6 +84,13 @@ namespace System.Xml
 
 		public override string LocalName {
 			get {
+				if (nsNode != null) {
+					if (nsNode == document)
+						return "xml";
+					else
+						return (nsNode.Name == "xmlns") ? String.Empty : nsNode.LocalName;
+				}
+
 				XPathNodeType nodeType = NodeType;
 				bool canHaveName = 
 					nodeType == XPathNodeType.Element || 
@@ -82,6 +103,9 @@ namespace System.Xml
 
 		public override string Name {
 			get {
+				if (nsNode != null)
+					return LocalName;
+
 				XPathNodeType nodeType = NodeType;
 				bool canHaveName = 
 					nodeType == XPathNodeType.Element || 
@@ -93,9 +117,7 @@ namespace System.Xml
 		}
 
 		public override string NamespaceURI {
-			get {
-				return node.NamespaceURI;
-			}
+			get { return (nsNode != null) ? String.Empty : node.NamespaceURI; }
 		}
 
 		public override XmlNameTable NameTable {
@@ -105,15 +127,11 @@ namespace System.Xml
 		}
 
 		public override XPathNodeType NodeType {
-			get {
-				return node.XPathNodeType;
-			}
+			get { return (nsNode != null) ? XPathNodeType.Namespace : node.XPathNodeType; }
 		}
 
 		public override string Prefix {
-			get {
-				return node.Prefix;
-			}
+			get { return (nsNode != null) ? String.Empty : node.Prefix; }
 		}
 
 		public override string Value {
@@ -129,6 +147,8 @@ namespace System.Xml
 				case XPathNodeType.Element:
 				case XPathNodeType.Root:
 					return node.InnerText;
+				case XPathNodeType.Namespace:
+					return nsNode == document ? XmlnsXML : nsNode.Value;
 				}
 				return String.Empty;
 			}
@@ -146,13 +166,18 @@ namespace System.Xml
 
 		public override XPathNavigator Clone ()
 		{
-			return new XmlDocumentNavigator (node);
+			XmlDocumentNavigator clone = new XmlDocumentNavigator (node);
+			clone.nsNode = nsNode;
+			return clone;
 		}
 
 		public override string GetAttribute (string localName, string namespaceURI)
 		{
-			XmlElement el = Node as XmlElement;
-			return el != null ? el.GetAttribute (localName, namespaceURI) : String.Empty;
+			if (HasAttributes) {
+				XmlElement el = Node as XmlElement;
+				return el != null ? el.GetAttribute (localName, namespaceURI) : String.Empty;
+			}
+			return String.Empty;
 		}
 
 		public override string GetNamespace (string name)
@@ -168,7 +193,8 @@ namespace System.Xml
 		{
 			XmlDocumentNavigator otherDocumentNavigator = other as XmlDocumentNavigator;
 			if (otherDocumentNavigator != null)
-				return node == otherDocumentNavigator.node;
+				return node == otherDocumentNavigator.node
+					&& nsNode == otherDocumentNavigator.nsNode;
 			return false;
 		}
 
@@ -178,6 +204,7 @@ namespace System.Xml
 			if (otherDocumentNavigator != null) {
 				if (document == otherDocumentNavigator.document) {
 					node = otherDocumentNavigator.node;
+					nsNode = otherDocumentNavigator.nsNode;
 					return true;
 				}
 			}
@@ -186,12 +213,14 @@ namespace System.Xml
 
 		public override bool MoveToAttribute (string localName, string namespaceURI)
 		{
-			attributesEnumerator = node.Attributes.GetEnumerator ();
-			while (attributesEnumerator.MoveNext ()) {
-				XmlAttribute attr = attributesEnumerator.Current as XmlAttribute;
-				if (attr.LocalName == localName && attr.NamespaceURI == namespaceURI) {
-					node = attr;
-					return true;
+			if (node.Attributes != null) {
+				foreach (XmlAttribute attr in node.Attributes) {
+					if (attr.LocalName == localName
+						&& attr.NamespaceURI == namespaceURI) {
+						node = attr;
+						nsNode = null;
+						return true;
+					}
 				}
 			}
 			return false;
@@ -199,7 +228,7 @@ namespace System.Xml
 
 		public override bool MoveToFirst ()
 		{
-			if (node.NodeType != XmlNodeType.Attribute && node.ParentNode != null) {
+			if (nsNode == null && node.NodeType != XmlNodeType.Attribute && node.ParentNode != null) {
 				MoveToParent ();
 				// Follow these 2 steps so that we can skip 
 				// some types of nodes .
@@ -211,9 +240,16 @@ namespace System.Xml
 
 		public override bool MoveToFirstAttribute ()
 		{
+			if (node.Attributes == null)
+				return false;
 			if (NodeType == XPathNodeType.Element) {
-				attributesEnumerator = node.Attributes.GetEnumerator ();
-				return MoveToNextAttribute ();
+				foreach (XmlAttribute attr in node.Attributes) {
+					if (attr.NamespaceURI != Xmlns) {
+						node = attr;
+						nsNode = null;
+						return true;
+					}
+				}
 			}
 			return false;
 		}
@@ -248,10 +284,32 @@ namespace System.Xml
 			return false;
 		}
 
-		[MonoTODO]
 		public override bool MoveToFirstNamespace (XPathNamespaceScope namespaceScope)
 		{
-			throw new NotImplementedException ();
+			if (NodeType != XPathNodeType.Element)
+				return false;
+
+			XmlElement el = node as XmlElement;
+			if (node.Attributes != null) {
+				do {
+					foreach (XmlAttribute attr in el.Attributes) {
+						if (attr.NamespaceURI == Xmlns) {
+							nsNode = attr;
+							return true;
+						}
+					}
+					if (namespaceScope == XPathNamespaceScope.Local)
+						return false;
+					el = node.ParentNode as XmlElement;
+				} while (el != null);
+			}
+
+			if (namespaceScope == XPathNamespaceScope.All) {
+				nsNode = document;
+				return true;
+			}
+			else
+				return false;
 		}
 
 		public override bool MoveToId (string id)
@@ -264,14 +322,36 @@ namespace System.Xml
 			return true;
 		}
 
-		[MonoTODO]
 		public override bool MoveToNamespace (string name)
 		{
-			throw new NotImplementedException ();
+			if (name == "xml") {
+				nsNode = document;
+				return true;
+			}
+
+			if (NodeType != XPathNodeType.Element)
+				return false;
+
+			XmlElement el = node as XmlElement;
+			if (node.Attributes != null) {
+				do {
+					foreach (XmlAttribute attr in el.Attributes) {
+						if (attr.NamespaceURI == Xmlns && Name == name) {
+							nsNode = attr;
+							return true;
+						}
+					}
+					el = node.ParentNode as XmlElement;
+				} while (el != null);
+			}
+			return false;
 		}
 
 		public override bool MoveToNext ()
 		{
+			if (nsNode != null)
+				return false;
+
 			if (node.NextSibling != null) {
 				if (node.ParentNode != null && node.ParentNode.NodeType == XmlNodeType.Document) {
 					XmlNode n = node.NextSibling;
@@ -299,29 +379,96 @@ namespace System.Xml
 
 		public override bool MoveToNextAttribute ()
 		{
-			if (attributesEnumerator != null && attributesEnumerator.MoveNext ()) {
-				node = attributesEnumerator.Current as XmlAttribute;
-				return true;
+			if (NodeType != XPathNodeType.Attribute)
+				return false;
+
+			// Find current attribute.
+			int pos = 0;
+			XmlElement owner = ((XmlAttribute) node).OwnerElement;
+			int count = owner.Attributes.Count;
+			for(; pos < count; pos++)
+				if (owner.Attributes [pos] == node)
+					break;
+			if (pos == count)
+				return false;	// Where is current attribute? Maybe removed.
+
+			// Find next attribute.
+			for(pos++; pos < count; pos++) {
+				if (owner.Attributes [pos].NamespaceURI != Xmlns) {
+					node = owner.Attributes [pos];
+					nsNode = null;
+					return true;
+				}
 			}
 			return false;
 		}
 
-		[MonoTODO]
 		public override bool MoveToNextNamespace (XPathNamespaceScope namespaceScope)
 		{
-			throw new NotImplementedException ();
+			if (nsNode == document)
+				// Current namespace is "xml", so there should be no more namespace nodes.
+				return false;
+
+			if (nsNode == null)
+				return false;
+
+			// Get current attribute's position.
+			int pos = 0;
+			XmlElement owner = ((XmlAttribute) nsNode).OwnerElement;
+			int count = owner.Attributes.Count;
+			for(; pos < count; pos++)
+				if (owner.Attributes [pos] == nsNode)
+					break;
+			if (pos == count)
+				return false;	// Where is current attribute? Maybe removed.
+
+			// Find next namespace from the same element as current ns node.
+			for(pos++; pos < count; pos++) {
+				if (owner.Attributes [pos].NamespaceURI == Xmlns) {
+					nsNode = owner.Attributes [pos];
+					return true;
+				}
+			}
+
+			// If not found more, then find from ancestors.
+			// But if scope is Local, then it returns false here.
+			if (namespaceScope == XPathNamespaceScope.Local)
+				return false;
+			owner = owner.ParentNode as XmlElement;
+			while (owner != null) {
+				foreach (XmlAttribute attr in owner.Attributes) {
+					if (attr.NamespaceURI == Xmlns) {
+						nsNode = attr;
+						return true;
+					}
+				}
+				owner = owner.ParentNode as XmlElement;
+			}
+
+			if (namespaceScope == XPathNamespaceScope.All) {
+				nsNode = document;
+				return true;
+			}
+			else
+				return false;
 		}
 
 		public override bool MoveToParent ()
 		{
-			if (node.NodeType == XmlNodeType.Attribute) {
+			if (nsNode != null) {
+				nsNode = null;
+				return true;
+			}
+			else if (node.NodeType == XmlNodeType.Attribute) {
 				XmlElement ownerElement = ((XmlAttribute)node).OwnerElement;
 				if (ownerElement != null) {
 					node = ownerElement;
+					nsNode = null;
 					return true;
 				}
 			} else if (node.ParentNode != null) {
 				node = node.ParentNode;
+				nsNode = null;
 				return true;
 			}
 			return false;
@@ -329,6 +476,9 @@ namespace System.Xml
 
 		public override bool MoveToPrevious ()
 		{
+			if (nsNode != null)
+				return false;
+
 			if (node.PreviousSibling != null) {
 				node = node.PreviousSibling;
 				return true;
@@ -339,6 +489,7 @@ namespace System.Xml
 		public override void MoveToRoot ()
 		{
 			node = document;
+			nsNode = null;
 		}
 
 		internal XmlNode Node { get { return node; } }
@@ -349,5 +500,5 @@ namespace System.Xml
                 }
 
 		#endregion
-	}
-}
+	}
+}

+ 5 - 0
mcs/class/System.XML/System.Xml/XmlNodeReader.cs

@@ -592,6 +592,11 @@ namespace System.Xml
 		// Its traversal behavior is almost same as Read().
 		public override string ReadInnerXml ()
 		{
+			if (this.state != ReadState.Interactive) {
+				state = ReadState.Error;
+				return String.Empty;
+			}
+
 			XmlNode initial = current;
 			// Almost copied from XmlTextReader.
 			switch (NodeType) {