|
|
@@ -24,6 +24,7 @@ namespace System.Xml
|
|
|
XmlDocument ownerDocument;
|
|
|
XmlNode parentNode;
|
|
|
StringBuilder tmpBuilder;
|
|
|
+ XmlLinkedNode lastLinkedChild;
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
@@ -152,8 +153,8 @@ namespace System.Xml
|
|
|
}
|
|
|
|
|
|
internal virtual XmlLinkedNode LastLinkedChild {
|
|
|
- get { return null; }
|
|
|
- set { }
|
|
|
+ get { return lastLinkedChild; }
|
|
|
+ set { lastLinkedChild = value; }
|
|
|
}
|
|
|
|
|
|
public abstract string LocalName { get; }
|
|
|
@@ -359,62 +360,11 @@ namespace System.Xml
|
|
|
|
|
|
public virtual XmlNode InsertBefore (XmlNode newChild, XmlNode refChild)
|
|
|
{
|
|
|
- XmlDocument ownerDoc = (NodeType == XmlNodeType.Document) ? (XmlDocument)this : OwnerDocument;
|
|
|
-
|
|
|
- if (NodeType != XmlNodeType.Element &&
|
|
|
- NodeType != XmlNodeType.Attribute &&
|
|
|
- NodeType != XmlNodeType.Document &&
|
|
|
- NodeType != XmlNodeType.DocumentFragment)
|
|
|
- throw new InvalidOperationException (String.Format ("current node {0} is not allowed to have any children.", NodeType));
|
|
|
-
|
|
|
- switch (NodeType) {
|
|
|
- case XmlNodeType.Attribute:
|
|
|
- switch (newChild.NodeType) {
|
|
|
- case XmlNodeType.Text:
|
|
|
- case XmlNodeType.EntityReference:
|
|
|
- break;
|
|
|
- default:
|
|
|
- throw new ArgumentException (String.Format (
|
|
|
- "Cannot insert specified type of node {0} as a child of this node {0}.",
|
|
|
- newChild.NodeType, NodeType));
|
|
|
- }
|
|
|
- break;
|
|
|
- case XmlNodeType.Element:
|
|
|
- switch (newChild.NodeType) {
|
|
|
- case XmlNodeType.Attribute:
|
|
|
- case XmlNodeType.Document:
|
|
|
- case XmlNodeType.DocumentType:
|
|
|
- case XmlNodeType.Entity:
|
|
|
- case XmlNodeType.Notation:
|
|
|
- case XmlNodeType.XmlDeclaration:
|
|
|
- throw new ArgumentException ("Cannot insert specified type of node as a child of this node.");
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- 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.");
|
|
|
-
|
|
|
- if(this == ownerDoc && ownerDoc.DocumentElement != null && (newChild is XmlElement))
|
|
|
- throw new XmlException ("multiple document element not allowed.");
|
|
|
-
|
|
|
- // checking validity finished. then appending...
|
|
|
-
|
|
|
-
|
|
|
- if (newChild == this || isAncestorIntern(newChild))
|
|
|
- throw new ArgumentException("Cannot insert a node or any ancestor of that node as a child of itself.");
|
|
|
-
|
|
|
- return insertBeforeIntern (newChild, refChild);
|
|
|
+ return InsertBefore (newChild, refChild, true);
|
|
|
}
|
|
|
|
|
|
// check for the node to be one of node ancestors
|
|
|
- internal bool isAncestorIntern(XmlNode newChild)
|
|
|
+ internal bool IsAncestor (XmlNode newChild)
|
|
|
{
|
|
|
XmlNode currNode = this.ParentNode;
|
|
|
while(currNode != null)
|
|
|
@@ -426,14 +376,17 @@ namespace System.Xml
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- internal XmlNode insertBeforeIntern (XmlNode newChild, XmlNode refChild)
|
|
|
+ internal XmlNode InsertBefore (XmlNode newChild, XmlNode refChild, bool checkNodeType)
|
|
|
{
|
|
|
+ if (checkNodeType)
|
|
|
+ CheckNodeInsertion (newChild, refChild);
|
|
|
+
|
|
|
XmlDocument ownerDoc = (NodeType == XmlNodeType.Document) ? (XmlDocument)this : OwnerDocument;
|
|
|
|
|
|
ownerDoc.onNodeInserting (newChild, this);
|
|
|
|
|
|
if(newChild.ParentNode != null)
|
|
|
- newChild.ParentNode.RemoveChild (newChild);
|
|
|
+ newChild.ParentNode.RemoveChild (newChild, checkNodeType);
|
|
|
|
|
|
if(newChild.NodeType == XmlNodeType.DocumentFragment) {
|
|
|
int x = newChild.ChildNodes.Count;
|
|
|
@@ -476,11 +429,79 @@ namespace System.Xml
|
|
|
prev.NextLinkedSibling = newLinkedChild;
|
|
|
newLinkedChild.NextLinkedSibling = refChild as XmlLinkedNode;
|
|
|
}
|
|
|
+ switch (newChild.NodeType) {
|
|
|
+ case XmlNodeType.EntityReference:
|
|
|
+ ((XmlEntityReference) newChild).SetReferencedEntityContent ();
|
|
|
+ break;
|
|
|
+ case XmlNodeType.Entity:
|
|
|
+ ((XmlEntity) newChild).SetEntityContent ();
|
|
|
+ break;
|
|
|
+ case XmlNodeType.DocumentType:
|
|
|
+ foreach (XmlEntity ent in ((XmlDocumentType)newChild).Entities)
|
|
|
+ ent.SetEntityContent ();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
ownerDoc.onNodeInserted (newChild, newChild.ParentNode);
|
|
|
}
|
|
|
return newChild;
|
|
|
}
|
|
|
|
|
|
+ private void CheckNodeInsertion (XmlNode newChild, XmlNode refChild)
|
|
|
+ {
|
|
|
+ XmlDocument ownerDoc = (NodeType == XmlNodeType.Document) ? (XmlDocument)this : OwnerDocument;
|
|
|
+
|
|
|
+ if (NodeType != XmlNodeType.Element &&
|
|
|
+ NodeType != XmlNodeType.Attribute &&
|
|
|
+ NodeType != XmlNodeType.Document &&
|
|
|
+ NodeType != XmlNodeType.DocumentFragment)
|
|
|
+ throw new InvalidOperationException (String.Format ("current node {0} is not allowed to have any children.", NodeType));
|
|
|
+
|
|
|
+ switch (NodeType) {
|
|
|
+ case XmlNodeType.Attribute:
|
|
|
+ switch (newChild.NodeType) {
|
|
|
+ case XmlNodeType.Text:
|
|
|
+ case XmlNodeType.EntityReference:
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ throw new ArgumentException (String.Format (
|
|
|
+ "Cannot insert specified type of node {0} as a child of this node {0}.",
|
|
|
+ newChild.NodeType, NodeType));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case XmlNodeType.Element:
|
|
|
+ switch (newChild.NodeType) {
|
|
|
+ case XmlNodeType.Attribute:
|
|
|
+ case XmlNodeType.Document:
|
|
|
+ case XmlNodeType.DocumentType:
|
|
|
+ case XmlNodeType.Entity:
|
|
|
+ case XmlNodeType.Notation:
|
|
|
+ case XmlNodeType.XmlDeclaration:
|
|
|
+ throw new ArgumentException ("Cannot insert specified type of node as a child of this node.");
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ 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.");
|
|
|
+
|
|
|
+ if(this == ownerDoc && ownerDoc.DocumentElement != null && (newChild is XmlElement))
|
|
|
+ throw new XmlException ("multiple document element not allowed.");
|
|
|
+
|
|
|
+ // checking validity finished. then appending...
|
|
|
+
|
|
|
+
|
|
|
+ if (newChild == this || IsAncestor (newChild))
|
|
|
+ throw new ArgumentException("Cannot insert a node or any ancestor of that node as a child of itself.");
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
public virtual void Normalize ()
|
|
|
{
|
|
|
// if (tmpBuilder == null)
|
|
|
@@ -559,12 +580,11 @@ namespace System.Xml
|
|
|
|
|
|
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.");
|
|
|
-
|
|
|
- ownerDoc.onNodeRemoving (oldChild, oldChild.ParentNode);
|
|
|
+ return RemoveChild (oldChild, true);
|
|
|
+ }
|
|
|
|
|
|
+ private void CheckNodeRemoval ()
|
|
|
+ {
|
|
|
if (NodeType != XmlNodeType.Attribute &&
|
|
|
NodeType != XmlNodeType.Element &&
|
|
|
NodeType != XmlNodeType.Document &&
|
|
|
@@ -573,6 +593,18 @@ namespace System.Xml
|
|
|
|
|
|
if (IsReadOnly)
|
|
|
throw new ArgumentException (String.Format ("This {0} node is read only.", NodeType));
|
|
|
+ }
|
|
|
+
|
|
|
+ internal XmlNode RemoveChild (XmlNode oldChild, bool checkNodeType)
|
|
|
+ {
|
|
|
+ XmlDocument ownerDoc = (NodeType == XmlNodeType.Document) ? (XmlDocument)this : OwnerDocument;
|
|
|
+ if(oldChild.ParentNode != this)
|
|
|
+ throw new XmlException ("specified child is not child of this node.");
|
|
|
+
|
|
|
+ ownerDoc.onNodeRemoving (oldChild, oldChild.ParentNode);
|
|
|
+
|
|
|
+ if (checkNodeType)
|
|
|
+ CheckNodeRemoval ();
|
|
|
|
|
|
if (Object.ReferenceEquals (LastLinkedChild, LastLinkedChild.NextLinkedSibling) && Object.ReferenceEquals (LastLinkedChild, oldChild))
|
|
|
// If there is only one children, simply clear.
|
|
|
@@ -609,7 +641,7 @@ namespace System.Xml
|
|
|
if(oldChild.ParentNode != this)
|
|
|
throw new InvalidOperationException ("oldChild is not a child of this node.");
|
|
|
|
|
|
- if (newChild == this || isAncestorIntern(newChild))
|
|
|
+ if (newChild == this || IsAncestor (newChild))
|
|
|
throw new ArgumentException("Cannot insert a node or any ancestor of that node as a child of itself.");
|
|
|
|
|
|
foreach(XmlNode n in ChildNodes) {
|