2016-08-03 10:59:49 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// <copyright file="XmlDocumentFragment.cs" company="Microsoft">
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
// </copyright>
|
2017-08-21 15:34:15 +00:00
|
|
|
// <owner current="true" primary="true">Microsoft</owner>
|
2016-08-03 10:59:49 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// <code>DocumentFragment</code> is a "lightweight" or "minimal"
|
|
|
|
// <code>Document</code> object. It is very common to want to be able to
|
|
|
|
// extract a portion of a document's tree or to create a new fragment of a
|
|
|
|
// document. Imagine implementing a user command like cut or rearranging a
|
|
|
|
// document by moving fragments around. It is desirable to have an object
|
|
|
|
// which can hold such fragments and it is quite natural to use a Node for
|
|
|
|
// this purpose. While it is true that a <code>Document</code> object could
|
|
|
|
// fulfil this role, a <code>Document</code> object can potentially be a
|
|
|
|
// heavyweight object, depending on the underlying implementation. What is
|
|
|
|
// really needed for this is a very lightweight object.
|
|
|
|
// <code>DocumentFragment</code> is such an object.
|
|
|
|
// <p>Furthermore, various operations -- such as inserting nodes as children
|
|
|
|
// of another <code>Node</code> -- may take <code>DocumentFragment</code>
|
|
|
|
// objects as arguments; this results in all the child nodes of the
|
|
|
|
// <code>DocumentFragment</code> being moved to the child list of this node.
|
|
|
|
// <p>The children of a <code>DocumentFragment</code> node are zero or more
|
|
|
|
// nodes representing the tops of any sub-trees defining the structure of the
|
|
|
|
// document. <code>DocumentFragment</code> nodes do not need to be
|
|
|
|
// well-formed XML documents (although they do need to follow the rules
|
|
|
|
// imposed upon well-formed XML parsed entities, which can have multiple top
|
|
|
|
// nodes). For example, a <code>DocumentFragment</code> might have only one
|
|
|
|
// child and that child node could be a <code>Text</code> node. Such a
|
|
|
|
// structure model represents neither an HTML document nor a well-formed XML
|
|
|
|
// document.
|
|
|
|
// <p>When a <code>DocumentFragment</code> is inserted into a
|
|
|
|
// <code>Document</code> (or indeed any other <code>Node</code> that may take
|
|
|
|
// children) the children of the <code>DocumentFragment</code> and not the
|
|
|
|
// <code>DocumentFragment</code> itself are inserted into the
|
|
|
|
// <code>Node</code>. This makes the <code>DocumentFragment</code> very
|
|
|
|
// useful when the user wishes to create nodes that are siblings; the
|
|
|
|
// <code>DocumentFragment</code> acts as the parent of these nodes so that the
|
|
|
|
// user can use the standard methods from the <code>Node</code> interface,
|
|
|
|
// such as <code>insertBefore()</code> and <code>appendChild()</code>.
|
|
|
|
|
|
|
|
namespace System.Xml {
|
|
|
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
using System.Xml.XPath;
|
|
|
|
|
|
|
|
// Represents a lightweight object that is useful for tree insert
|
|
|
|
// operations.
|
|
|
|
public class XmlDocumentFragment : XmlNode {
|
|
|
|
XmlLinkedNode lastChild;
|
|
|
|
|
|
|
|
protected internal XmlDocumentFragment( XmlDocument ownerDocument ): base( ) {
|
|
|
|
if ( ownerDocument == null )
|
|
|
|
throw new ArgumentException(Res.GetString(Res.Xdom_Node_Null_Doc));
|
|
|
|
parentNode= ownerDocument;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gets the name of the node.
|
|
|
|
public override String Name {
|
|
|
|
get { return OwnerDocument.strDocumentFragmentName;}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gets the name of the current node without the namespace prefix.
|
|
|
|
public override String LocalName {
|
|
|
|
get { return OwnerDocument.strDocumentFragmentName;}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gets the type of the current node.
|
|
|
|
public override XmlNodeType NodeType {
|
|
|
|
get { return XmlNodeType.DocumentFragment;}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gets the parent of this node (for nodes that can have parents).
|
|
|
|
public override XmlNode ParentNode {
|
|
|
|
get { return null;}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gets the XmlDocument that contains this node.
|
|
|
|
public override XmlDocument OwnerDocument {
|
|
|
|
get {
|
|
|
|
return (XmlDocument)parentNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gets or sets the markup representing just
|
|
|
|
// the children of this node.
|
|
|
|
public override string InnerXml {
|
|
|
|
get {
|
|
|
|
return base.InnerXml;
|
|
|
|
}
|
|
|
|
set {
|
|
|
|
RemoveAll();
|
|
|
|
XmlLoader loader = new XmlLoader();
|
|
|
|
//Hack that the content is the same element
|
|
|
|
loader.ParsePartialContent( this, value, XmlNodeType.Element );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creates a duplicate of this node.
|
|
|
|
public override XmlNode CloneNode(bool deep) {
|
|
|
|
Debug.Assert( OwnerDocument != null );
|
|
|
|
XmlDocument doc = OwnerDocument;
|
|
|
|
XmlDocumentFragment clone = doc.CreateDocumentFragment();
|
|
|
|
if (deep)
|
|
|
|
clone.CopyChildren( doc, this, deep );
|
|
|
|
return clone;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override bool IsContainer {
|
|
|
|
get { return true;}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override XmlLinkedNode LastNode {
|
|
|
|
get { return lastChild;}
|
|
|
|
set { lastChild = value;}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override bool IsValidChildType( XmlNodeType type ) {
|
|
|
|
switch (type) {
|
|
|
|
case XmlNodeType.Element:
|
|
|
|
case XmlNodeType.Text:
|
|
|
|
case XmlNodeType.EntityReference:
|
|
|
|
case XmlNodeType.Comment:
|
|
|
|
case XmlNodeType.Whitespace:
|
|
|
|
case XmlNodeType.SignificantWhitespace:
|
|
|
|
case XmlNodeType.ProcessingInstruction:
|
|
|
|
case XmlNodeType.CDATA:
|
|
|
|
return true;
|
|
|
|
|
|
|
|
case XmlNodeType.XmlDeclaration:
|
|
|
|
//if there is an XmlDeclaration node, it has to be the first node;
|
|
|
|
XmlNode firstNode = FirstChild;
|
|
|
|
if (firstNode == null || firstNode.NodeType != XmlNodeType.XmlDeclaration)
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false; //not allowed to insert a second XmlDeclaration node
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
internal override bool CanInsertAfter( XmlNode newChild, XmlNode refChild ) {
|
|
|
|
Debug.Assert(newChild != null); //should be checked that newChild is not null before this function call
|
|
|
|
if (newChild.NodeType == XmlNodeType.XmlDeclaration) {
|
|
|
|
if (refChild == null) {
|
|
|
|
//append at the end
|
|
|
|
return (LastNode == null);
|
|
|
|
} else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override bool CanInsertBefore( XmlNode newChild, XmlNode refChild ) {
|
|
|
|
Debug.Assert(newChild != null); //should be checked that newChild is not null before this function call
|
|
|
|
if (newChild.NodeType == XmlNodeType.XmlDeclaration) {
|
|
|
|
return (refChild==null || refChild==FirstChild);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Saves the node to the specified XmlWriter.
|
|
|
|
public override void WriteTo(XmlWriter w) {
|
|
|
|
WriteContentTo( w );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Saves all the children of the node to the specified XmlWriter.
|
|
|
|
public override void WriteContentTo(XmlWriter w) {
|
|
|
|
foreach( XmlNode n in this ) {
|
|
|
|
n.WriteTo( w );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override XPathNodeType XPNodeType { get { return XPathNodeType.Root; } }
|
|
|
|
}
|
|
|
|
}
|