| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751 |
- // -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- //
- // System.Xml.XmlNode
- //
- // Author:
- // Daniel Weber ([email protected])
- //
- // (C) 2001 Daniel Weber
- using System;
- using System.Collections;
- using System.Xml.XPath;
- namespace System.Xml
- {
- public abstract class XmlNode : ICloneable, IEnumerable, IXPathNavigable
- {
- //======= Private data members ==============================================
- private XmlNodeListAsArrayList _childNodes;
- protected XmlDocument FOwnerDocument;
- protected XmlNode _parent;
- // Names of node
- // for <foo:bar xmlns:foo="http://www.foobar.com/schema/foobar">... </foo:bar>
- // qualified name: foo:bar
- // namespaceURI = "http://www.foobar.com/schema/foobar"
- // localName = bar
- // prefix = foo
- // Note that namespaces can be nested (child namespace != parent namespace)
- // namespaces are optional
- protected string Fname;
- protected string FnamespaceURI;
- protected string Fprefix;
- protected string FlocalName;
- // baseURI holds the location from which the document was loaded
- // If the node was created from a document at c:\tmp.xml, then that's what will be here
- protected string FbaseURI;
- // value of the node (overriden in classes that do something different)
- // default behavior is just to store it
- protected string Fvalue;
-
- //=====================================================================
- // ============ Properties ============================================
- //=====================================================================
- /// <summary>
- /// Get the XmlAttributeCollection representing the attributes
- /// on the node type. Returns null if the node type is not XmlElement.
- /// </summary>
- public virtual XmlAttributeCollection Attributes
- {
- get
- {
- return null;
- }
- }
- /// <summary>
- /// Return the base Uniform Resource Indicator (URI) used to resolve
- /// this node, or String.Empty.
- /// </summary>
- public virtual string BaseURI
- {
- get
- {
- return FbaseURI;
- }
- }
- /// <summary>
- /// Return all child nodes of this node. If there are no children,
- /// return an empty XmlNodeList;
- /// </summary>
- public virtual XmlNodeList ChildNodes
- {
- get
- {
- if (_childNodes == null)
- _childNodes = new XmlNodeListAsArrayList();
- return _childNodes as XmlNodeList;
- }
- }
-
- /// <summary>
- /// Return first child node as XmlNode or null
- /// if the node has no children
- /// </summary>
- public virtual XmlNode FirstChild
- {
- get
- {
- if (ChildNodes.Count == 0)
- return null;
- else
- return ChildNodes[0];
- }
- }
- /// <summary>
- /// Return true if the node has children
- /// </summary>
- public virtual bool HasChildNodes
- {
- get
- {
- if (ChildNodes.Count == 0)
- return true;
- else
- return false;
- }
- }
- /// <summary>
- /// Get or Set the concatenated values of node and children
- /// </summary>
- public virtual string InnerText
- {
- get
- {
- // TODO - implement set InnerText()
- throw new NotImplementedException();
- }
- set
- {
- // TODO - implement set InnerText()
- throw new NotImplementedException();
- }
- }
- /// <summary>
- /// Get/Set the XML representing just the child nodes of this node
- /// </summary>
- public virtual string InnerXml
- {
- get
- {
- // TODO - implement set InnerXml()
- throw new NotImplementedException();
- }
- set
- {
- // TODO - implement set InnerXml()
- throw new NotImplementedException();
- }
- }
- /// <summary>
- /// Property Get - true if node is read-only
- /// </summary>
- public virtual bool IsReadOnly
- {
- get
- {
- return OwnerDocument.IsReadOnly;
- }
- }
- /// <summary>
- /// Return the child element named [string]. Returns XmlElement
- /// Indexer for XmlNode class.
- /// </summary>
- [System.Runtime.CompilerServices.IndexerNameAttribute("Item")]
- public virtual XmlElement this [String index]
- {
- get
- {
- // TODO - implement XmlNode.Item(string)
- throw new NotImplementedException();
- }
- }
- /// <summary>
- /// Get the last child node, or null if there are no nodes
- /// </summary>
- public virtual XmlNode LastChild
- {
- get
- {
- if (_childNodes.Count == 0)
- return null;
- else
- return _childNodes.Item(_childNodes.Count - 1);
- }
- }
- /// <summary>
- /// Returns the local name of the node with qualifiers removed
- /// LocalName of ns:elementName = "elementName"
- /// </summary>
- public abstract string LocalName {get;}
- /// <summary>
- /// Get the qualified node name
- /// derived classes must implement as behavior varies
- /// by tag type.
- /// </summary>
- public abstract string Name { get; }
- /// <summary>
- /// Get the namespace URI or String.Empty if none
- /// </summary>
- public virtual string NamespaceURI
- {
- get
- {
- // TODO - implement Namespace URI, or determine abstractness
- throw new NotImplementedException("XmlNode.NamespaceURI not implemented");
- }
- }
- /// <summary>
- /// Get the node immediatelly following this node, or null
- /// </summary>
- public virtual XmlNode NextSibling
- {
- get
- {
-
- if (_parent != null)
- {
- XmlNodeListAsArrayList children = _parent.ChildNodes as XmlNodeListAsArrayList;
- int ourIndex = children.data.IndexOf(this);
- return children[ourIndex + 1];
- }
- else
- return null;
- }
- }
- public virtual XmlNodeType NodeType
- {
- get
- {
- return XmlNodeType.None;
- }
- }
- /// <summary>
- /// Return the string representing this node and all it's children
- /// </summary>
- public virtual string OuterXml
- {
- get
- {
- // TODO - implement OuterXml {get;}
- throw new NotImplementedException();
- }
- }
- /// <summary>
- /// Return owning document.
- /// If this nodeType is a document, return null
- /// </summary>
- public virtual XmlDocument OwnerDocument
- {
- get
- {
- return FOwnerDocument;
- }
- }
- /// <summary>
- /// Returns the parent node, or null
- /// Return value depends on superclass node type
- /// </summary>
- public virtual XmlNode ParentNode
- {
- get
- {
- return _parent;
- }
- }
-
- /// <summary>
- /// set/get the namespace prefix for this node, or
- /// string.empty if it does not exist
- /// </summary>
- public virtual string Prefix
- {
- get
- {
- return Fprefix;
- }
-
- set
- {
- // TODO - validation on XmlNode.Prefix {set;}? (no)
- Fprefix = value;
- }
- }
- /// <summary>
- /// The preceding XmlNode or null
- /// </summary>
- public virtual XmlNode PreviousSibling {
- get
- {
- if (_parent != null)
- {
- XmlNodeListAsArrayList children = _parent.ChildNodes as XmlNodeListAsArrayList;
- int ourIndex = children.data.IndexOf(this);
- return children[ourIndex - 1];
- }
- else
- return null;
- }
- }
- /// <summary>
- /// Get/Set the value for this node
- /// </summary>
- public virtual string Value
- {
- get
- {
- return Fvalue;
- }
-
- set
- {
- Fvalue = value;
- }
- }
- //=====================================================================
- //======= Methods =====================================================
- //=====================================================================
- /// <summary>
- /// Appends the specified node to the end of the child node list
- /// </summary>
- /// <param name="newChild"></param>
- /// <returns></returns>
- public virtual XmlNode AppendChild (XmlNode newChild)
- {
- return InsertBefore(newChild, null);
- }
- /// <summary>
- /// Return a clone of this node
- /// </summary>
- /// <returns></returns>
- public virtual object Clone()
- {
- // TODO - implement XmlNode.Clone() as object
- throw new NotImplementedException("object XmlNode.Clone() not implmented");
- }
- /// <summary>
- /// Return a clone of the node
- /// </summary>
- /// <param name="deep">Make copy of all children</param>
- /// <returns>Cloned node</returns>
- public abstract XmlNode CloneNode( bool deep);
- /// <summary>
- /// Return an XPathNavigator for navigating this node
- /// </summary>
- /// <returns></returns>
- public System.Xml.XPath.XPathNavigator CreateNavigator()
- {
- // TODO - implement CreateNavigator()
- throw new NotImplementedException();
- }
- /// <summary>
- /// Provide support for "for each"
- /// </summary>
- /// <returns></returns>
- public IEnumerator GetEnumerator()
- {
- return _childNodes.data.GetEnumerator();
- }
- /// <summary>
- /// Look up the closest namespace for this node that is in scope for the given prefix
- /// </summary>
- /// <param name="prefix"></param>
- /// <returns>Namespace URI</returns>
- public virtual string GetNamespaceOfPrefix(string prefix)
- {
- // TODO - implement GetNamespaceOfPrefix()
- throw new NotImplementedException();
- }
- /// <summary>
- /// Get the closest xmlns declaration for the given namespace URI that is in scope.
- /// Returns the prefix defined in that declaration.
- /// </summary>
- /// <param name="namespaceURI"></param>
- /// <returns></returns>
- public virtual string GetPrefixOfNamespace(string namespaceURI)
- {
- // TODO - implement GetPrefixOfNamespace
- throw new NotImplementedException();
- }
-
- /// <summary>
- /// Insert newChild directly after the reference node.
- /// If refChild is null, newChild is inserted at the beginning of childnodes.
- /// If newChild is a document fragment, all nodes are inserted after refChild.
- /// If newChild is already in the tree, it is first removed.
- /// </summary>
- /// <exception cref="ArgumentException">NewChild was created from differant document.
- /// RefChild not a child of this node or null.
- /// Node is read-only</exception>
- /// <exception cref="InvalidOperationException">Node is of type that does not have children
- /// Node to insert is an ancestor of this node.</exception>
- /// <param name="newChild">Child node to insert.</param>
- /// <param name="refChild">Reference node to insert after</param>
- /// <returns>Removed node, or null if no node removed.</returns>
- public virtual XmlNode InsertAfter(XmlNode newChild, XmlNode refChild)
- {
- // Checks parent not ancestor, arguments valid, etc. Throws exception on error
- InsertionCheck(newChild, refChild);
- // Scan the node list, looking for refChild and seeing if newChild is in the list
- // Note that if refNode is null (prepend), we don't want to do the .Equals(null)
- XmlNode retval = null;
- int refNodeIndex = -1;
-
- for (int i = 0; i < _childNodes.Count; i++)
- {
- XmlNode e = _childNodes.data[i] as XmlNode;
- if (e.Equals(newChild))
- {
- retval = e;
- FOwnerDocument.onNodeRemoving(newChild, newChild.ParentNode);
- _childNodes.data.RemoveAt(i);
- newChild.setParent(null);
- FOwnerDocument.onNodeRemoved(newChild, null);
- break;
-
- }
- if ( (refChild != null ) & ( e.Equals(refChild) ) )
- {
- refNodeIndex = i;
- if (retval != null)
- break;
- }
- }
- if ( ( refNodeIndex == -1 ) & (refChild != null) )
- throw new ArgumentException("Reference node not found (and not null) in call to XmlNode.InsertAfter()");
- FOwnerDocument.onNodeInserting(newChild, this);
- if (refChild == null)
- refNodeIndex = 0;
- else
- refNodeIndex++; // insert after reference...
- if (newChild.NodeType == XmlNodeType.DocumentFragment)
- {
- // Insert all children, starting from refNodeIndex (0,1,2...n)
- for (int i = 0; i < newChild.ChildNodes.Count; i++)
- {
- XmlNode e = newChild.ChildNodes[i] as XmlNode;
- FOwnerDocument.onNodeInserting(e, this);
- _childNodes.data.Insert(refNodeIndex, newChild.ChildNodes[i]);
- e.setParent(this);
- FOwnerDocument.onNodeInserted(newChild, this);
- refNodeIndex ++;
- }
- }
- else
- {
- FOwnerDocument.onNodeInserting(newChild, this);
- _childNodes.data.Insert(refNodeIndex, newChild);
- newChild.setParent(this);
- FOwnerDocument.onNodeInserted(newChild, this);
- }
- return retval;
- }
-
- /// <summary>
- /// Insert newChild directly before the reference node.
- /// If refChild is null, newChild is inserted at the end of childnodes.
- /// If newChild is a document fragment, all nodes are inserted before refChild.
- /// If newChild is already in the tree, it is first removed.
- /// </summary>
- /// <exception cref="ArgumentException">NewChild was created from different document.
- /// RefChild not a child of this node, or is null.
- /// Node is read-only</exception>
- /// <exception cref="InvalidOperationException">Node is of type that does not have children.
- /// Node to insert is an ancestor of this node.</exception>
- /// <param name="newChild">Child node to insert.</param>
- /// <param name="refChild">Reference node to insert after</param>
- /// <returns>Removed node, or null if no node removed.</returns>
- public virtual XmlNode InsertBefore(XmlNode newChild, XmlNode refChild)
- {
- // Checks parent not ancestor, arguments valid, etc. Throws exception on error
- InsertionCheck(newChild, refChild);
- // Scan the node list, looking for refChild and seeing if newChild is in the list
- XmlNode retval = null;
- int refNodeIndex = -1;
-
- for (int i = 0; i < _childNodes.Count; i++)
- {
- XmlNode e = _childNodes.data[i] as XmlNode;
- if (e.Equals(newChild))
- {
- retval = e;
- FOwnerDocument.onNodeRemoving(newChild, newChild.ParentNode);
- _childNodes.data.RemoveAt(i);
- newChild.setParent(null);
- FOwnerDocument.onNodeRemoved(newChild, null);
- break;
- }
- if ( (refChild != null ) & ( e.Equals(refChild) ) )
- {
- refNodeIndex = i;
- if (retval != null)
- break;
- }
- }
- if ( ( refNodeIndex == -1 ) & (refChild != null) )
- throw new ArgumentException("Reference node not found (and not null) in call to XmlNode.InsertAfter()");
- if (refChild == null)
- refNodeIndex = _childNodes.Count;
- if (newChild.NodeType == XmlNodeType.DocumentFragment)
- {
- // Insert all children, starting from refNodeIndex (0,1,2...n)
- for (int i = 0; i < newChild.ChildNodes.Count; i++)
- {
- XmlNode e = newChild.ChildNodes[i] as XmlNode;
- FOwnerDocument.onNodeInserting(e, this);
- _childNodes.data.Insert(refNodeIndex, newChild.ChildNodes[i]);
- e.setParent(this);
- FOwnerDocument.onNodeInserted(newChild, this);
- refNodeIndex ++;
- }
- }
- else
- {
- FOwnerDocument.onNodeInserting(newChild, this);
- _childNodes.data.Insert(refNodeIndex, newChild);
- newChild.setParent(this);
- FOwnerDocument.onNodeInserted(newChild, this);
- }
- return retval;
-
- }
- /// <summary>
- /// Put all nodes under this node in "normal" form
- /// Whatever that means...
- /// </summary>
- public virtual void Normalize()
- {
- // TODO - Implement Normalize()
- throw new NotImplementedException();
- }
- /// <summary>
- /// Add the specified child to the beginning of the child node list
- /// </summary>
- /// <param name="newChild">Node to add</param>
- /// <returns>The node added</returns>
- public virtual XmlNode PrependChild(XmlNode newChild)
- {
- return InsertAfter(newChild, null);
- }
- /// <summary>
- /// Remove all children and attributes
- /// </summary>
- public virtual void RemoveAll()
- {
- if (_childNodes == null)
- return;
- else
- {
- // Remove in order, 0..n
- while (_childNodes.Count > 0)
- {
- XmlNode e = _childNodes[0];
- FOwnerDocument.onNodeRemoving(e, this);
- e.setParent(null);
- _childNodes.data.RemoveAt(0);
- FOwnerDocument.onNodeRemoved(e, null);
- }
- }
- }
- /// <summary>
- /// Remove specified child node
- /// </summary>
- /// <param name="oldChild"></param>
- /// <returns>Removed node</returns>
- public virtual XmlNode RemoveChild(XmlNode oldChild)
- {
- // TODO - implement RemoveChild(oldChild)
- throw new NotImplementedException();
- }
- /// <summary>
- /// Select a list of nodes matching the xpath
- /// </summary>
- /// <param name="xpath"></param>
- /// <returns>matching nodes</returns>
- public XmlNodeList SelectNodes( string xpath)
- {
- // TODO - imlement SelectNodes(xpath)
- throw new NotImplementedException();
- }
- /// <summary>
- /// Select a list of nodes matching the xpath. Any prefixes are resolved
- /// using the passed namespace manager
- /// </summary>
- /// <param name="xpath"></param>
- /// <param name="nsmgr"></param>
- /// <returns></returns>
- public XmlNodeList SelectNodes(string xpath, XmlNamespaceManager nsmgr)
- {
- // TODO - implement SelectNodes(xpath, nsmgr)
- throw new NotImplementedException();
- }
- /// <summary>
- /// Selects the first node that matches xpath
- /// </summary>
- /// <param name="?"></param>
- /// <returns></returns>
- public XmlNode SelectSingleNode(string xpatch)
- {
- // TODO - implement SelectSingeNode(xpath)
- throw new NotImplementedException();
- }
- /// <summary>
- /// Returns the first node that matches xpath
- /// Uses the passed namespace manager to resolve namespace URI's
- /// </summary>
- /// <param name="xpath"></param>
- /// <param name="nsmgr"></param>
- /// <returns></returns>
- public XmlNode SelectSingleNode(string xpath, XmlNamespaceManager nsmgr)
- {
- // Implement SelectSingleNode(xpath, nsmgr)
- throw new NotImplementedException();
- }
- /// <summary>
- /// Tests if the DOM implementation supports the passed feature
- /// </summary>
- /// <param name="feature"></param>
- /// <param name="version"></param>
- /// <returns></returns>
- public virtual bool Supports(string feature, string version)
- {
- //TODO - implement Supports(feature, version)
- throw new NotImplementedException();
- }
- /// <summary>
- /// Returns a string representation of the current node and it's children
- /// </summary>
- /// <returns></returns>
- public override string ToString()
- {
- // TODO - implement ToString()
- throw new NotImplementedException();
- }
- /// <summary>
- /// Saves all children of the current node to the passed writer
- /// </summary>
- /// <param name="w"></param>
- public abstract void WriteContentTo(XmlWriter w);
-
- /// <summary>
- /// Saves the current node to writer w
- /// </summary>
- /// <param name="w"></param>
- public abstract void WriteTo(XmlWriter w);
- //======= Internal methods ===============================================
- /// <summary>
- /// accessor {set;} for parentNode only visible internally.
- /// </summary>
- /// <param name="newParent">new parent node.</param>
- internal void setParent( XmlNode newParent)
- {
- if (newParent.OwnerDocument.Equals( FOwnerDocument) )
- _parent = newParent;
- else
- throw new ArgumentException("New parent node owner does not match");
- }
-
- //======= Protected methods ==============================================
- //======= Private Methods ===================================================
- /// <summary>
- /// Helper function to perform checks required before insrting a node.
- /// Throws applicable exceptions on error.
- /// </summary>
- /// <param name="newChild"></param>
- /// <param name="refChild"></param>
- private void InsertionCheck( XmlNode newChild, XmlNode refChild)
- {
- if (newChild == null)
- throw new ArgumentNullException("Null newNode passed to InsertAfter()");
- if (newChild.Equals(this))
- throw new ArgumentException("Cannot insert node onto itself");
- if (! FOwnerDocument.Equals( newChild.OwnerDocument) )
- throw new ArgumentException("Reference node has different owner document than this node");
-
- if ( FOwnerDocument.IsReadOnly )
- throw new ArgumentException("Operation not supported - tree is read-only");
- //Check that insert node is not in our path to the root
- XmlNode curParent = _parent;
- while ( (curParent != null) & (! FOwnerDocument.Equals(curParent) ))
- {
- if (curParent.Equals(newChild) )
- throw new ArgumentException("Cannot insert ancestor a node");
- curParent = curParent.ParentNode;
- }
- }
- // Constructors
- //===========================================================================
- //When we're first created, we won't know parent, etc.
- internal XmlNode( XmlDocument aOwnerDoc )
- {
- // Don't create childnodes object, since not all derived classes have children
- FOwnerDocument = aOwnerDoc;
- }
- } // XmlNode
- } // using namespace System.Xml
-
|