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)
9 // Duncan Mak (duncan@ximian.com)
11 // (C) 2001 Daniel Weber
12 // (C) 2002 Kral Ferch, Jason Diamond, Miguel de Icaza, Duncan Mak
18 using System.Xml.XPath;
19 using System.Diagnostics;
23 public class XmlDocument : XmlNode
27 XmlLinkedNode lastLinkedChild;
28 XmlNameTable nameTable;
29 string baseURI = String.Empty;
35 public XmlDocument () : base (null) { }
38 protected internal XmlDocument (XmlImplementation imp) : base (null)
40 throw new NotImplementedException ();
43 public XmlDocument (XmlNameTable nt) : base (null)
52 public event XmlNodeChangedEventHandler NodeChanged;
54 public event XmlNodeChangedEventHandler NodeChanging;
56 public event XmlNodeChangedEventHandler NodeInserted;
58 public event XmlNodeChangedEventHandler NodeInserting;
60 public event XmlNodeChangedEventHandler NodeRemoved;
62 public event XmlNodeChangedEventHandler NodeRemoving;
68 public override string BaseURI {
74 public XmlElement DocumentElement {
76 XmlNode node = FirstChild;
78 while (node != null) {
79 if (node is XmlElement)
81 node = node.NextSibling;
84 return node != null ? node as XmlElement : null;
89 public virtual XmlDocumentType DocumentType {
90 get { throw new NotImplementedException(); }
94 public XmlImplementation Implementation {
95 get { throw new NotImplementedException(); }
98 [MonoTODO ("Setter.")]
99 public override string InnerXml {
101 // Not sure why this is an override. Passing through for now.
102 return base.InnerXml;
104 set { throw new NotImplementedException(); }
107 public override bool IsReadOnly {
108 get { return false; }
111 internal override XmlLinkedNode LastLinkedChild {
113 return lastLinkedChild;
117 lastLinkedChild = value;
121 public override string LocalName {
122 get { return "#document"; }
125 public override string Name {
126 get { return "#document"; }
129 public XmlNameTable NameTable {
130 get { return nameTable; }
133 public override XmlNodeType NodeType {
134 get { return XmlNodeType.Document; }
137 public override XmlDocument OwnerDocument {
142 public bool PreserveWhitespace {
143 get { throw new NotImplementedException(); }
144 set { throw new NotImplementedException(); }
148 public virtual XmlResolver XmlResolver {
149 set { throw new NotImplementedException(); }
157 public override XmlNode CloneNode (bool deep)
159 throw new NotImplementedException ();
162 public XmlAttribute CreateAttribute (string name)
164 return CreateAttribute (name, String.Empty);
167 public XmlAttribute CreateAttribute (string qualifiedName, string namespaceURI)
172 ParseName (qualifiedName, out prefix, out localName);
174 return CreateAttribute (prefix, localName, namespaceURI);
177 public virtual XmlAttribute CreateAttribute (string prefix, string localName, string namespaceURI)
179 if ((localName == null) || (localName == String.Empty))
180 throw new ArgumentException ("The attribute local name cannot be empty.");
182 return new XmlAttribute (prefix, localName, namespaceURI, this);
185 public virtual XmlCDataSection CreateCDataSection (string data)
187 return new XmlCDataSection (data, this);
190 public virtual XmlComment CreateComment (string data)
192 return new XmlComment(data, this);
196 protected internal virtual XmlAttribute CreateDefaultAttribute (string prefix, string localName, string namespaceURI)
198 throw new NotImplementedException ();
202 public virtual XmlDocumentFragment CreateDocumentFragment ()
204 throw new NotImplementedException ();
207 public virtual XmlDocumentType CreateDocumentType (string name, string publicId,
208 string systemId, string internalSubset)
210 return new XmlDocumentType (name, publicId, systemId, internalSubset, this);
213 public XmlElement CreateElement (string name)
215 return CreateElement (name, String.Empty);
218 public XmlElement CreateElement (
219 string qualifiedName,
225 ParseName (qualifiedName, out prefix, out localName);
227 return CreateElement (prefix, localName, namespaceURI);
230 public virtual XmlElement CreateElement (
235 if ((localName == null) || (localName == String.Empty))
236 throw new ArgumentException ("The local name for elements or attributes cannot be null or an empty string.");
238 return new XmlElement (prefix != null ? prefix : String.Empty, localName, namespaceURI != null ? namespaceURI : String.Empty, this);
242 public virtual XmlEntityReference CreateEntityReference (string name)
244 throw new NotImplementedException ();
247 public virtual XmlNode CreateNode (
248 string nodeTypeString,
252 return CreateNode (GetNodeTypeFromString (nodeTypeString), name, namespaceURI);
255 public virtual XmlNode CreateNode (
260 string prefix = null;
261 string localName = name;
263 if ((type == XmlNodeType.Attribute) || (type == XmlNodeType.Element) || (type == XmlNodeType.EntityReference))
264 ParseName (name, out prefix, out localName);
266 return CreateNode (type, prefix, localName, namespaceURI);
269 public virtual XmlNode CreateNode (
276 case XmlNodeType.Attribute: return CreateAttribute (prefix, name, namespaceURI);
277 case XmlNodeType.CDATA: return CreateCDataSection (null);
278 case XmlNodeType.Comment: return CreateComment (null);
279 case XmlNodeType.Document: return new XmlDocument (); // TODO - test to see which constructor to use, i.e. use existing NameTable or not.
280 case XmlNodeType.DocumentFragment: return CreateDocumentFragment ();
281 case XmlNodeType.DocumentType: return CreateDocumentType (null, null, null, null);
282 case XmlNodeType.Element: return CreateElement (prefix, name, namespaceURI);
283 case XmlNodeType.EntityReference: return CreateEntityReference (null);
284 case XmlNodeType.ProcessingInstruction: return CreateProcessingInstruction (null, null);
285 case XmlNodeType.SignificantWhitespace: return CreateSignificantWhitespace (String.Empty);
286 case XmlNodeType.Text: return CreateTextNode (null);
287 case XmlNodeType.Whitespace: return CreateWhitespace (String.Empty);
288 case XmlNodeType.XmlDeclaration: return CreateXmlDeclaration ("1.0", null, null);
289 default: throw new ArgumentOutOfRangeException(String.Format("{0}\nParameter name: {1}",
290 "Specified argument was out of the range of valid values", type.ToString ()));
294 public virtual XmlProcessingInstruction CreateProcessingInstruction (
298 return new XmlProcessingInstruction (target, data, this);
301 public virtual XmlSignificantWhitespace CreateSignificantWhitespace (string text)
303 foreach (char c in text)
304 if ((c != ' ') && (c != '\r') && (c != '\n') && (c != '\t'))
305 throw new ArgumentException ("Invalid whitespace characters.");
307 return new XmlSignificantWhitespace (text, this);
310 public virtual XmlText CreateTextNode (string text)
312 return new XmlText (text, this);
315 public virtual XmlWhitespace CreateWhitespace (string text)
317 foreach (char c in text)
318 if ((c != ' ') && (c != '\r') && (c != '\n') && (c != '\t'))
319 throw new ArgumentException ("Invalid whitespace characters.");
321 return new XmlWhitespace (text, this);
324 public virtual XmlDeclaration CreateXmlDeclaration (string version, string encoding,
327 if (version != "1.0")
328 throw new ArgumentException ("version string is not correct.");
330 if ((standalone != null) && !((standalone == "yes") || (standalone == "no")))
331 throw new ArgumentException ("standalone string is not correct.");
333 return new XmlDeclaration (version, encoding, standalone, this);
337 public virtual XmlElement GetElementById (string elementId)
339 throw new NotImplementedException ();
343 public virtual XmlNodeList GetElementsByTagName (string name)
345 throw new NotImplementedException ();
349 public virtual XmlNodeList GetElementsByTagName (string localName, string namespaceURI)
351 throw new NotImplementedException();
354 private XmlNodeType GetNodeTypeFromString (string nodeTypeString)
356 switch (nodeTypeString) {
357 case "attribute": return XmlNodeType.Attribute;
358 case "cdatasection": return XmlNodeType.CDATA;
359 case "comment": return XmlNodeType.Comment;
360 case "document": return XmlNodeType.Document;
361 case "documentfragment": return XmlNodeType.DocumentFragment;
362 case "documenttype": return XmlNodeType.DocumentType;
363 case "element": return XmlNodeType.Element;
364 case "entityreference": return XmlNodeType.EntityReference;
365 case "processinginstruction": return XmlNodeType.ProcessingInstruction;
366 case "significantwhitespace": return XmlNodeType.SignificantWhitespace;
367 case "text": return XmlNodeType.Text;
368 case "whitespace": return XmlNodeType.Whitespace;
370 throw new ArgumentException(String.Format("The string doesn't represent any node type : {0}.", nodeTypeString));
375 public virtual XmlNode ImportNode (XmlNode node, bool deep)
377 throw new NotImplementedException ();
381 public virtual void Load (Stream inStream)
383 throw new NotImplementedException ();
386 public virtual void Load (string filename)
389 XmlReader xmlReader = new XmlTextReader (new StreamReader (filename));
394 public virtual void Load (TextReader txtReader)
396 throw new NotImplementedException ();
399 public virtual void Load (XmlReader xmlReader)
401 // Reset our document
402 // For now this just means removing all our children but later this
403 // may turn out o need to call a private method that resets other things
404 // like properties we have, etc.
407 XmlNode currentNode = this;
410 while (xmlReader.Read ())
412 switch (xmlReader.NodeType) {
414 case XmlNodeType.CDATA:
415 newNode = CreateCDataSection(xmlReader.Value);
416 currentNode.AppendChild (newNode);
419 case XmlNodeType.Comment:
420 newNode = CreateComment (xmlReader.Value);
421 currentNode.AppendChild (newNode);
424 case XmlNodeType.Element:
425 XmlElement element = CreateElement (xmlReader.Prefix, xmlReader.LocalName, xmlReader.NamespaceURI);
426 currentNode.AppendChild (element);
428 // set the element's attributes.
429 while (xmlReader.MoveToNextAttribute ()) {
430 XmlAttribute attribute = CreateAttribute (xmlReader.Prefix, xmlReader.LocalName, xmlReader.NamespaceURI);
431 attribute.Value = xmlReader.Value;
432 element.SetAttributeNode (attribute);
435 xmlReader.MoveToElement ();
437 // if this element isn't empty, push it onto our "stack".
438 if (!xmlReader.IsEmptyElement)
439 currentNode = element;
443 case XmlNodeType.EndElement:
444 currentNode = currentNode.ParentNode;
447 case XmlNodeType.ProcessingInstruction:
448 newNode = CreateProcessingInstruction (xmlReader.Name, xmlReader.Value);
449 currentNode.AppendChild (newNode);
452 case XmlNodeType.Text:
453 newNode = CreateTextNode (xmlReader.Value);
454 currentNode.AppendChild (newNode);
460 public virtual void LoadXml (string xml)
462 XmlReader xmlReader = new XmlTextReader (new StringReader (xml));
466 internal void onNodeChanged (XmlNode node, XmlNode Parent)
468 if (NodeChanged != null)
469 NodeChanged (node, new XmlNodeChangedEventArgs
470 (XmlNodeChangedAction.Change,
471 node, Parent, Parent));
474 internal void onNodeChanging(XmlNode node, XmlNode Parent)
476 if (NodeChanging != null)
477 NodeChanging (node, new XmlNodeChangedEventArgs
478 (XmlNodeChangedAction.Change,
479 node, Parent, Parent));
482 internal void onNodeInserted (XmlNode node, XmlNode newParent)
484 if (NodeInserted != null)
485 NodeInserted (node, new XmlNodeChangedEventArgs
486 (XmlNodeChangedAction.Insert,
487 node, null, newParent));
490 internal void onNodeInserting (XmlNode node, XmlNode newParent)
492 if (NodeInserting != null)
493 NodeInserting (node, new XmlNodeChangedEventArgs
494 (XmlNodeChangedAction.Insert,
495 node, null, newParent));
498 internal void onNodeRemoved (XmlNode node, XmlNode oldParent)
500 if (NodeRemoved != null)
501 NodeRemoved (node, new XmlNodeChangedEventArgs
502 (XmlNodeChangedAction.Remove,
503 node, oldParent, null));
506 internal void onNodeRemoving (XmlNode node, XmlNode oldParent)
508 if (NodeRemoving != null)
509 NodeRemoving (node, new XmlNodeChangedEventArgs
510 (XmlNodeChangedAction.Remove,
511 node, oldParent, null));
514 private void ParseName (string name, out string prefix, out string localName)
516 int indexOfColon = name.IndexOf (':');
518 if (indexOfColon != -1) {
519 prefix = name.Substring (0, indexOfColon);
520 localName = name.Substring (indexOfColon + 1);
528 public virtual XmlNode ReadNode(XmlReader reader)
530 throw new NotImplementedException ();
533 [MonoTODO ("Verify what encoding is used by default; Should use PreserveWhiteSpace")]
534 public virtual void Save(Stream outStream)
536 XmlTextWriter xmlWriter = new XmlTextWriter (outStream, Encoding.UTF8);
537 WriteContentTo (xmlWriter);
541 [MonoTODO ("Verify what encoding is used by default; Should use PreseveWhiteSpace")]
542 public virtual void Save (string filename)
544 XmlTextWriter xmlWriter = new XmlTextWriter (filename, Encoding.UTF8);
545 WriteContentTo (xmlWriter);
550 public virtual void Save (TextWriter writer)
552 XmlTextWriter xmlWriter = new XmlTextWriter (writer);
553 WriteContentTo (xmlWriter);
557 [MonoTODO ("Should preserve white space if PreserveWhisspace is set")]
558 public virtual void Save (XmlWriter xmlWriter)
561 // This should preserve white space if PreserveWhiteSpace is true
563 WriteContentTo (xmlWriter);
567 public override void WriteContentTo (XmlWriter w)
569 foreach(XmlNode childNode in ChildNodes)
570 childNode.WriteTo(w);
573 public override void WriteTo (XmlWriter w)