The Labs \ Source Viewer \ SSCLI \ System.Xml \ XmlDocumentFragment

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlDocumentFragment.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. // <code>DocumentFragment</code> is a "lightweight" or "minimal"
  16. // <code>Document</code> object. It is very common to want to be able to
  17. // extract a portion of a document's tree or to create a new fragment of a
  18. // document. Imagine implementing a user command like cut or rearranging a
  19. // document by moving fragments around. It is desirable to have an object
  20. // which can hold such fragments and it is quite natural to use a Node for
  21. // this purpose. While it is true that a <code>Document</code> object could
  22. // fulfil this role, a <code>Document</code> object can potentially be a
  23. // heavyweight object, depending on the underlying implementation. What is
  24. // really needed for this is a very lightweight object.
  25. // <code>DocumentFragment</code> is such an object.
  26. // <p>Furthermore, various operations -- such as inserting nodes as children
  27. // of another <code>Node</code> -- may take <code>DocumentFragment</code>
  28. // objects as arguments; this results in all the child nodes of the
  29. // <code>DocumentFragment</code> being moved to the child list of this node.
  30. // <p>The children of a <code>DocumentFragment</code> node are zero or more
  31. // nodes representing the tops of any sub-trees defining the structure of the
  32. // document. <code>DocumentFragment</code> nodes do not need to be
  33. // well-formed XML documents (although they do need to follow the rules
  34. // imposed upon well-formed XML parsed entities, which can have multiple top
  35. // nodes). For example, a <code>DocumentFragment</code> might have only one
  36. // child and that child node could be a <code>Text</code> node. Such a
  37. // structure model represents neither an HTML document nor a well-formed XML
  38. // document.
  39. // <p>When a <code>DocumentFragment</code> is inserted into a
  40. // <code>Document</code> (or indeed any other <code>Node</code> that may take
  41. // children) the children of the <code>DocumentFragment</code> and not the
  42. // <code>DocumentFragment</code> itself are inserted into the
  43. // <code>Node</code>. This makes the <code>DocumentFragment</code> very
  44. // useful when the user wishes to create nodes that are siblings; the
  45. // <code>DocumentFragment</code> acts as the parent of these nodes so that the
  46. // user can use the standard methods from the <code>Node</code> interface,
  47. // such as <code>insertBefore()</code> and <code>appendChild()</code>.
  48. namespace System.Xml
  49. {
  50.    
  51.     using System.Diagnostics;
  52.     using System.Xml.XPath;
  53.    
  54.     // Represents a lightweight object that is useful for tree insert
  55.     // operations.
  56.     public class XmlDocumentFragment : XmlNode
  57.     {
  58.         XmlLinkedNode lastChild;
  59.        
  60.         protected internal XmlDocumentFragment(XmlDocument ownerDocument) : base()
  61.         {
  62.             if (ownerDocument == null)
  63.                 throw new ArgumentException(Res.GetString(Res.Xdom_Node_Null_Doc));
  64.             parentNode = ownerDocument;
  65.         }
  66.        
  67.         // Gets the name of the node.
  68.         public override string Name {
  69.             get { return OwnerDocument.strDocumentFragmentName; }
  70.         }
  71.        
  72.         // Gets the name of the current node without the namespace prefix.
  73.         public override string LocalName {
  74.             get { return OwnerDocument.strDocumentFragmentName; }
  75.         }
  76.        
  77.         // Gets the type of the current node.
  78.         public override XmlNodeType NodeType {
  79.             get { return XmlNodeType.DocumentFragment; }
  80.         }
  81.        
  82.         // Gets the parent of this node (for nodes that can have parents).
  83.         public override XmlNode ParentNode {
  84.             get { return null; }
  85.         }
  86.        
  87.         // Gets the XmlDocument that contains this node.
  88.         public override XmlDocument OwnerDocument {
  89.             get { return (XmlDocument)parentNode; }
  90.         }
  91.        
  92.        
  93.         // Gets or sets the markup representing just
  94.         // the children of this node.
  95.         public override string InnerXml {
  96.             get { return base.InnerXml; }
  97.             set {
  98.                 RemoveAll();
  99.                 XmlLoader loader = new XmlLoader();
  100.                 //Hack that the content is the same element
  101.                 loader.ParsePartialContent(this, value, XmlNodeType.Element);
  102.             }
  103.         }
  104.        
  105.         // Creates a duplicate of this node.
  106.         public override XmlNode CloneNode(bool deep)
  107.         {
  108.             Debug.Assert(OwnerDocument != null);
  109.             XmlDocument doc = OwnerDocument;
  110.             XmlDocumentFragment clone = doc.CreateDocumentFragment();
  111.             if (deep)
  112.                 clone.CopyChildren(doc, this, deep);
  113.             return clone;
  114.         }
  115.        
  116.         internal override bool IsContainer {
  117.             get { return true; }
  118.         }
  119.        
  120.         internal override XmlLinkedNode LastNode {
  121.             get { return lastChild; }
  122.             set { lastChild = value; }
  123.         }
  124.        
  125.         internal override bool IsValidChildType(XmlNodeType type)
  126.         {
  127.             switch (type) {
  128.                 case XmlNodeType.Element:
  129.                 case XmlNodeType.Text:
  130.                 case XmlNodeType.EntityReference:
  131.                 case XmlNodeType.Comment:
  132.                 case XmlNodeType.Whitespace:
  133.                 case XmlNodeType.SignificantWhitespace:
  134.                 case XmlNodeType.ProcessingInstruction:
  135.                 case XmlNodeType.CDATA:
  136.                     return true;
  137.                 case XmlNodeType.XmlDeclaration:
  138.                    
  139.                     //if there is an XmlDeclaration node, it has to be the first node;
  140.                     XmlNode firstNode = FirstChild;
  141.                     if (firstNode == null || firstNode.NodeType != XmlNodeType.XmlDeclaration)
  142.                         return true;
  143.                     else
  144.                         return false;
  145.                     break;
  146.                 default:
  147.                     //not allowed to insert a second XmlDeclaration node
  148.                     return false;
  149.             }
  150.         }
  151.         internal override bool CanInsertAfter(XmlNode newChild, XmlNode refChild)
  152.         {
  153.             Debug.Assert(newChild != null);
  154.             //should be checked that newChild is not null before this function call
  155.             if (newChild.NodeType == XmlNodeType.XmlDeclaration) {
  156.                 if (refChild == null) {
  157.                     //append at the end
  158.                     return (LastNode == null);
  159.                 }
  160.                 else
  161.                     return false;
  162.             }
  163.             return true;
  164.         }
  165.        
  166.         internal override bool CanInsertBefore(XmlNode newChild, XmlNode refChild)
  167.         {
  168.             Debug.Assert(newChild != null);
  169.             //should be checked that newChild is not null before this function call
  170.             if (newChild.NodeType == XmlNodeType.XmlDeclaration) {
  171.                 return (refChild == null || refChild == FirstChild);
  172.             }
  173.             return true;
  174.         }
  175.        
  176.         // Saves the node to the specified XmlWriter.
  177.         public override void WriteTo(XmlWriter w)
  178.         {
  179.             WriteContentTo(w);
  180.         }
  181.        
  182.         // Saves all the children of the node to the specified XmlWriter.
  183.         public override void WriteContentTo(XmlWriter w)
  184.         {
  185.             foreach (XmlNode n in this) {
  186.                 n.WriteTo(w);
  187.             }
  188.         }
  189.        
  190.         internal override XPathNodeType XPNodeType {
  191.             get { return XPathNodeType.Root; }
  192.         }
  193.     }
  194. }

Developer Fusion