| File: System\Xml\Dom\XmlDocumentFragment.cs | Web Access |
| Project: src\runtime\src\libraries\System.Private.Xml\src\System.Private.Xml.csproj (System.Private.Xml) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; using System.Xml.XPath; namespace System.Xml { // Represents a lightweight object that is useful for tree insert // operations. // <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>. public class XmlDocumentFragment : XmlNode { private XmlLinkedNode? _lastChild; protected internal XmlDocumentFragment(XmlDocument ownerDocument) : base() { if (ownerDocument == null) throw new ArgumentException(SR.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; } } } }