2 // System.Xml.XmlDocument
5 // Daniel Weber (daniel-weber@austin.rr.com)
6 // Kral Ferch <kral_ferch@hotmail.com>
7 // Jason Diamond <jason@injektilo.org>
8 // Miguel de Icaza (miguel@ximian.com)
10 // (C) 2001 Daniel Weber
11 // (C) 2002 Kral Ferch, Jason Diamond, Miguel de Icaza
17 using System.Xml.XPath;
18 using System.Diagnostics;
22 public class XmlDocument : XmlNode
26 XmlLinkedNode lastLinkedChild;
27 XmlNameTable nameTable;
33 public XmlDocument () : base (null) { }
36 protected internal XmlDocument (XmlImplementation imp) : base (null)
38 throw new NotImplementedException ();
41 public XmlDocument (XmlNameTable nt) : base (null)
50 public event XmlNodeChangedEventHandler NodeChanged;
52 public event XmlNodeChangedEventHandler NodeChanging;
54 public event XmlNodeChangedEventHandler NodeInserted;
56 public event XmlNodeChangedEventHandler NodeInserting;
58 public event XmlNodeChangedEventHandler NodeRemoved;
60 public event XmlNodeChangedEventHandler NodeRemoving;
67 public override string BaseURI {
68 get { throw new NotImplementedException(); }
71 public XmlElement DocumentElement {
73 XmlNode node = FirstChild;
75 while (node != null) {
76 if (node is XmlElement)
78 node = node.NextSibling;
81 return node != null ? node as XmlElement : null;
86 public virtual XmlDocumentType DocumentType {
87 get { throw new NotImplementedException(); }
91 public XmlImplementation Implementation {
92 get { throw new NotImplementedException(); }
95 [MonoTODO ("Setter.")]
96 public override string InnerXml {
98 // Not sure why this is an override. Passing through for now.
101 set { throw new NotImplementedException(); }
104 public override bool IsReadOnly {
105 get { return false; }
108 internal override XmlLinkedNode LastLinkedChild {
110 return lastLinkedChild;
114 lastLinkedChild = value;
118 public override string LocalName {
119 get { return "#document"; }
122 public override string Name {
123 get { return "#document"; }
126 public XmlNameTable NameTable {
127 get { return nameTable; }
130 public override XmlNodeType NodeType {
131 get { return XmlNodeType.Document; }
134 public override XmlDocument OwnerDocument {
139 public bool PreserveWhitespace {
140 get { throw new NotImplementedException(); }
141 set { throw new NotImplementedException(); }
145 public virtual XmlResolver XmlResolver {
146 set { throw new NotImplementedException(); }
154 public override XmlNode CloneNode (bool deep)
156 throw new NotImplementedException ();
159 public XmlAttribute CreateAttribute (string name)
161 return CreateAttribute (name, String.Empty);
164 public XmlAttribute CreateAttribute (string qualifiedName, string namespaceURI)
169 ParseName (qualifiedName, out prefix, out localName);
171 return CreateAttribute (prefix, localName, namespaceURI);
174 public virtual XmlAttribute CreateAttribute (string prefix, string localName, string namespaceURI)
176 if ((localName == null) || (localName == String.Empty))
177 throw new ArgumentException ("The attribute local name cannot be empty.");
179 return new XmlAttribute (prefix, localName, namespaceURI, this);
182 public virtual XmlCDataSection CreateCDataSection (string data)
184 return new XmlCDataSection (data, this);
187 public virtual XmlComment CreateComment (string data)
189 return new XmlComment(data, this);
193 protected internal virtual XmlAttribute CreateDefaultAttribute (string prefix, string localName, string namespaceURI)
195 throw new NotImplementedException ();
199 public virtual XmlDocumentFragment CreateDocumentFragment ()
201 throw new NotImplementedException ();
204 public virtual XmlDocumentType CreateDocumentType (string name, string publicId,
205 string systemId, string internalSubset)
207 return new XmlDocumentType (name, publicId, systemId, internalSubset, this);
210 public XmlElement CreateElement (string name)
212 return CreateElement (name, String.Empty);
215 public XmlElement CreateElement (
216 string qualifiedName,
222 ParseName (qualifiedName, out prefix, out localName);
224 return CreateElement (prefix, localName, namespaceURI);
227 public virtual XmlElement CreateElement (
232 if ((localName == null) || (localName == String.Empty))
233 throw new ArgumentException ("The local name for elements or attributes cannot be null or an empty string.");
235 return new XmlElement (prefix, localName, namespaceURI, this);
239 public virtual XmlEntityReference CreateEntityReference (string name)
241 throw new NotImplementedException ();
245 protected internal virtual XPathNavigator CreateNavigator (XmlNode node)
247 throw new NotImplementedException ();
250 public virtual XmlNode CreateNode (
251 string nodeTypeString,
255 return CreateNode (GetNodeTypeFromString (nodeTypeString), name, namespaceURI);
258 public virtual XmlNode CreateNode (
263 string prefix = null;
264 string localName = name;
266 if ((type == XmlNodeType.Attribute) || (type == XmlNodeType.Element) || (type == XmlNodeType.EntityReference))
267 ParseName (name, out prefix, out localName);
269 return CreateNode (type, prefix, localName, namespaceURI);
272 public virtual XmlNode CreateNode (
279 case XmlNodeType.Attribute: return CreateAttribute (prefix, name, namespaceURI);
280 case XmlNodeType.CDATA: return CreateCDataSection (null);
281 case XmlNodeType.Comment: return CreateComment (null);
282 case XmlNodeType.Document: return new XmlDocument (); // TODO - test to see which constructor to use, i.e. use existing NameTable or not.
283 case XmlNodeType.DocumentFragment: return CreateDocumentFragment ();
284 case XmlNodeType.DocumentType: return CreateDocumentType (null, null, null, null);
285 case XmlNodeType.Element: return CreateElement (prefix, name, namespaceURI);
286 case XmlNodeType.EntityReference: return CreateEntityReference (null);
287 case XmlNodeType.ProcessingInstruction: return CreateProcessingInstruction (null, null);
288 case XmlNodeType.SignificantWhitespace: return CreateSignificantWhitespace (String.Empty);
289 case XmlNodeType.Text: return CreateTextNode (null);
290 case XmlNodeType.Whitespace: return CreateWhitespace (String.Empty);
291 case XmlNodeType.XmlDeclaration: return CreateXmlDeclaration ("1.0", null, null);
292 default: throw new ArgumentOutOfRangeException(String.Format("{0}\nParameter name: {1}",
293 "Specified argument was out of the range of valid values", type.ToString ()));
297 public virtual XmlProcessingInstruction CreateProcessingInstruction (
301 return new XmlProcessingInstruction (target, data, this);
304 public virtual XmlSignificantWhitespace CreateSignificantWhitespace (string text)
306 foreach (char c in text)
307 if ((c != ' ') && (c != '\r') && (c != '\n') && (c != '\t'))
308 throw new ArgumentException ("Invalid whitespace characters.");
310 return new XmlSignificantWhitespace (text, this);
313 public virtual XmlText CreateTextNode (string text)
315 return new XmlText (text, this);
318 public virtual XmlWhitespace CreateWhitespace (string text)
320 foreach (char c in text)
321 if ((c != ' ') && (c != '\r') && (c != '\n') && (c != '\t'))
322 throw new ArgumentException ("Invalid whitespace characters.");
324 return new XmlWhitespace (text, this);
327 public virtual XmlDeclaration CreateXmlDeclaration (string version, string encoding,
330 if (version != "1.0")
331 throw new ArgumentException ("version string is not correct.");
333 if ((standalone != null) && !((standalone == "yes") || (standalone == "no")))
334 throw new ArgumentException ("standalone string is not correct.");
336 return new XmlDeclaration (version, encoding, standalone, this);
340 public virtual XmlElement GetElementById (string elementId)
342 throw new NotImplementedException ();
346 public virtual XmlNodeList GetElementsByTagName (string name)
348 throw new NotImplementedException ();
352 public virtual XmlNodeList GetElementsByTagName (string localName, string namespaceURI)
354 throw new NotImplementedException();
357 private XmlNodeType GetNodeTypeFromString (string nodeTypeString)
359 switch (nodeTypeString) {
360 case "attribute": return XmlNodeType.Attribute;
361 case "cdatasection": return XmlNodeType.CDATA;
362 case "comment": return XmlNodeType.Comment;
363 case "document": return XmlNodeType.Document;
364 case "documentfragment": return XmlNodeType.DocumentFragment;
365 case "documenttype": return XmlNodeType.DocumentType;
366 case "element": return XmlNodeType.Element;
367 case "entityreference": return XmlNodeType.EntityReference;
368 case "processinginstruction": return XmlNodeType.ProcessingInstruction;
369 case "significantwhitespace": return XmlNodeType.SignificantWhitespace;
370 case "text": return XmlNodeType.Text;
371 case "whitespace": return XmlNodeType.Whitespace;
373 throw new ArgumentException(String.Format("The string doesn't represent any node type : {0}.", nodeTypeString));
378 public virtual XmlNode ImportNode (XmlNode node, bool deep)
380 throw new NotImplementedException ();
384 public virtual void Load (Stream inStream)
386 throw new NotImplementedException ();
389 public virtual void Load (string filename)
391 XmlReader xmlReader = new XmlTextReader (new StreamReader (filename));
396 public virtual void Load (TextReader txtReader)
398 throw new NotImplementedException ();
401 public virtual void Load (XmlReader xmlReader)
403 // Reset our document
404 // For now this just means removing all our children but later this
405 // may turn out o need to call a private method that resets other things
406 // like properties we have, etc.
409 XmlNode currentNode = this;
412 while (xmlReader.Read ())
414 switch (xmlReader.NodeType) {
416 case XmlNodeType.CDATA:
417 newNode = CreateCDataSection(xmlReader.Value);
418 currentNode.AppendChild (newNode);
421 case XmlNodeType.Comment:
422 newNode = CreateComment (xmlReader.Value);
423 currentNode.AppendChild (newNode);
426 case XmlNodeType.Element:
427 XmlElement element = CreateElement (xmlReader.Prefix, xmlReader.LocalName, xmlReader.NamespaceURI);
428 currentNode.AppendChild (element);
430 // set the element's attributes.
431 while (xmlReader.MoveToNextAttribute ())
432 element.SetAttribute (xmlReader.Name, xmlReader.Value);
434 xmlReader.MoveToElement ();
436 // if this element isn't empty, push it onto our "stack".
437 if (!xmlReader.IsEmptyElement)
438 currentNode = element;
442 case XmlNodeType.EndElement:
443 currentNode = currentNode.ParentNode;
446 case XmlNodeType.ProcessingInstruction:
447 newNode = CreateProcessingInstruction (xmlReader.Name, xmlReader.Value);
448 currentNode.AppendChild (newNode);
451 case XmlNodeType.Text:
452 newNode = CreateTextNode (xmlReader.Value);
453 currentNode.AppendChild (newNode);
459 public virtual void LoadXml (string xml)
461 XmlReader xmlReader = new XmlTextReader (new StringReader (xml));
465 internal void onNodeChanged (XmlNode node, XmlNode Parent)
467 if (NodeChanged != null)
468 NodeInserted (node, new XmlNodeChangedEventArgs
469 (XmlNodeChangedAction.Change,
470 node, Parent, Parent));
473 internal void onNodeChanging(XmlNode node, XmlNode Parent)
475 if (NodeInserting != null)
476 NodeChanging (node, new XmlNodeChangedEventArgs
477 (XmlNodeChangedAction.Change,
478 node, Parent, Parent));
481 internal void onNodeInserted (XmlNode node, XmlNode newParent)
483 if (NodeInserted != null)
484 NodeInserted (node, new XmlNodeChangedEventArgs
485 (XmlNodeChangedAction.Insert,
486 node, null, newParent));
489 internal void onNodeInserting (XmlNode node, XmlNode newParent)
491 if (NodeInserting != null)
492 NodeInserting (node, new XmlNodeChangedEventArgs
493 (XmlNodeChangedAction.Insert,
494 node, null, newParent));
497 internal void onNodeRemoved (XmlNode node, XmlNode oldParent)
499 if (NodeRemoved != null)
500 NodeRemoved (node, new XmlNodeChangedEventArgs
501 (XmlNodeChangedAction.Remove,
502 node, oldParent, null));
505 internal void onNodeRemoving (XmlNode node, XmlNode oldParent)
507 if (NodeRemoving != null)
508 NodeRemoving (node, new XmlNodeChangedEventArgs
509 (XmlNodeChangedAction.Remove,
510 node, oldParent, null));
513 private void ParseName (string name, out string prefix, out string localName)
515 int indexOfColon = name.IndexOf (':');
517 if (indexOfColon != -1) {
518 prefix = name.Substring (0, indexOfColon);
519 localName = name.Substring (indexOfColon + 1);
527 public virtual XmlNode ReadNode(XmlReader reader)
529 throw new NotImplementedException ();
532 [MonoTODO ("Verify what encoding is used by default; Should use PreserveWhiteSpace")]
533 public virtual void Save(Stream outStream)
535 XmlTextWriter xmlWriter = new XmlTextWriter (outStream, Encoding.UTF8);
536 WriteContentTo (xmlWriter);
540 [MonoTODO ("Verify what encoding is used by default; Should use PreseveWhiteSpace")]
541 public virtual void Save (string filename)
543 XmlTextWriter xmlWriter = new XmlTextWriter (filename, Encoding.UTF8);
544 WriteContentTo (xmlWriter);
549 public virtual void Save (TextWriter writer)
551 XmlTextWriter xmlWriter = new XmlTextWriter (writer);
552 WriteContentTo (xmlWriter);
556 [MonoTODO ("Should preserve white space if PreserveWhisspace is set")]
557 public virtual void Save (XmlWriter xmlWriter)
560 // This should preserve white space if PreserveWhiteSpace is true
562 WriteContentTo (xmlWriter);
566 public override void WriteContentTo (XmlWriter w)
568 foreach(XmlNode childNode in ChildNodes)
569 childNode.WriteTo(w);
572 public override void WriteTo (XmlWriter w)