Browse Source

2005-03-24 Atsushi Enomoto <[email protected]>

	* XmlWriter.cs : WriteQualifiedName() should check namespace validity
	  (whether it is in scope or not).
	* XmlTextWriter.cs : When WriteQualifiedName() is invoked inside
	  attribute and no matching namespace declaration, create prefix
	  on demand. Code reused from WriteStartAttribute().

	* XmlTextWriterTests.cs : added more tests on WriteQualifiedName().


svn path=/trunk/mcs/; revision=42189
Atsushi Eno 21 years ago
parent
commit
c8d5ac5a2d

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

@@ -1,3 +1,11 @@
+2005-03-24  Atsushi Enomoto <[email protected]>
+
+	* XmlWriter.cs : WriteQualifiedName() should check namespace validity
+	  (whether it is in scope or not).
+	* XmlTextWriter.cs : When WriteQualifiedName() is invoked inside
+	  attribute and no matching namespace declaration, create prefix
+	  on demand. Code reused from WriteStartAttribute().
+
 2005-03-22  Atsushi Enomoto <[email protected]>
 
 	* XmlValidatingReader.cs : create schema set on demand.

+ 33 - 11
mcs/class/System.XML/System.Xml/XmlTextWriter.cs

@@ -703,11 +703,27 @@ openElements [openElementCount - 1]).IndentingOverriden;
 
 		public override void WriteQualifiedName (string localName, string ns)
 		{
+			if (!XmlChar.IsNCName (localName))
+				throw new ArgumentException (String.Format ("Invalid local name '{0}'", localName));
+
 			CheckState ();
 			if (!openAttribute)
 				CloseStartElement ();
 
+			// WriteQualifiedName internal will reject such
+			// qname whose namespace is not declared.
+			string prefix = null;
+			if (openAttribute && LookupPrefix (ns) == null) {
+				prefix = CheckNewPrefix (true, null, ns);
+				namespaceManager.AddNamespace (prefix, ns);
+			}
+
 			WriteQualifiedNameInternal (localName, ns);
+
+			if (prefix != null) {
+				namespaceManager.RemoveNamespace (prefix, ns);
+				newAttributeNamespaces [prefix] = ns;
+			}
 		}
 
 		public override void WriteRaw (string data)
@@ -786,17 +802,7 @@ openElements [openElementCount - 1]).IndentingOverriden;
 						}
 					}
 
-			do {
-					if (createPrefix)
-						prefix = "d" + indentLevel + "p" + (++autoCreatedPrefixes);
-					createPrefix = false;
-					// check if prefix exists. If yes - check if namespace is the same.
-					if (newAttributeNamespaces [prefix] == null)
-						newAttributeNamespaces.Add (prefix, ns);
-					else if (!newAttributeNamespaces [prefix].Equals (ns))
-//						throw new ArgumentException ("Duplicate prefix with different namespace");
-						createPrefix = true;
-			} while (createPrefix);
+					prefix = CheckNewPrefix (createPrefix, prefix, ns);
 				}
 
 				if (prefix == String.Empty && ns != XmlnsNamespace)
@@ -834,6 +840,22 @@ openElements [openElementCount - 1]).IndentingOverriden;
 			}
 		}
 
+		private string CheckNewPrefix (bool createPrefix, string prefix, string ns)
+		{
+			do {
+				if (createPrefix)
+					prefix = "d" + indentLevel + "p" + (++autoCreatedPrefixes);
+				createPrefix = false;
+				// Check if prefix exists.
+				// If yes - check if namespace is the same.
+				if (newAttributeNamespaces [prefix] == null)
+					newAttributeNamespaces.Add (prefix, ns);
+				else if (!newAttributeNamespaces [prefix].Equals (ns))
+					createPrefix = true;
+			} while (createPrefix);
+			return prefix;
+		}
+
 		public override void WriteStartDocument ()
 		{
 			WriteStartDocument ("");

+ 3 - 0
mcs/class/System.XML/System.Xml/XmlWriter.cs

@@ -378,6 +378,9 @@ namespace System.Xml
 #endif
 
 			string prefix = ns.Length > 0 ? LookupPrefix (ns) : String.Empty;
+			if (prefix == null)
+				throw new ArgumentException (String.Format ("Namespace '{0}' is not declared.", ns));
+
 			if (prefix != String.Empty) {
 				WriteString (prefix);
 				WriteString (":");

+ 4 - 0
mcs/class/System.XML/Test/System.Xml/ChangeLog

@@ -1,3 +1,7 @@
+2005-03-24  Atsushi Enomoto <[email protected]>
+
+	* XmlTextWriterTests.cs : added more tests on WriteQualifiedName().
+
 2005-03-15  Atsushi Enomoto <[email protected]>
 
 	* XmlValidatingReaderTests.cs : Added test for sequential text nodes

+ 36 - 0
mcs/class/System.XML/Test/System.Xml/XmlTextWriterTests.cs

@@ -788,6 +788,42 @@ namespace MonoTests.System.Xml
 			AssertEquals ("<test xmlns:me='http://localhost/'>me:bob</test>", StringWriterText);
 		}
 
+		[Test]
+		public void WriteQualifiedNameNonDeclaredAttribute ()
+		{
+			xtw.WriteStartElement ("foo");
+			xtw.WriteStartAttribute ("a", "");
+			xtw.WriteQualifiedName ("attr", "urn:a");
+			xtw.WriteWhitespace (" ");
+			xtw.WriteQualifiedName ("attr", "urn:b");
+			xtw.WriteEndAttribute ();
+			xtw.WriteEndElement ();
+			string xml = sw.ToString ();
+			Assert ("foo", xml.IndexOf ("<foo ") >= 0);
+			Assert ("qnames", xml.IndexOf ("a='d1p1:attr d1p2:attr'") > 0);
+			Assert ("xmlns:a", xml.IndexOf (" xmlns:d1p1='urn:a'") > 0);
+			Assert ("xmlns:b", xml.IndexOf (" xmlns:d1p2='urn:b'") > 0);
+		}
+
+		[Test]
+		[ExpectedException (typeof (ArgumentException))]
+		public void WriteQualifiedNameNonDeclaredContent ()
+		{
+			xtw.WriteStartElement ("foo");
+			xtw.WriteQualifiedName ("abc", "urn:abc");
+		}
+
+		[Test]
+		[ExpectedException (typeof (ArgumentException))]
+		public void WriteQualifiedNameNonNCName ()
+		{
+			xtw.WriteStartElement ("foo");
+			xtw.WriteAttributeString ("xmlns", "urn:default");
+			xtw.WriteStartElement ("child");
+			xtw.WriteStartAttribute ("a", "");
+			xtw.WriteQualifiedName ("x:def", "urn:def");
+		}
+
 		[Test]
 		public void WriteRaw ()
 		{