1 // XmlAttributeTests.cs : Tests for the XmlAttribute class
3 // Author: Mike Kestner <mkestner@speakeasy.net>
4 // Author: Martin Willemoes Hansen <mwh@sysrq.dk>
6 // (C) 2002 Mike Kestner
7 // (C) 2003 Martin Willemoes Hansen
13 using NUnit
.Framework
;
15 namespace MonoTests
.System
.Xml
18 public class XmlAttributeTests
27 public void GetReady()
29 doc
= new XmlDocument ();
30 attr
= doc
.CreateAttribute ("attr1");
34 private void EventNodeInserted(Object sender
, XmlNodeChangedEventArgs e
)
39 private void EventNodeChanged(Object sender
, XmlNodeChangedEventArgs e
)
44 private void EventNodeRemoved(Object sender
, XmlNodeChangedEventArgs e
)
50 public void Attributes ()
52 Assert
.IsNull (attr
.Attributes
);
56 public void AttributeInnerAndOuterXml ()
58 attr
= doc
.CreateAttribute ("foo", "bar", "http://abc.def");
60 Assert
.AreEqual ("baz", attr
.InnerXml
, "#1");
61 Assert
.AreEqual ("foo:bar=\"baz\"", attr
.OuterXml
, "#2");
65 public void AttributeWithNoValue ()
67 XmlAttribute attribute
= doc
.CreateAttribute ("name");
68 Assert
.AreEqual (String
.Empty
, attribute
.Value
, "#1");
69 Assert
.IsFalse (attribute
.HasChildNodes
, "#2");
70 Assert
.IsNull (attribute
.FirstChild
, "#3");
71 Assert
.IsNull (attribute
.LastChild
, "#4");
72 Assert
.AreEqual (0, attribute
.ChildNodes
.Count
, "#5");
76 public void AttributeWithValue ()
78 XmlAttribute attribute
= doc
.CreateAttribute ("name");
79 attribute
.Value
= "value";
80 Assert
.AreEqual ("value", attribute
.Value
, "#1");
81 Assert
.IsTrue (attribute
.HasChildNodes
, "#2");
82 Assert
.IsNotNull (attribute
.FirstChild
, "#3");
83 Assert
.IsNotNull (attribute
.LastChild
, "#4");
84 Assert
.AreEqual (1, attribute
.ChildNodes
.Count
, "#5");
85 Assert
.AreEqual (XmlNodeType
.Text
, attribute
.ChildNodes
[0].NodeType
, "#6");
86 Assert
.AreEqual ("value", attribute
.ChildNodes
[0].Value
, "#7");
90 public void CheckPrefixWithNamespace ()
92 XmlDocument doc
= new XmlDocument ();
93 doc
.LoadXml ("<root xmlns:foo='urn:foo' foo='attfoo' foo:foo='attfoofoo' />");
94 // hogehoge does not match to any namespace.
95 Assert
.AreEqual ("xmlns:foo", doc
.DocumentElement
.Attributes
[0].Name
);
97 doc
.DocumentElement
.Attributes
[0].Prefix
= "hogehoge";
98 doc
.Save (TextWriter
.Null
);
100 } catch (ArgumentException ex
) {
101 // Cannot bind to the reserved namespace
102 Assert
.AreEqual (typeof (ArgumentException
), ex
.GetType (), "#2");
103 Assert
.IsNull (ex
.InnerException
, "#3");
104 Assert
.IsNotNull (ex
.Message
, "#4");
105 Assert
.IsNull (ex
.ParamName
, "#5");
110 public void NamespaceAttributes ()
113 doc
.CreateAttribute (string.Empty
, "xmlns", "urn:foo");
115 } catch (ArgumentException ex
) {
116 // The namespace declaration attribute has an
117 // incorrect namespaceURI: urn:foo
118 Assert
.AreEqual (typeof (ArgumentException
), ex
.GetType (), "#A2");
119 Assert
.IsNull (ex
.InnerException
, "#A3");
120 Assert
.IsNotNull (ex
.Message
, "#A4");
121 Assert
.IsNull (ex
.ParamName
, "#A5");
124 doc
.LoadXml ("<root/>");
127 doc
.DocumentElement
.SetAttribute ("xmlns", "urn:foo", "urn:bar");
129 } catch (ArgumentException ex
) {
130 // The namespace declaration attribute has an
131 // incorrect namespaceURI: urn:foo
132 Assert
.AreEqual (typeof (ArgumentException
), ex
.GetType (), "#B2");
133 Assert
.IsNull (ex
.InnerException
, "#B3");
134 Assert
.IsNotNull (ex
.Message
, "#B4");
135 Assert
.IsNull (ex
.ParamName
, "#B5");
140 public void HasChildNodes ()
142 Assert
.IsTrue (attr
.HasChildNodes
, "#1");
143 XmlAttribute attr2
= doc
.CreateAttribute ("attr2");
144 Assert
.IsFalse (attr2
.HasChildNodes
, "#2");
150 Assert
.AreEqual ("attr1", attr
.Name
);
154 public void NodeType ()
156 Assert
.AreEqual (XmlNodeType
.Attribute
, attr
.NodeType
);
160 public void OwnerDocument ()
162 Assert
.AreSame (doc
, attr
.OwnerDocument
);
166 public void ParentNode ()
168 Assert
.IsNull (attr
.ParentNode
, "Attr parents not allowed");
174 Assert
.AreEqual ("val1", attr
.Value
, "#1");
175 XmlAttribute attr2
= doc
.CreateAttribute ("attr2");
176 Assert
.AreEqual (string.Empty
, attr2
.Value
, "#2");
180 [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=336180
181 public void SetInnerTextAndXml ()
183 string original
= doc
.OuterXml
;
184 doc
.LoadXml ("<root name='value' />");
185 XmlAttribute attr
= doc
.DocumentElement
.Attributes
["name"];
186 attr
.InnerText
= "a&b";
187 Assert
.AreEqual ("a&b", attr
.Value
, "setInnerText");
188 attr
.InnerXml
= "a&b";
189 Assert
.AreEqual ("a&b", attr
.Value
, "setInnerXml");
190 attr
.InnerXml
= "'a&b'";
191 Assert
.AreEqual ("'a&b'", attr
.InnerXml
, "setInnerXml.InnerXml");
192 Assert
.AreEqual ("'a&b'", attr
.Value
, "setInnerXml.Value");
193 attr
.InnerXml
= "\"a&b\"";
194 Assert
.AreEqual ("\"a&b\"", attr
.InnerXml
, "Double_Quote");
195 attr
.InnerXml
= "\"a&b'";
196 Assert
.AreEqual ("\"a&b'", attr
.InnerXml
, "DoubleQuoteStart_SingleQuoteEnd");
198 attr
.Value
= string.Empty
;
199 XmlNodeChangedEventHandler evInserted
= new XmlNodeChangedEventHandler (EventNodeInserted
);
200 XmlNodeChangedEventHandler evChanged
= new XmlNodeChangedEventHandler (EventNodeChanged
);
201 XmlNodeChangedEventHandler evRemoved
= new XmlNodeChangedEventHandler (EventNodeRemoved
);
202 doc
.NodeInserted
+= evInserted
;
203 doc
.NodeChanged
+= evChanged
;
204 doc
.NodeRemoved
+= evRemoved
;
206 // set_InnerText event
207 attr
.InnerText
= "fire";
208 Assert
.IsFalse (inserted
, "setInnerText.NodeInserted");
209 Assert
.IsTrue (changed
, "setInnerText.NodeChanged");
210 Assert
.IsFalse (removed
, "setInnerText.NodeRemoved");
211 inserted
= changed
= removed
= false;
212 // set_InnerXml event
213 attr
.InnerXml
= "fire";
214 Assert
.IsTrue (inserted
, "setInnserXml.NodeInserted");
215 Assert
.IsFalse (changed
, "setInnserXml.NodeChanged");
216 Assert
.IsTrue (removed
, "setInnserXml.NodeRemoved");
217 inserted
= changed
= removed
= false;
219 doc
.NodeInserted
-= evInserted
;
220 doc
.NodeChanged
-= evChanged
;
221 doc
.NodeRemoved
-= evRemoved
;
225 private void OnSetInnerText (object o
, XmlNodeChangedEventArgs e
)
227 if(e
.NewParent
.Value
== "fire")
228 doc
.DocumentElement
.SetAttribute ("appended", "event was fired");
232 public void WriteTo ()
234 doc
.AppendChild (doc
.CreateElement ("root"));
235 doc
.DocumentElement
.SetAttribute ("attr", string.Empty
);
236 doc
.DocumentElement
.Attributes
["attr"].InnerXml
= "&ent;";
237 StringWriter sw
= new StringWriter ();
238 XmlTextWriter xtw
= new XmlTextWriter (sw
);
239 xtw
.WriteStartElement ("result");
240 XmlAttribute attr
= doc
.DocumentElement
.Attributes
["attr"];
243 Assert
.AreEqual ("<result attr=\"&ent;\" />", sw
.ToString ());
247 public void IdentityConstraints ()
249 string dtd
= "<!DOCTYPE root [<!ELEMENT root (c)+><!ELEMENT c EMPTY><!ATTLIST c foo ID #IMPLIED bar CDATA #IMPLIED>]>";
250 string xml
= dtd
+ "<root><c foo='id1' bar='1' /><c foo='id2' bar='2'/></root>";
251 XmlValidatingReader vr
= new XmlValidatingReader (xml
, XmlNodeType
.Document
, null);
253 Assert
.IsNotNull (doc
.GetElementById ("id1"), "#1");
254 Assert
.IsNotNull (doc
.GetElementById ("id2"), "#2");
255 // MS.NET BUG: Later I try to append it to another element, but
256 // it should raise InvalidOperationException.
257 // (and if MS.NET conform to DOM 1.0, it should be XmlException.)
258 // XmlAttribute attr = doc.DocumentElement.FirstChild.Attributes [0];
259 XmlAttribute attr
= doc
.DocumentElement
.FirstChild
.Attributes
.RemoveAt (0);
260 Assert
.AreEqual ("id1", attr
.Value
, "#3");
262 doc
.DocumentElement
.LastChild
.Attributes
.SetNamedItem (attr
);
263 Assert
.IsNotNull (doc
.GetElementById ("id1"), "#4");
264 XmlElement elem2
= doc
.GetElementById ("id2");
265 // MS.NET BUG: it doesn't remove replaced attribute with SetNamedItem!
266 // AssertNull (elem2, "#5");
267 // AssertEquals ("2", elem2.GetAttribute ("bar"), "#6");
268 // elem2.RemoveAttribute ("foo");
269 // AssertEquals (string.Empty, elem2.GetAttribute ("foo"), "#7");
271 // MS.NET BUG: elem should be the element which has the attribute bar='1'!
272 XmlElement elem
= doc
.GetElementById ("id1");
273 // AssertEquals ("2", elem.GetAttribute ("bar"), "#8");
275 // Here, required attribute foo is no more required,
276 XmlElement elemNew
= doc
.CreateElement ("c");
277 doc
.DocumentElement
.AppendChild (elemNew
);
278 // but once attribute is set, document recognizes this ID.
279 elemNew
.SetAttribute ("foo", "id3");
280 Assert
.IsNotNull (doc
.GetElementById ("id3"), "#9");
281 elemNew
.RemoveAttribute ("foo");
282 Assert
.IsNull (doc
.GetElementById ("id3"), "#10");
284 // MS.NET BUG: multiple IDs are allowed.
285 // In such case GetElementById fails.
286 elemNew
.SetAttribute ("foo", "id2");
288 // While XmlValidatingReader validated ID cannot be removed.
289 // It is too curious for me.
290 elem
.RemoveAttribute ("foo");
294 Assert
.IsNull (doc
.GetElementById ("id1"), "#11");
295 Assert
.IsNull (doc
.GetElementById ("id2"), "#12");
296 Assert
.IsNull (doc
.GetElementById ("id3"), "#13");
301 public void DefaultAttributeRemoval ()
303 XmlDocument doc
= new XmlDocument ();
304 doc
.LoadXml ("<!DOCTYPE root [<!ELEMENT root (#PCDATA)><!ATTLIST root foo CDATA 'foo-def'>]><root></root>");
305 doc
.NodeInserted
+= new XmlNodeChangedEventHandler (OnInsert
);
306 doc
.NodeChanged
+= new XmlNodeChangedEventHandler (OnChange
);
307 doc
.NodeRemoved
+= new XmlNodeChangedEventHandler (OnRemove
);
308 doc
.DocumentElement
.RemoveAll ();
311 private void OnInsert (object o
, XmlNodeChangedEventArgs e
)
313 if (removeAllStep
== 1)
314 Assert
.AreEqual (XmlNodeType
.Text
, e
.Node
.NodeType
);
315 else if (removeAllStep
== 2) {
316 Assert
.AreEqual ("foo", e
.Node
.Name
);
317 Assert
.IsFalse (((XmlAttribute
) e
.Node
).Specified
);
323 private void OnChange (object o
, XmlNodeChangedEventArgs e
)
325 Assert
.Fail ("Should not be called.");
328 private void OnRemove (object o
, XmlNodeChangedEventArgs e
)
330 Assert
.AreEqual (0, removeAllStep
, "#1");
331 Assert
.AreEqual ("foo", e
.Node
.Name
, "#2");
336 public void EmptyStringHasTextNode ()
338 doc
.LoadXml ("<root attr=''/>");
339 XmlAttribute attr
= doc
.DocumentElement
.GetAttributeNode ("attr");
340 Assert
.IsNotNull (attr
, "#1");
341 Assert
.AreEqual (1, attr
.ChildNodes
.Count
, "#2");
342 Assert
.AreEqual (XmlNodeType
.Text
, attr
.ChildNodes
[0].NodeType
, "#3");
343 Assert
.AreEqual (String
.Empty
, attr
.ChildNodes
[0].Value
, "#4");
347 public void CrazyPrefix ()
349 XmlDocument doc
= new XmlDocument ();
350 doc
.AppendChild (doc
.CreateElement ("foo"));
351 doc
.DocumentElement
.SetAttribute ("a", "urn:a", "attr");
352 XmlAttribute a
= doc
.DocumentElement
.Attributes
[0];
353 a
.Prefix
="hoge:hoge:hoge";
354 // This test is nothing more than ****.
355 Assert
.AreEqual ("hoge:hoge:hoge", a
.Prefix
);
356 // The resulting string is not XML (so broken), so
357 // it should not be tested.
358 // doc.Save (TextWriter.Null);
362 public void SetValueAndEntityRefChild ()
364 string dtd
= @"<!DOCTYPE root [
365 <!ELEMENT root EMPTY>
366 <!ATTLIST root foo CDATA #IMPLIED>
367 <!ENTITY ent 'entityyyy'>
369 string xml
= dtd
+ "<root foo='&ent;' />";
370 XmlDocument doc
= new XmlDocument ();
372 doc
.DocumentElement
.Attributes
[0].Value
= "replaced";
376 public void UpdateIDAttrValueAfterAppend ()
378 XmlDocument doc
= new XmlDocument ();
379 doc
.LoadXml ("<!DOCTYPE USS[<!ELEMENT USS EMPTY><!ATTLIST USS Id ID #REQUIRED>]><USS Id='foo'/>");
380 Assert
.IsNotNull (doc
.SelectSingleNode ("id ('foo')"), "#1");
381 doc
.DocumentElement
.Attributes
[0].Value
= "bar";
382 Assert
.IsNull (doc
.SelectSingleNode ("id ('foo')"), "#2");
383 Assert
.IsNotNull (doc
.SelectSingleNode ("id ('bar')"), "#3");
384 doc
.DocumentElement
.Attributes
[0].ChildNodes
[0].Value
= "baz";
385 // Tests below don't work fine under MS.NET
386 // Assert.IsNull (doc.SelectSingleNode ("id ('bar')"), "#4");
387 // Assert.IsNotNull (doc.SelectSingleNode ("id ('baz')"), "#5");
388 doc
.DocumentElement
.Attributes
[0].AppendChild (doc
.CreateTextNode ("baz"));
389 Assert
.IsNull (doc
.SelectSingleNode ("id ('baz')"), "#6");
390 // Assert.IsNull (doc.SelectSingleNode ("id ('bar')"), "#7");
391 // Assert.IsNotNull (doc.SelectSingleNode ("id ('bazbaz')"), "#7");
394 [Test
] // http://lists.ximian.com/pipermail/mono-list/2006-May/031557.html
395 public void NonEmptyPrefixWithEmptyNS ()
397 XmlDocument xmlDoc
= new XmlDocument ();
398 xmlDoc
.AppendChild (xmlDoc
.CreateNode (XmlNodeType
.XmlDeclaration
,
399 string.Empty
, string.Empty
));
401 XmlElement docElement
= xmlDoc
.CreateElement ("doc");
402 docElement
.SetAttribute ("xmlns", "http://whatever.org/XMLSchema/foo");
403 docElement
.SetAttribute ("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
404 docElement
.SetAttribute ("xsi:schemaLocation", "http://whatever.org/XMLSchema/foo.xsd");
405 xmlDoc
.AppendChild (docElement
);
407 XmlElement fooElement
= xmlDoc
.CreateElement ("foo");
408 docElement
.AppendChild (fooElement
);
409 xmlDoc
.Save (TextWriter
.Null
);
413 public void NullPrefix ()
415 new MyXmlAttribute ("foo", "urn:foo", new XmlDocument ());
418 class MyXmlAttribute
: XmlAttribute
420 public MyXmlAttribute (string localName
, string ns
, XmlDocument doc
)
421 : base (null, localName
, ns
, doc
)