+ 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.");
+
+ if (refChild != null && newChild.OwnerDocument != refChild.OwnerDocument)
+ throw new ArgumentException ("argument nodes are on the different documents.");
+
+ // 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);
+
+ if(newChild.NodeType == XmlNodeType.DocumentFragment) {
+ int x = newChild.ChildNodes.Count;
+ 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 {
+ XmlLinkedNode newLinkedChild = (XmlLinkedNode) newChild;
+ XmlLinkedNode lastLinkedChild = LastLinkedChild;
+
+ newLinkedChild.parentNode = this;
+
+ 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) {
+ XmlLinkedNode formerFirst = FirstChild as XmlLinkedNode;
+ LastLinkedChild.NextLinkedSibling = newLinkedChild;
+ LastLinkedChild = newLinkedChild;
+ newLinkedChild.NextLinkedSibling = formerFirst;
+ }
+ else {
+ LastLinkedChild = newLinkedChild;
+ LastLinkedChild.NextLinkedSibling = newLinkedChild; // FirstChild
+ }
+ }
+ else {
+ // append not last, so:
+ // * if newchild is first, then set next of lastchild is newChild.
+ // otherwise, set next of previous sibling to newChild
+ // * set next of newChild to refChild
+ XmlLinkedNode prev = refChild.PreviousSibling as XmlLinkedNode;
+ if(prev == null)
+ LastLinkedChild.NextLinkedSibling = newLinkedChild;
+ else
+ prev.NextLinkedSibling = newLinkedChild;
+ newLinkedChild.NextLinkedSibling = refChild as XmlLinkedNode;
+ }
+ ownerDoc.onNodeInserted (newChild, newChild.ParentNode);
+ }
+ return newChild;
+ }
+ else
+ throw new InvalidOperationException ();