//
// Author:
// Kral Ferch <kral_ferch@hotmail.com>
+// Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
//
// (C) 2002 Kral Ferch
+// (C) 2002 Atsushi Enomoto
//
using System;
#region Properties
- public virtual XmlAttributeCollection Attributes
- {
+ public virtual XmlAttributeCollection Attributes {
get { return null; }
}
- public virtual string BaseURI
- {
- get { return ParentNode.BaseURI; }
+ public virtual string BaseURI {
+ get {
+ // Isn't it conformant to W3C XML Base Recommendation?
+ // As far as I tested, there are not...
+ return (ParentNode != null) ? ParentNode.BaseURI : OwnerDocument.BaseURI;
+ }
}
public virtual XmlNodeList ChildNodes {
get {
- return new XmlNodeListChildren(this);
+ return new XmlNodeListChildren (this);
}
}
get { return LastChild != null; }
}
- [MonoTODO]
+ [MonoTODO("confirm whether this way is right for each not-overriden types.")]
public virtual string InnerText {
get {
StringBuilder builder = new StringBuilder ();
StringWriter sw = new StringWriter ();
XmlTextWriter xtw = new XmlTextWriter (sw);
- WriteContentTo(xtw);
+ WriteContentTo (xtw);
- return sw.GetStringBuilder().ToString();
+ return sw.GetStringBuilder ().ToString ();
}
set { throw new NotImplementedException (); }
StringWriter sw = new StringWriter ();
XmlTextWriter xtw = new XmlTextWriter (sw);
- WriteTo(xtw);
+ WriteTo (xtw);
- return sw.GetStringBuilder().ToString();
+ return sw.GetStringBuilder ().ToString ();
}
}
set { throw new InvalidOperationException ("This node does not have a value"); }
}
+ internal virtual string XmlLang {
+ get {
+ if(Attributes != null)
+ foreach(XmlAttribute attr in Attributes)
+ if(attr.Name == "xml:lang")
+ return attr.Value;
+ return (ParentNode != null) ? ParentNode.XmlLang : OwnerDocument.XmlLang;
+ }
+ }
+
+ internal virtual XmlSpace XmlSpace {
+ get {
+ if(Attributes != null) {
+ foreach(XmlAttribute attr in Attributes) {
+ if(attr.Name == "xml:space") {
+ switch(attr.Value) {
+ case "preserve": return XmlSpace.Preserve;
+ case "default": return XmlSpace.Default;
+ }
+ break;
+ }
+ }
+ }
+ return (ParentNode != null) ? ParentNode.XmlSpace : OwnerDocument.XmlSpace;
+ }
+ }
+
#endregion
#region Methods
public virtual XmlNode AppendChild (XmlNode newChild)
{
// I assume that AppendChild(n) equals to InsertAfter(n, this.LastChild) or InsertBefore(n, null)
- return InsertBefore(newChild, null);
-
- // Below are formerly used logic.
-/* XmlDocument ownerDoc = (NodeType == XmlNodeType.Document) ? (XmlDocument)this : OwnerDocument;
-
- if (NodeType == XmlNodeType.Document || NodeType == XmlNodeType.Element || NodeType == XmlNodeType.Attribute || NodeType == XmlNodeType.DocumentFragment) {
-
- if (IsReadOnly)
- throw new ArgumentException ("The specified node is readonly.");
-
- if (newChild.OwnerDocument != ownerDoc)
- throw new ArgumentException ("Can't append a node created by another document.");
-
- // checking validity finished. then appending...
-
- ownerDoc.onNodeInserting (newChild, this);
-
- if(newChild.ParentNode != null)
- newChild.ParentNode.RemoveChild(newChild);
-
- if(newChild.NodeType == XmlNodeType.DocumentFragment)
- {
- int x = newChild.ChildNodes.Count;
- for(int i=0; i<x; i++)
- {
- // When this logic became to remove children in order, then index will have never to increments.
- XmlNode n = newChild.ChildNodes[0];
- this.AppendChild(n); // recursively invokes events. (It is compatible with MS implementation.)
- }
- }
- else
- {
- XmlLinkedNode newLinkedChild = (XmlLinkedNode) newChild;
- XmlLinkedNode lastLinkedChild = LastLinkedChild;
-
- newLinkedChild.parentNode = this;
-
- if (lastLinkedChild != null)
- {
- newLinkedChild.NextLinkedSibling = lastLinkedChild.NextLinkedSibling;
- lastLinkedChild.NextLinkedSibling = newLinkedChild;
- }
- else
- newLinkedChild.NextLinkedSibling = newLinkedChild;
-
- LastLinkedChild = newLinkedChild;
-
- ownerDoc.onNodeInserted (newChild, newChild.ParentNode);
-
- }
- return newChild;
- } else
- throw new InvalidOperationException();
-*/ }
+ return InsertBefore (newChild, null);
+ }
public virtual XmlNode Clone ()
{
// By MS document, it is equivalent to CloneNode(true).
- return this.CloneNode(true);
+ return this.CloneNode (true);
}
public abstract XmlNode CloneNode (bool deep);
[MonoTODO]
public XPathNavigator CreateNavigator ()
{
- return new XmlDocumentNavigator(this);
+ return new XmlDocumentNavigator (this);
}
public IEnumerator GetEnumerator ()
{
- return new XmlNodeListChildren(this).GetEnumerator();
+ return new XmlNodeListChildren (this).GetEnumerator ();
}
-// [MonoTODO]
+ [MonoTODO("performance problem.")]
public virtual string GetNamespaceOfPrefix (string prefix)
{
- XmlNamespaceManager nsmgr = ConstructNamespaceManager();
- return nsmgr.LookupNamespace(prefix);
-// throw new NotImplementedException ();
+ XmlNamespaceManager nsmgr = ConstructNamespaceManager ();
+ return nsmgr.LookupNamespace (prefix);
}
-// [MonoTODO]
+ [MonoTODO("performance problem.")]
public virtual string GetPrefixOfNamespace (string namespaceURI)
{
- XmlNamespaceManager nsmgr = ConstructNamespaceManager();
- return nsmgr.LookupPrefix(namespaceURI);
-// throw new NotImplementedException ();
+ XmlNamespaceManager nsmgr = ConstructNamespaceManager ();
+ string ns = nsmgr.LookupPrefix (namespaceURI);
+ return (ns != null) ? ns : String.Empty;
}
object ICloneable.Clone ()
return GetEnumerator ();
}
- [MonoTODO]
public virtual XmlNode InsertAfter (XmlNode newChild, XmlNode refChild)
{
// I assume that insertAfter(n1, n2) equals to InsertBefore(n1, n2.PreviousSibling).
// I took this way because rather than calling InsertAfter() from InsertBefore()
// because current implementation of 'NextSibling' looks faster than 'PreviousSibling'.
- XmlNode argNode = (refChild == null) ? null : refChild.NextSibling;
- return InsertBefore(newChild, argNode);
+ XmlNode argNode = null;
+ if(refChild != null)
+ argNode = refChild.NextSibling;
+ else if(ChildNodes.Count > 0)
+ argNode = FirstChild;
+ return InsertBefore (newChild, argNode);
}
- [MonoTODO]
+ [MonoTODO("If inserted node is entity reference, then check conforming entity. Wait for DTD implementation.")]
public virtual XmlNode InsertBefore (XmlNode newChild, XmlNode refChild)
{
XmlDocument ownerDoc = (NodeType == XmlNodeType.Document) ? (XmlDocument)this : OwnerDocument;
- if (NodeType == XmlNodeType.Document || NodeType == XmlNodeType.Element || NodeType == XmlNodeType.Attribute || NodeType == XmlNodeType.DocumentFragment)
- {
+ if (NodeType == XmlNodeType.Document ||
+ NodeType == XmlNodeType.Element ||
+ NodeType == XmlNodeType.Attribute ||
+ NodeType == XmlNodeType.DocumentFragment) {
if (IsReadOnly)
throw new ArgumentException ("The specified node is readonly.");
if (newChild.OwnerDocument != ownerDoc)
throw new ArgumentException ("Can't append a node created by another document.");
- if(refChild != null)
- {
- if(newChild.OwnerDocument != refChild.OwnerDocument)
+ if (refChild != null && newChild.OwnerDocument != refChild.OwnerDocument)
throw new ArgumentException ("argument nodes are on the different documents.");
- if(refChild == ownerDoc.DocumentElement && (newChild is XmlElement || newChild is XmlCharacterData || newChild is XmlEntityReference))
- throw new XmlException("cannot insert this node to this position.");
- }
+ // This check is done by MS.NET 1.0, but isn't done for MS.NET 1.1.
+ // Skip this check in the meantime...
+// if(this == ownerDoc && ownerDoc.DocumentElement != null && (newChild is XmlElement))
+// throw new XmlException ("multiple document element not allowed.");
+
// checking validity finished. then appending...
ownerDoc.onNodeInserting (newChild, this);
if(newChild.ParentNode != null)
- newChild.ParentNode.RemoveChild(newChild);
+ newChild.ParentNode.RemoveChild (newChild);
- if(newChild.NodeType == XmlNodeType.DocumentFragment)
- {
+ if(newChild.NodeType == XmlNodeType.DocumentFragment) {
int x = newChild.ChildNodes.Count;
- for(int i=0; i<x; i++)
- {
- // When this logic became to remove children in order, then index will have never to increments.
- XmlNode n = newChild.ChildNodes[0];
- this.InsertBefore(n, refChild); // recursively invokes events. (It is compatible with MS implementation.)
+ for(int i=0; i<x; i++) {
+ XmlNode n = newChild.ChildNodes [0];
+ this.InsertBefore (n, refChild); // recursively invokes events. (It is compatible with MS implementation.)
}
}
- else
- {
+ else {
XmlLinkedNode newLinkedChild = (XmlLinkedNode) newChild;
XmlLinkedNode lastLinkedChild = LastLinkedChild;
newLinkedChild.parentNode = this;
- if(refChild == null)
- {
+ if(refChild == null) {
// append last, so:
// * set nextSibling of previous lastchild to newChild
// * set lastchild = newChild
// * set next of newChild to firstChild
- if(LastLinkedChild != null)
- {
+ if(LastLinkedChild != null) {
XmlLinkedNode formerFirst = FirstChild as XmlLinkedNode;
LastLinkedChild.NextLinkedSibling = newLinkedChild;
LastLinkedChild = newLinkedChild;
newLinkedChild.NextLinkedSibling = formerFirst;
}
- else
- {
+ else {
LastLinkedChild = newLinkedChild;
LastLinkedChild.NextLinkedSibling = newLinkedChild; // FirstChild
}
}
- else
- {
+ else {
// append not last, so:
// * if newchild is first, then set next of lastchild is newChild.
// otherwise, set next of previous sibling to newChild
return newChild;
}
else
- throw new InvalidOperationException();
+ throw new InvalidOperationException ();
}
[MonoTODO]
throw new NotImplementedException ();
}
- [MonoTODO]
public virtual XmlNode PrependChild (XmlNode newChild)
{
- throw new NotImplementedException ();
+ return InsertAfter (newChild, null);
}
public virtual void RemoveAll ()
{
- XmlDocument ownerDoc = (NodeType == XmlNodeType.Document) ? (XmlDocument)this : OwnerDocument;
-
- ownerDoc.onNodeRemoving (this, this.ParentNode);
- LastLinkedChild = null;
- ownerDoc.onNodeRemoved (this, this.ParentNode);
+ XmlNode next = null;
+ for (XmlNode node = FirstChild; node != null; node = next) {
+ next = node.NextSibling;
+ RemoveChild (node);
+ }
}
public virtual XmlNode RemoveChild (XmlNode oldChild)
{
+ XmlDocument ownerDoc = (NodeType == XmlNodeType.Document) ? (XmlDocument)this : OwnerDocument;
if(oldChild.ParentNode != this)
- throw new XmlException("specified child is not child of this node.");
+ throw new XmlException ("specified child is not child of this node.");
- OwnerDocument.onNodeRemoving (oldChild, oldChild.ParentNode);
+ ownerDoc.onNodeRemoving (oldChild, oldChild.ParentNode);
- if (NodeType == XmlNodeType.Document || NodeType == XmlNodeType.Element || NodeType == XmlNodeType.Attribute || NodeType == XmlNodeType.DocumentFragment)
- {
+ if (NodeType == XmlNodeType.Document || NodeType == XmlNodeType.Element || NodeType == XmlNodeType.Attribute || NodeType == XmlNodeType.DocumentFragment) {
if (IsReadOnly)
- throw new ArgumentException();
+ throw new ArgumentException ();
- if (Object.ReferenceEquals(LastLinkedChild, LastLinkedChild.NextLinkedSibling) && Object.ReferenceEquals(LastLinkedChild, oldChild))
+ if (Object.ReferenceEquals (LastLinkedChild, LastLinkedChild.NextLinkedSibling) && Object.ReferenceEquals (LastLinkedChild, oldChild))
LastLinkedChild = null;
else {
XmlLinkedNode oldLinkedChild = (XmlLinkedNode)oldChild;
XmlLinkedNode beforeLinkedChild = LastLinkedChild;
- while (!Object.ReferenceEquals(beforeLinkedChild.NextLinkedSibling, LastLinkedChild) && !Object.ReferenceEquals(beforeLinkedChild.NextLinkedSibling, oldLinkedChild))
+ while (!Object.ReferenceEquals (beforeLinkedChild.NextLinkedSibling, LastLinkedChild) && !Object.ReferenceEquals (beforeLinkedChild.NextLinkedSibling, oldLinkedChild))
beforeLinkedChild = beforeLinkedChild.NextLinkedSibling;
- if (!Object.ReferenceEquals(beforeLinkedChild.NextLinkedSibling, oldLinkedChild))
- throw new ArgumentException();
+ if (!Object.ReferenceEquals (beforeLinkedChild.NextLinkedSibling, oldLinkedChild))
+ throw new ArgumentException ();
beforeLinkedChild.NextLinkedSibling = oldLinkedChild.NextLinkedSibling;
oldLinkedChild.NextLinkedSibling = null;
}
- OwnerDocument.onNodeRemoved (oldChild, oldChild.ParentNode);
+ ownerDoc.onNodeRemoved (oldChild, oldChild.ParentNode);
oldChild.parentNode = null; // clear parent 'after' above logic.
return oldChild;
}
else
- throw new ArgumentException();
+ throw new ArgumentException ();
}
- [MonoTODO]
public virtual XmlNode ReplaceChild (XmlNode newChild, XmlNode oldChild)
{
- throw new NotImplementedException ();
+ if(oldChild.ParentNode != this)
+ throw new InvalidOperationException ("oldChild is not a child of this node.");
+ XmlNode parent = this.ParentNode;
+ while(parent != null) {
+ if(newChild == parent)
+ throw new InvalidOperationException ("newChild is ancestor of this node.");
+ parent = parent.ParentNode;
+ }
+ foreach(XmlNode n in ChildNodes) {
+ if(n == oldChild) {
+ XmlNode prev = oldChild.PreviousSibling;
+ RemoveChild (oldChild);
+ InsertAfter (newChild, prev);
+ break;
+ }
+ }
+ return oldChild;
}
public XmlNodeList SelectNodes (string xpath)
public abstract void WriteTo (XmlWriter w);
- // It parses with XmlReader and then construct DOM of the parsed contents.
- internal void ConstructDOM(XmlReader xmlReader, XmlNode currentNode)
- {
- // I am not confident whether this method should be placed in this class or not...
- // Please verify its validity and then erase this comment;-)
- XmlNode newNode;
- XmlDocument doc = currentNode is XmlDocument ? (XmlDocument)currentNode : currentNode.OwnerDocument;
- // Below are 'almost' copied from XmlDocument.Load(XmlReader xmlReader)
- while (xmlReader.Read ())
- {
- switch (xmlReader.NodeType)
- {
- case XmlNodeType.CDATA:
- newNode = doc.CreateCDataSection(xmlReader.Value);
- currentNode.AppendChild (newNode);
- break;
-
- case XmlNodeType.Comment:
- newNode = doc.CreateComment (xmlReader.Value);
- currentNode.AppendChild (newNode);
- break;
-
- case XmlNodeType.Element:
- XmlElement element = doc.CreateElement (xmlReader.Prefix, xmlReader.LocalName, xmlReader.NamespaceURI);
- currentNode.AppendChild (element);
-
- // set the element's attributes.
- while (xmlReader.MoveToNextAttribute ())
- {
- XmlAttribute attribute = doc.CreateAttribute (xmlReader.Prefix, xmlReader.LocalName, xmlReader.NamespaceURI);
- attribute.Value = xmlReader.Value;
- element.SetAttributeNode (attribute);
- }
-
- xmlReader.MoveToElement ();
-
- // if this element isn't empty, push it onto our "stack".
- if (!xmlReader.IsEmptyElement)
- currentNode = element;
-
- break;
-
- case XmlNodeType.EndElement:
- currentNode = currentNode.ParentNode;
- break;
-
- case XmlNodeType.ProcessingInstruction:
- newNode = doc.CreateProcessingInstruction (xmlReader.Name, xmlReader.Value);
- currentNode.AppendChild (newNode);
- break;
-
- case XmlNodeType.Text:
- newNode = doc.CreateTextNode (xmlReader.Value);
- currentNode.AppendChild (newNode);
- break;
-
- case XmlNodeType.XmlDeclaration:
- // empty strings are dummy, then gives over setting value contents to setter.
- newNode = doc.CreateXmlDeclaration("1.0" , String.Empty, String.Empty);
- ((XmlDeclaration)newNode).Value = xmlReader.Value;
- this.AppendChild(newNode);
- break;
-
- case XmlNodeType.DocumentType:
- XmlTextReader xmlTextReader = xmlReader as XmlTextReader;
- if(xmlTextReader != null)
- {
- XmlDocumentType dtdNode = doc.CreateDocumentType(xmlTextReader.Name, xmlTextReader.publicId, xmlTextReader.systemId, xmlTextReader.Value);
- this.AppendChild(dtdNode);
- }
- else
- throw new XmlException("construction of DocumentType node from this XmlReader is not supported.");
- break;
- }
- }
- }
-
// It parses this and all the ancestor elements,
// find 'xmlns' declarations, stores and then return them.
// TODO: tests
- internal XmlNamespaceManager ConstructNamespaceManager()
+ internal XmlNamespaceManager ConstructNamespaceManager ()
{
XmlDocument doc = this is XmlDocument ? (XmlDocument)this : this.OwnerDocument;
- XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
+ XmlNamespaceManager nsmgr = new XmlNamespaceManager (doc.NameTable);
XmlElement el = null;
- switch(this.NodeType)
- {
- case XmlNodeType.Attribute:
- el = ((XmlAttribute)this).OwnerElement;
- break;
- case XmlNodeType.Element:
- el = this as XmlElement;
- break;
- default:
- el = this.ParentNode as XmlElement;
- break;
+ switch(this.NodeType) {
+ case XmlNodeType.Attribute:
+ el = ((XmlAttribute)this).OwnerElement;
+ break;
+ case XmlNodeType.Element:
+ el = this as XmlElement;
+ break;
+ default:
+ el = this.ParentNode as XmlElement;
+ break;
}
- while(el != null)
- {
- foreach(XmlAttribute attr in el.Attributes)
- {
- if(attr.Prefix == "xmlns" || (attr.Name == "xmlns" && attr.Prefix == String.Empty))
- {
- if(nsmgr.LookupNamespace(attr.LocalName) == null )
- {
- nsmgr.AddNamespace(attr.LocalName, attr.Value);
- }
+ while(el != null) {
+ foreach(XmlAttribute attr in el.Attributes) {
+ if(attr.Prefix == "xmlns" || (attr.Name == "xmlns" && attr.Prefix == String.Empty)) {
+ if(nsmgr.LookupNamespace (attr.LocalName) == null )
+ nsmgr.AddNamespace (attr.LocalName, attr.Value);
}
}
// When reached to document, then it will set null value :)