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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlNode.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. namespace System.Xml
  16. {
  17.     using System;
  18.     using System.IO;
  19.     using System.Collections;
  20.     using System.Text;
  21.     using System.Diagnostics;
  22.     using System.Xml.Schema;
  23.     using System.Xml.XPath;
  24.     using MS.Internal.Xml.XPath;
  25.     using System.Globalization;
  26.    
  27.     // Represents a single node in the document.
  28.     [DebuggerDisplay("{new DebuggerDisplayXmlNodeProxy(this)}")]
  29.     public abstract class XmlNode : ICloneable, IEnumerable, IXPathNavigable
  30.     {
  31.         internal XmlNode parentNode;
  32.         //this pointer is reused to save the userdata information, need to prevent internal user access the pointer directly.
  33.         internal XmlNode()
  34.         {
  35.         }
  36.        
  37.         internal XmlNode(XmlDocument doc)
  38.         {
  39.             if (doc == null)
  40.                 throw new ArgumentException(Res.GetString(Res.Xdom_Node_Null_Doc));
  41.             this.parentNode = doc;
  42.         }
  43.        
  44.         public virtual XPathNavigator CreateNavigator()
  45.         {
  46.             XmlDocument doc = OwnerDocument;
  47.             Debug.Assert(doc != null);
  48.             return doc.CreateNavigator(this);
  49.         }
  50.        
  51.         // Selects the first node that matches the xpath expression
  52.         public XmlNode SelectSingleNode(string xpath)
  53.         {
  54.             XmlNodeList list = SelectNodes(xpath);
  55.             //since SelectNodes could return null for certain node types
  56.             if ((list != null) && (list.Count > 0))
  57.                 return list[0];
  58.             else
  59.                 return null;
  60.         }
  61.        
  62.         // Selects the first node that matches the xpath expression and given namespace context.
  63.         public XmlNode SelectSingleNode(string xpath, XmlNamespaceManager nsmgr)
  64.         {
  65.             XPathNavigator xn = (this).CreateNavigator();
  66.             //if the method is called on node types like DocType, Entity, XmlDeclaration,
  67.             //the navigator returned is null. So just return null from here for those node types.
  68.             if (xn == null)
  69.                 return null;
  70.             XPathExpression exp = xn.Compile(xpath);
  71.             exp.SetContext(nsmgr);
  72.             XmlNodeList list = new XPathNodeList(xn.Select(exp));
  73.             ;
  74.             if (list.Count > 0)
  75.                 return list[0];
  76.             else
  77.                 return null;
  78.         }
  79.        
  80.         // Selects all nodes that match the xpath expression
  81.         public XmlNodeList SelectNodes(string xpath)
  82.         {
  83.             XPathNavigator n = (this).CreateNavigator();
  84.             //if the method is called on node types like DocType, Entity, XmlDeclaration,
  85.             //the navigator returned is null. So just return null from here for those node types.
  86.             if (n == null)
  87.                 return null;
  88.             return new XPathNodeList(n.Select(xpath));
  89.         }
  90.        
  91.         // Selects all nodes that match the xpath expression and given namespace context.
  92.         public XmlNodeList SelectNodes(string xpath, XmlNamespaceManager nsmgr)
  93.         {
  94.             XPathNavigator xn = (this).CreateNavigator();
  95.             //if the method is called on node types like DocType, Entity, XmlDeclaration,
  96.             //the navigator returned is null. So just return null from here for those node types.
  97.             if (xn == null)
  98.                 return null;
  99.             XPathExpression exp = xn.Compile(xpath);
  100.             exp.SetContext(nsmgr);
  101.             return new XPathNodeList(xn.Select(exp));
  102.         }
  103.        
  104.         // Gets the name of the node.
  105.         public abstract string Name {
  106.             get;
  107.         }
  108.        
  109.         // Gets or sets the value of the node.
  110.         public virtual string Value {
  111.             get { return null; }
  112.             set {
  113.                 throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, Res.GetString(Res.Xdom_Node_SetVal), NodeType.ToString()));
  114.             }
  115.         }
  116.        
  117.         // Gets the type of the current node.
  118.         public abstract XmlNodeType NodeType {
  119.             get;
  120.         }
  121.        
  122.         // Gets the parent of this node (for nodes that can have parents).
  123.         public virtual XmlNode ParentNode {
  124.             get {
  125.                 Debug.Assert(parentNode != null);
  126.                
  127.                 if (parentNode.NodeType != XmlNodeType.Document) {
  128.                     return parentNode;
  129.                 }
  130.                
  131.                 // Linear lookup through the children of the document
  132.                 XmlLinkedNode firstChild = parentNode.FirstChild as XmlLinkedNode;
  133.                 if (firstChild != null) {
  134.                     XmlLinkedNode node = firstChild;
  135.                     do {
  136.                         if (node == this) {
  137.                             return parentNode;
  138.                         }
  139.                         node = node.next;
  140.                     }
  141.                     while (node != null && node != firstChild);
  142.                 }
  143.                 return null;
  144.             }
  145.         }
  146.        
  147.         // Gets all children of this node.
  148.         public virtual XmlNodeList ChildNodes {
  149.             get { return new XmlChildNodes(this); }
  150.         }
  151.        
  152.         // Gets the node immediately preceding this node.
  153.         public virtual XmlNode PreviousSibling {
  154.             get { return null; }
  155.         }
  156.        
  157.         // Gets the node immediately following this node.
  158.         public virtual XmlNode NextSibling {
  159.             get { return null; }
  160.         }
  161.        
  162.         // Gets a XmlAttributeCollection containing the attributes
  163.         // of this node.
  164.         public virtual XmlAttributeCollection Attributes {
  165.             get { return null; }
  166.         }
  167.        
  168.         // Gets the XmlDocument that contains this node.
  169.         public virtual XmlDocument OwnerDocument {
  170.             get {
  171.                 Debug.Assert(parentNode != null);
  172.                 if (parentNode.NodeType == XmlNodeType.Document)
  173.                     return (XmlDocument)parentNode;
  174.                 return parentNode.OwnerDocument;
  175.             }
  176.         }
  177.        
  178.         // Gets the first child of this node.
  179.         public virtual XmlNode FirstChild {
  180.             get {
  181.                 XmlLinkedNode linkedNode = LastNode;
  182.                 if (linkedNode != null)
  183.                     return linkedNode.next;
  184.                
  185.                 return null;
  186.             }
  187.         }
  188.        
  189.         // Gets the last child of this node.
  190.         public virtual XmlNode LastChild {
  191.             get { return LastNode; }
  192.         }
  193.        
  194.         internal virtual bool IsContainer {
  195.             get { return false; }
  196.         }
  197.        
  198.         internal virtual XmlLinkedNode LastNode {
  199.             get { return null; }
  200.             set { }
  201.         }
  202.        
  203.         internal bool AncestorNode(XmlNode node)
  204.         {
  205.             XmlNode n = this.ParentNode;
  206.            
  207.             while (n != null && n != this) {
  208.                 if (n == node)
  209.                     return true;
  210.                 n = n.ParentNode;
  211.             }
  212.            
  213.             return false;
  214.         }
  215.        
  216.         //trace to the top to find out its parent node.
  217.         internal bool IsConnected()
  218.         {
  219.             XmlNode parent = ParentNode;
  220.             while (parent != null && !(parent.NodeType == XmlNodeType.Document))
  221.                 parent = parent.ParentNode;
  222.             return parent != null;
  223.         }
  224.        
  225.         // Inserts the specified node immediately before the specified reference node.
  226.         public virtual XmlNode InsertBefore(XmlNode newChild, XmlNode refChild)
  227.         {
  228.             if (this == newChild || AncestorNode(newChild))
  229.                 throw new ArgumentException(Res.GetString(Res.Xdom_Node_Insert_Child));
  230.            
  231.             if (refChild == null)
  232.                 return AppendChild(newChild);
  233.            
  234.             if (!IsContainer)
  235.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Insert_Contain));
  236.            
  237.             if (refChild.ParentNode != this)
  238.                 throw new ArgumentException(Res.GetString(Res.Xdom_Node_Insert_Path));
  239.            
  240.             if (newChild == refChild)
  241.                 return newChild;
  242.            
  243.             XmlDocument childDoc = newChild.OwnerDocument;
  244.             XmlDocument thisDoc = OwnerDocument;
  245.             if (childDoc != null && childDoc != thisDoc && childDoc != this)
  246.                 throw new ArgumentException(Res.GetString(Res.Xdom_Node_Insert_Context));
  247.            
  248.             if (!CanInsertBefore(newChild, refChild))
  249.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Insert_Location));
  250.            
  251.             if (newChild.ParentNode != null)
  252.                 newChild.ParentNode.RemoveChild(newChild);
  253.            
  254.             // special case for doc-fragment.
  255.             if (newChild.NodeType == XmlNodeType.DocumentFragment) {
  256.                 XmlNode first = newChild.FirstChild;
  257.                 XmlNode node = first;
  258.                 if (node != null) {
  259.                     newChild.RemoveChild(node);
  260.                     InsertBefore(node, refChild);
  261.                     // insert the rest of the children after this one.
  262.                     InsertAfter(newChild, node);
  263.                 }
  264.                 return first;
  265.             }
  266.            
  267.             if (!(newChild is XmlLinkedNode) || !IsValidChildType(newChild.NodeType))
  268.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Insert_TypeConflict));
  269.            
  270.             XmlLinkedNode newNode = (XmlLinkedNode)newChild;
  271.             XmlLinkedNode refNode = (XmlLinkedNode)refChild;
  272.            
  273.             string newChildValue = newChild.Value;
  274.             XmlNodeChangedEventArgs args = GetEventArgs(newChild, newChild.ParentNode, this, newChildValue, newChildValue, XmlNodeChangedAction.Insert);
  275.            
  276.             if (args != null)
  277.                 BeforeEvent(args);
  278.            
  279.             if (refNode == FirstChild) {
  280.                 newNode.next = refNode;
  281.                 LastNode.next = newNode;
  282.                 newNode.SetParent(this);
  283.                
  284.                 if (newNode.IsText) {
  285.                     if (refNode.IsText) {
  286.                         NestTextNodes(newNode, refNode);
  287.                     }
  288.                 }
  289.             }
  290.             else {
  291.                 XmlLinkedNode prevNode = (XmlLinkedNode)refNode.PreviousSibling;
  292.                
  293.                 newNode.next = refNode;
  294.                 prevNode.next = newNode;
  295.                 newNode.SetParent(this);
  296.                
  297.                 if (prevNode.IsText) {
  298.                     if (newNode.IsText) {
  299.                         NestTextNodes(prevNode, newNode);
  300.                         if (refNode.IsText) {
  301.                             NestTextNodes(newNode, refNode);
  302.                         }
  303.                     }
  304.                     else {
  305.                         if (refNode.IsText) {
  306.                             UnnestTextNodes(prevNode, refNode);
  307.                         }
  308.                     }
  309.                 }
  310.                 else {
  311.                     if (newNode.IsText) {
  312.                         if (refNode.IsText) {
  313.                             NestTextNodes(newNode, refNode);
  314.                         }
  315.                     }
  316.                 }
  317.             }
  318.            
  319.             if (args != null)
  320.                 AfterEvent(args);
  321.            
  322.             return newNode;
  323.         }
  324.        
  325.         // Inserts the specified node immediately after the specified reference node.
  326.         public virtual XmlNode InsertAfter(XmlNode newChild, XmlNode refChild)
  327.         {
  328.             if (this == newChild || AncestorNode(newChild))
  329.                 throw new ArgumentException(Res.GetString(Res.Xdom_Node_Insert_Child));
  330.            
  331.             if (refChild == null)
  332.                 return PrependChild(newChild);
  333.            
  334.             if (!IsContainer)
  335.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Insert_Contain));
  336.            
  337.             if (refChild.ParentNode != this)
  338.                 throw new ArgumentException(Res.GetString(Res.Xdom_Node_Insert_Path));
  339.            
  340.             if (newChild == refChild)
  341.                 return newChild;
  342.            
  343.             XmlDocument childDoc = newChild.OwnerDocument;
  344.             XmlDocument thisDoc = OwnerDocument;
  345.             if (childDoc != null && childDoc != thisDoc && childDoc != this)
  346.                 throw new ArgumentException(Res.GetString(Res.Xdom_Node_Insert_Context));
  347.            
  348.             if (!CanInsertAfter(newChild, refChild))
  349.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Insert_Location));
  350.            
  351.             if (newChild.ParentNode != null)
  352.                 newChild.ParentNode.RemoveChild(newChild);
  353.            
  354.             // special case for doc-fragment.
  355.             if (newChild.NodeType == XmlNodeType.DocumentFragment) {
  356.                 XmlNode last = refChild;
  357.                 XmlNode first = newChild.FirstChild;
  358.                 XmlNode node = first;
  359.                 while (node != null) {
  360.                     XmlNode next = node.NextSibling;
  361.                     newChild.RemoveChild(node);
  362.                     InsertAfter(node, last);
  363.                     last = node;
  364.                     node = next;
  365.                 }
  366.                 return first;
  367.             }
  368.            
  369.             if (!(newChild is XmlLinkedNode) || !IsValidChildType(newChild.NodeType))
  370.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Insert_TypeConflict));
  371.            
  372.             XmlLinkedNode newNode = (XmlLinkedNode)newChild;
  373.             XmlLinkedNode refNode = (XmlLinkedNode)refChild;
  374.            
  375.             string newChildValue = newChild.Value;
  376.             XmlNodeChangedEventArgs args = GetEventArgs(newChild, newChild.ParentNode, this, newChildValue, newChildValue, XmlNodeChangedAction.Insert);
  377.            
  378.             if (args != null)
  379.                 BeforeEvent(args);
  380.            
  381.             if (refNode == LastNode) {
  382.                 newNode.next = refNode.next;
  383.                 refNode.next = newNode;
  384.                 LastNode = newNode;
  385.                 newNode.SetParent(this);
  386.                
  387.                 if (refNode.IsText) {
  388.                     if (newNode.IsText) {
  389.                         NestTextNodes(refNode, newNode);
  390.                     }
  391.                 }
  392.             }
  393.             else {
  394.                 XmlLinkedNode nextNode = refNode.next;
  395.                
  396.                 newNode.next = nextNode;
  397.                 refNode.next = newNode;
  398.                 newNode.SetParent(this);
  399.                
  400.                 if (refNode.IsText) {
  401.                     if (newNode.IsText) {
  402.                         NestTextNodes(refNode, newNode);
  403.                         if (nextNode.IsText) {
  404.                             NestTextNodes(newNode, nextNode);
  405.                         }
  406.                     }
  407.                     else {
  408.                         if (nextNode.IsText) {
  409.                             UnnestTextNodes(refNode, nextNode);
  410.                         }
  411.                     }
  412.                 }
  413.                 else {
  414.                     if (newNode.IsText) {
  415.                         if (nextNode.IsText) {
  416.                             NestTextNodes(newNode, nextNode);
  417.                         }
  418.                     }
  419.                 }
  420.             }
  421.            
  422.            
  423.             if (args != null)
  424.                 AfterEvent(args);
  425.            
  426.             return newNode;
  427.         }
  428.        
  429.         // Replaces the child node oldChild with newChild node.
  430.         public virtual XmlNode ReplaceChild(XmlNode newChild, XmlNode oldChild)
  431.         {
  432.             XmlNode nextNode = oldChild.NextSibling;
  433.             RemoveChild(oldChild);
  434.             XmlNode node = InsertBefore(newChild, nextNode);
  435.             return oldChild;
  436.         }
  437.        
  438.         // Removes specified child node.
  439.         public virtual XmlNode RemoveChild(XmlNode oldChild)
  440.         {
  441.             if (!IsContainer)
  442.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Remove_Contain));
  443.            
  444.             if (oldChild.ParentNode != this)
  445.                 throw new ArgumentException(Res.GetString(Res.Xdom_Node_Remove_Child));
  446.            
  447.             XmlLinkedNode oldNode = (XmlLinkedNode)oldChild;
  448.            
  449.             string oldNodeValue = oldNode.Value;
  450.             XmlNodeChangedEventArgs args = GetEventArgs(oldNode, this, null, oldNodeValue, oldNodeValue, XmlNodeChangedAction.Remove);
  451.            
  452.             if (args != null)
  453.                 BeforeEvent(args);
  454.            
  455.             XmlLinkedNode lastNode = LastNode;
  456.            
  457.             if (oldNode == FirstChild) {
  458.                 if (oldNode == lastNode) {
  459.                     LastNode = null;
  460.                     oldNode.next = null;
  461.                     oldNode.SetParent(null);
  462.                 }
  463.                 else {
  464.                     XmlLinkedNode nextNode = oldNode.next;
  465.                    
  466.                     if (nextNode.IsText) {
  467.                         if (oldNode.IsText) {
  468.                             UnnestTextNodes(oldNode, nextNode);
  469.                         }
  470.                     }
  471.                    
  472.                     lastNode.next = nextNode;
  473.                     oldNode.next = null;
  474.                     oldNode.SetParent(null);
  475.                 }
  476.             }
  477.             else {
  478.                 if (oldNode == lastNode) {
  479.                     XmlLinkedNode prevNode = (XmlLinkedNode)oldNode.PreviousSibling;
  480.                     prevNode.next = oldNode.next;
  481.                     LastNode = prevNode;
  482.                     oldNode.next = null;
  483.                     oldNode.SetParent(null);
  484.                 }
  485.                 else {
  486.                     XmlLinkedNode prevNode = (XmlLinkedNode)oldNode.PreviousSibling;
  487.                     XmlLinkedNode nextNode = oldNode.next;
  488.                    
  489.                     if (nextNode.IsText) {
  490.                         if (prevNode.IsText) {
  491.                             NestTextNodes(prevNode, nextNode);
  492.                         }
  493.                         else {
  494.                             if (oldNode.IsText) {
  495.                                 UnnestTextNodes(oldNode, nextNode);
  496.                             }
  497.                         }
  498.                     }
  499.                    
  500.                     prevNode.next = nextNode;
  501.                     oldNode.next = null;
  502.                     oldNode.SetParent(null);
  503.                 }
  504.             }
  505.            
  506.             if (args != null)
  507.                 AfterEvent(args);
  508.            
  509.             return oldChild;
  510.         }
  511.        
  512.         // Adds the specified node to the beginning of the list of children of this node.
  513.         public virtual XmlNode PrependChild(XmlNode newChild)
  514.         {
  515.             return InsertBefore(newChild, FirstChild);
  516.         }
  517.        
  518.         // Adds the specified node to the end of the list of children of this node.
  519.         public virtual XmlNode AppendChild(XmlNode newChild)
  520.         {
  521.             XmlDocument thisDoc = OwnerDocument;
  522.             if (thisDoc == null) {
  523.                 thisDoc = this as XmlDocument;
  524.             }
  525.             if (!IsContainer)
  526.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Insert_Contain));
  527.            
  528.             if (this == newChild || AncestorNode(newChild))
  529.                 throw new ArgumentException(Res.GetString(Res.Xdom_Node_Insert_Child));
  530.            
  531.             if (newChild.ParentNode != null)
  532.                 newChild.ParentNode.RemoveChild(newChild);
  533.            
  534.             XmlDocument childDoc = newChild.OwnerDocument;
  535.             if (childDoc != null && childDoc != thisDoc && childDoc != this)
  536.                 throw new ArgumentException(Res.GetString(Res.Xdom_Node_Insert_Context));
  537.            
  538.             // special case for doc-fragment.
  539.             if (newChild.NodeType == XmlNodeType.DocumentFragment) {
  540.                 XmlNode first = newChild.FirstChild;
  541.                 XmlNode node = first;
  542.                 while (node != null) {
  543.                     XmlNode next = node.NextSibling;
  544.                     newChild.RemoveChild(node);
  545.                     AppendChild(node);
  546.                     node = next;
  547.                 }
  548.                 return first;
  549.             }
  550.            
  551.             if (!(newChild is XmlLinkedNode) || !IsValidChildType(newChild.NodeType))
  552.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Insert_TypeConflict));
  553.            
  554.            
  555.             if (!CanInsertAfter(newChild, LastChild))
  556.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Insert_Location));
  557.            
  558.             string newChildValue = newChild.Value;
  559.             XmlNodeChangedEventArgs args = GetEventArgs(newChild, newChild.ParentNode, this, newChildValue, newChildValue, XmlNodeChangedAction.Insert);
  560.            
  561.             if (args != null)
  562.                 BeforeEvent(args);
  563.            
  564.             XmlLinkedNode refNode = LastNode;
  565.             XmlLinkedNode newNode = (XmlLinkedNode)newChild;
  566.            
  567.             if (refNode == null) {
  568.                 newNode.next = newNode;
  569.                 LastNode = newNode;
  570.                 newNode.SetParent(this);
  571.             }
  572.             else {
  573.                 newNode.next = refNode.next;
  574.                 refNode.next = newNode;
  575.                 LastNode = newNode;
  576.                 newNode.SetParent(this);
  577.                
  578.                 if (refNode.IsText) {
  579.                     if (newNode.IsText) {
  580.                         NestTextNodes(refNode, newNode);
  581.                     }
  582.                 }
  583.             }
  584.            
  585.             if (args != null)
  586.                 AfterEvent(args);
  587.            
  588.             return newNode;
  589.         }
  590.        
  591.         //the function is provided only at Load time to speed up Load process
  592.         internal virtual XmlNode AppendChildForLoad(XmlNode newChild, XmlDocument doc)
  593.         {
  594.             XmlNodeChangedEventArgs args = doc.GetInsertEventArgsForLoad(newChild, this);
  595.            
  596.             if (args != null)
  597.                 doc.BeforeEvent(args);
  598.            
  599.             XmlLinkedNode refNode = LastNode;
  600.             XmlLinkedNode newNode = (XmlLinkedNode)newChild;
  601.            
  602.             if (refNode == null) {
  603.                 newNode.next = newNode;
  604.                 LastNode = newNode;
  605.                 newNode.SetParentForLoad(this);
  606.             }
  607.             else {
  608.                 newNode.next = refNode.next;
  609.                 refNode.next = newNode;
  610.                 LastNode = newNode;
  611.                 if (refNode.IsText && newNode.IsText) {
  612.                     NestTextNodes(refNode, newNode);
  613.                 }
  614.                 else {
  615.                     newNode.SetParentForLoad(this);
  616.                 }
  617.             }
  618.            
  619.             if (args != null)
  620.                 doc.AfterEvent(args);
  621.            
  622.             return newNode;
  623.         }
  624.        
  625.         internal virtual bool IsValidChildType(XmlNodeType type)
  626.         {
  627.             return false;
  628.         }
  629.        
  630.         internal virtual bool CanInsertBefore(XmlNode newChild, XmlNode refChild)
  631.         {
  632.             return true;
  633.         }
  634.        
  635.         internal virtual bool CanInsertAfter(XmlNode newChild, XmlNode refChild)
  636.         {
  637.             return true;
  638.         }
  639.        
  640.         // Gets a value indicating whether this node has any child nodes.
  641.         public virtual bool HasChildNodes {
  642.             get { return LastNode != null; }
  643.         }
  644.        
  645.         // Creates a duplicate of this node.
  646.         public abstract XmlNode CloneNode(bool deep);
  647.        
  648.         internal virtual void CopyChildren(XmlDocument doc, XmlNode container, bool deep)
  649.         {
  650.             for (XmlNode child = container.FirstChild; child != null; child = child.NextSibling) {
  651.                 AppendChildForLoad(child.CloneNode(deep), doc);
  652.             }
  653.         }
  654.        
  655.         // DOM Level 2
  656.        
  657.         // Puts all XmlText nodes in the full depth of the sub-tree
  658.         // underneath this XmlNode into a "normal" form where only
  659.         // markup (e.g., tags, comments, processing instructions, CDATA sections,
  660.         // and entity references) separates XmlText nodes, that is, there
  661.         // are no adjacent XmlText nodes.
  662.         public virtual void Normalize()
  663.         {
  664.             XmlNode firstChildTextLikeNode = null;
  665.             StringBuilder sb = new StringBuilder();
  666.             for (XmlNode crtChild = this.FirstChild; crtChild != null;) {
  667.                 XmlNode nextChild = crtChild.NextSibling;
  668.                 switch (crtChild.NodeType) {
  669.                     case XmlNodeType.Text:
  670.                     case XmlNodeType.Whitespace:
  671.                     case XmlNodeType.SignificantWhitespace:
  672.                        
  673.                         {
  674.                             sb.Append(crtChild.Value);
  675.                             XmlNode winner = NormalizeWinner(firstChildTextLikeNode, crtChild);
  676.                             if (winner == firstChildTextLikeNode) {
  677.                                 this.RemoveChild(crtChild);
  678.                             }
  679.                             else {
  680.                                 if (firstChildTextLikeNode != null)
  681.                                     this.RemoveChild(firstChildTextLikeNode);
  682.                                 firstChildTextLikeNode = crtChild;
  683.                             }
  684.                             break;
  685.                         }
  686.                         break;
  687.                     case XmlNodeType.Element:
  688.                        
  689.                         {
  690.                             crtChild.Normalize();
  691.                             goto default;
  692.                         }
  693.                         break;
  694.                     default:
  695.                        
  696.                         {
  697.                             if (firstChildTextLikeNode != null) {
  698.                                 firstChildTextLikeNode.Value = sb.ToString();
  699.                                 firstChildTextLikeNode = null;
  700.                             }
  701.                             sb.Remove(0, sb.Length);
  702.                             break;
  703.                         }
  704.                         break;
  705.                 }
  706.                 crtChild = nextChild;
  707.             }
  708.             if (firstChildTextLikeNode != null && sb.Length > 0)
  709.                 firstChildTextLikeNode.Value = sb.ToString();
  710.         }
  711.        
  712.         private XmlNode NormalizeWinner(XmlNode firstNode, XmlNode secondNode)
  713.         {
  714.             //first node has the priority
  715.             if (firstNode == null)
  716.                 return secondNode;
  717.             Debug.Assert(firstNode.NodeType == XmlNodeType.Text || firstNode.NodeType == XmlNodeType.SignificantWhitespace || firstNode.NodeType == XmlNodeType.Whitespace || secondNode.NodeType == XmlNodeType.Text || secondNode.NodeType == XmlNodeType.SignificantWhitespace || secondNode.NodeType == XmlNodeType.Whitespace);
  718.             if (firstNode.NodeType == XmlNodeType.Text)
  719.                 return firstNode;
  720.             if (secondNode.NodeType == XmlNodeType.Text)
  721.                 return secondNode;
  722.             if (firstNode.NodeType == XmlNodeType.SignificantWhitespace)
  723.                 return firstNode;
  724.             if (secondNode.NodeType == XmlNodeType.SignificantWhitespace)
  725.                 return secondNode;
  726.             if (firstNode.NodeType == XmlNodeType.Whitespace)
  727.                 return firstNode;
  728.             if (secondNode.NodeType == XmlNodeType.Whitespace)
  729.                 return secondNode;
  730.             Debug.Assert(true, "shouldn't have fall through here.");
  731.             return null;
  732.         }
  733.        
  734.         // Test if the DOM implementation implements a specific feature.
  735.         public virtual bool Supports(string feature, string version)
  736.         {
  737.             if (String.Compare("XML", feature, StringComparison.OrdinalIgnoreCase) == 0) {
  738.                 if (version == null || version == "1.0" || version == "2.0")
  739.                     return true;
  740.             }
  741.             return false;
  742.         }
  743.        
  744.         // Gets the namespace URI of this node.
  745.         public virtual string NamespaceURI {
  746.             get { return string.Empty; }
  747.         }
  748.        
  749.         // Gets or sets the namespace prefix of this node.
  750.         public virtual string Prefix {
  751.             get { return string.Empty; }
  752.             set { }
  753.         }
  754.        
  755.         // Gets the name of the node without the namespace prefix.
  756.         public abstract string LocalName {
  757.             get;
  758.         }
  759.        
  760.         // Microsoft extensions
  761.        
  762.         // Gets a value indicating whether the node is read-only.
  763.         public virtual bool IsReadOnly {
  764.             get {
  765.                 XmlDocument doc = OwnerDocument;
  766.                 return HasReadOnlyParent(this);
  767.             }
  768.         }
  769.        
  770.         static internal bool HasReadOnlyParent(XmlNode n)
  771.         {
  772.             while (n != null) {
  773.                 switch (n.NodeType) {
  774.                     case XmlNodeType.EntityReference:
  775.                     case XmlNodeType.Entity:
  776.                         return true;
  777.                     case XmlNodeType.Attribute:
  778.                        
  779.                         n = ((XmlAttribute)n).OwnerElement;
  780.                         break;
  781.                     default:
  782.                        
  783.                         n = n.ParentNode;
  784.                         break;
  785.                 }
  786.             }
  787.             return false;
  788.         }
  789.        
  790.         // Creates a duplicate of this node.
  791.         public virtual XmlNode Clone()
  792.         {
  793.             return this.CloneNode(true);
  794.         }
  795.        
  796.         object ICloneable.Clone()
  797.         {
  798.             return this.CloneNode(true);
  799.         }
  800.        
  801.         // Provides a simple ForEach-style iteration over the
  802.         // collection of nodes in this XmlNamedNodeMap.
  803.         IEnumerator IEnumerable.GetEnumerator()
  804.         {
  805.             return new XmlChildEnumerator(this);
  806.         }
  807.        
  808.         public IEnumerator GetEnumerator()
  809.         {
  810.             return new XmlChildEnumerator(this);
  811.         }
  812.        
  813.         private void AppendChildText(StringBuilder builder)
  814.         {
  815.             for (XmlNode child = FirstChild; child != null; child = child.NextSibling) {
  816.                 if (child.FirstChild == null) {
  817.                     if (child.NodeType == XmlNodeType.Text || child.NodeType == XmlNodeType.CDATA || child.NodeType == XmlNodeType.Whitespace || child.NodeType == XmlNodeType.SignificantWhitespace)
  818.                         builder.Append(child.InnerText);
  819.                 }
  820.                 else {
  821.                     child.AppendChildText(builder);
  822.                 }
  823.             }
  824.         }
  825.        
  826.         // Gets or sets the concatenated values of the node and
  827.         // all its children.
  828.         public virtual string InnerText {
  829.             get {
  830.                 XmlNode fc = FirstChild;
  831.                 if (fc == null) {
  832.                     return string.Empty;
  833.                 }
  834.                 if (fc.NextSibling == null) {
  835.                     XmlNodeType nodeType = fc.NodeType;
  836.                     switch (nodeType) {
  837.                         case XmlNodeType.Text:
  838.                         case XmlNodeType.CDATA:
  839.                         case XmlNodeType.Whitespace:
  840.                         case XmlNodeType.SignificantWhitespace:
  841.                             return fc.Value;
  842.                     }
  843.                 }
  844.                 StringBuilder builder = new StringBuilder();
  845.                 AppendChildText(builder);
  846.                 return builder.ToString();
  847.             }
  848.            
  849.             set {
  850.                 XmlNode firstChild = FirstChild;
  851.                 //there is one child
  852.                 // and exactly one
  853.                 //which is a text node
  854.                 if (firstChild != null && firstChild.NextSibling == null && firstChild.NodeType == XmlNodeType.Text) {
  855.                     //this branch is for perf reason and event fired when TextNode.Value is changed
  856.                     firstChild.Value = value;
  857.                 }
  858.                 else {
  859.                     RemoveAll();
  860.                     AppendChild(OwnerDocument.CreateTextNode(value));
  861.                 }
  862.             }
  863.         }
  864.        
  865.         // Gets the markup representing this node and all its children.
  866.         public virtual string OuterXml {
  867.             get {
  868.                 StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
  869.                 XmlDOMTextWriter xw = new XmlDOMTextWriter(sw);
  870.                 try {
  871.                     WriteTo(xw);
  872.                 }
  873.                 finally {
  874.                     xw.Close();
  875.                 }
  876.                 return sw.ToString();
  877.             }
  878.         }
  879.        
  880.         // Gets or sets the markup representing just the children of this node.
  881.         public virtual string InnerXml {
  882.             get {
  883.                 StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
  884.                 XmlDOMTextWriter xw = new XmlDOMTextWriter(sw);
  885.                 try {
  886.                     WriteContentTo(xw);
  887.                 }
  888.                 finally {
  889.                     xw.Close();
  890.                 }
  891.                 return sw.ToString();
  892.             }
  893.            
  894.             set {
  895.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Set_InnerXml));
  896.             }
  897.         }
  898.        
  899.         public virtual IXmlSchemaInfo SchemaInfo {
  900.             get { return XmlDocument.NotKnownSchemaInfo; }
  901.         }
  902.        
  903.         public virtual string BaseURI {
  904.             get {
  905.                 XmlNode curNode = this.ParentNode;
  906.                 //save one while loop since if going to here, the nodetype of this node can't be document, entity and entityref
  907.                 while (curNode != null) {
  908.                     XmlNodeType nt = curNode.NodeType;
  909.                     //EntityReference's children come from the dtd where they are defined.
  910.                     //we need to investigate the same thing for entity's children if they are defined in an external dtd file.
  911.                     if (nt == XmlNodeType.EntityReference)
  912.                         return ((XmlEntityReference)curNode).ChildBaseURI;
  913.                     if (nt == XmlNodeType.Document || nt == XmlNodeType.Entity || nt == XmlNodeType.Attribute)
  914.                         return curNode.BaseURI;
  915.                     curNode = curNode.ParentNode;
  916.                 }
  917.                 return String.Empty;
  918.             }
  919.         }
  920.        
  921.         // Saves the current node to the specified XmlWriter.
  922.         public abstract void WriteTo(XmlWriter w);
  923.        
  924.         // Saves all the children of the node to the specified XmlWriter.
  925.         public abstract void WriteContentTo(XmlWriter w);
  926.        
  927.         // Removes all the children and/or attributes
  928.         // of the current node.
  929.         public virtual void RemoveAll()
  930.         {
  931.             XmlNode child = FirstChild;
  932.             XmlNode sibling = null;
  933.            
  934.             while (child != null) {
  935.                 sibling = child.NextSibling;
  936.                 RemoveChild(child);
  937.                 child = sibling;
  938.             }
  939.         }
  940.        
  941.         internal XmlDocument Document {
  942.             get {
  943.                 if (NodeType == XmlNodeType.Document)
  944.                     return (XmlDocument)this;
  945.                 return OwnerDocument;
  946.             }
  947.         }
  948.        
  949.         // Looks up the closest xmlns declaration for the given
  950.         // prefix that is in scope for the current node and returns
  951.         // the namespace URI in the declaration.
  952.         public virtual string GetNamespaceOfPrefix(string prefix)
  953.         {
  954.             string namespaceName = GetNamespaceOfPrefixStrict(prefix);
  955.             return namespaceName != null ? namespaceName : string.Empty;
  956.         }
  957.        
  958.         internal string GetNamespaceOfPrefixStrict(string prefix)
  959.         {
  960.             XmlDocument doc = Document;
  961.             if (doc != null) {
  962.                 prefix = doc.NameTable.Get(prefix);
  963.                 if (prefix == null)
  964.                     return null;
  965.                
  966.                 XmlNode node = this;
  967.                 while (node != null) {
  968.                     if (node.NodeType == XmlNodeType.Element) {
  969.                         XmlElement elem = (XmlElement)node;
  970.                         if (elem.HasAttributes) {
  971.                             XmlAttributeCollection attrs = elem.Attributes;
  972.                             if (prefix.Length == 0) {
  973.                                 for (int iAttr = 0; iAttr < attrs.Count; iAttr++) {
  974.                                     XmlAttribute attr = attrs[iAttr];
  975.                                     if (attr.Prefix.Length == 0) {
  976.                                         if (Ref.Equal(attr.LocalName, doc.strXmlns)) {
  977.                                             return attr.Value;
  978.                                             // found xmlns
  979.                                         }
  980.                                     }
  981.                                 }
  982.                             }
  983.                             else {
  984.                                 for (int iAttr = 0; iAttr < attrs.Count; iAttr++) {
  985.                                     XmlAttribute attr = attrs[iAttr];
  986.                                     if (Ref.Equal(attr.Prefix, doc.strXmlns)) {
  987.                                         if (Ref.Equal(attr.LocalName, prefix)) {
  988.                                             return attr.Value;
  989.                                             // found xmlns:prefix
  990.                                         }
  991.                                     }
  992.                                     else if (Ref.Equal(attr.Prefix, prefix)) {
  993.                                         return attr.NamespaceURI;
  994.                                         // found prefix:attr
  995.                                     }
  996.                                 }
  997.                             }
  998.                         }
  999.                         if (Ref.Equal(node.Prefix, prefix)) {
  1000.                             return node.NamespaceURI;
  1001.                         }
  1002.                         node = node.ParentNode;
  1003.                     }
  1004.                     else if (node.NodeType == XmlNodeType.Attribute) {
  1005.                         node = ((XmlAttribute)node).OwnerElement;
  1006.                     }
  1007.                     else {
  1008.                         node = node.ParentNode;
  1009.                     }
  1010.                 }
  1011.                 if (Ref.Equal(doc.strXml, prefix)) {
  1012.                     // xmlns:xml
  1013.                     return doc.strReservedXml;
  1014.                 }
  1015.                 else if (Ref.Equal(doc.strXmlns, prefix)) {
  1016.                     // xmlns:xmlns
  1017.                     return doc.strReservedXmlns;
  1018.                 }
  1019.             }
  1020.             return null;
  1021.         }
  1022.        
  1023.         // Looks up the closest xmlns declaration for the given namespace
  1024.         // URI that is in scope for the current node and returns
  1025.         // the prefix defined in that declaration.
  1026.         public virtual string GetPrefixOfNamespace(string namespaceURI)
  1027.         {
  1028.             string prefix = GetPrefixOfNamespaceStrict(namespaceURI);
  1029.             return prefix != null ? prefix : string.Empty;
  1030.         }
  1031.        
  1032.         internal string GetPrefixOfNamespaceStrict(string namespaceURI)
  1033.         {
  1034.             XmlDocument doc = Document;
  1035.             if (doc != null) {
  1036.                 namespaceURI = doc.NameTable.Add(namespaceURI);
  1037.                
  1038.                 XmlNode node = this;
  1039.                 while (node != null) {
  1040.                     if (node.NodeType == XmlNodeType.Element) {
  1041.                         XmlElement elem = (XmlElement)node;
  1042.                         if (elem.HasAttributes) {
  1043.                             XmlAttributeCollection attrs = elem.Attributes;
  1044.                             for (int iAttr = 0; iAttr < attrs.Count; iAttr++) {
  1045.                                 XmlAttribute attr = attrs[iAttr];
  1046.                                 if (attr.Prefix.Length == 0) {
  1047.                                     if (Ref.Equal(attr.LocalName, doc.strXmlns)) {
  1048.                                         if (attr.Value == namespaceURI) {
  1049.                                             return string.Empty;
  1050.                                             // found xmlns="namespaceURI"
  1051.                                         }
  1052.                                     }
  1053.                                 }
  1054.                                 else if (Ref.Equal(attr.Prefix, doc.strXmlns)) {
  1055.                                     if (attr.Value == namespaceURI) {
  1056.                                         return attr.LocalName;
  1057.                                         // found xmlns:prefix="namespaceURI"
  1058.                                     }
  1059.                                 }
  1060.                                 else if (Ref.Equal(attr.NamespaceURI, namespaceURI)) {
  1061.                                     return attr.Prefix;
  1062.                                     // found prefix:attr
  1063.                                     // with prefix bound to namespaceURI
  1064.                                 }
  1065.                             }
  1066.                         }
  1067.                         if (Ref.Equal(node.NamespaceURI, namespaceURI)) {
  1068.                             return node.Prefix;
  1069.                         }
  1070.                         node = node.ParentNode;
  1071.                     }
  1072.                     else if (node.NodeType == XmlNodeType.Attribute) {
  1073.                         node = ((XmlAttribute)node).OwnerElement;
  1074.                     }
  1075.                     else {
  1076.                         node = node.ParentNode;
  1077.                     }
  1078.                 }
  1079.                 if (Ref.Equals(doc.strReservedXml, namespaceURI)) {
  1080.                     // xmlns:xml
  1081.                     return doc.strXml;
  1082.                 }
  1083.                 else if (Ref.Equals(doc.strReservedXmlns, namespaceURI)) {
  1084.                     // xmlns:xmlns
  1085.                     return doc.strXmlns;
  1086.                 }
  1087.             }
  1088.             return null;
  1089.         }
  1090.        
  1091.         // Retrieves the first child element with the specified name.
  1092.         public virtual XmlElement this[string name]
  1093.         {
  1094.             get {
  1095.                 for (XmlNode n = FirstChild; n != null; n = n.NextSibling) {
  1096.                     if (n.NodeType == XmlNodeType.Element && n.Name == name)
  1097.                         return (XmlElement)n;
  1098.                 }
  1099.                 return null;
  1100.             }
  1101.         }
  1102.        
  1103.         // Retrieves the first child element with the specified LocalName and
  1104.         // NamespaceURI.
  1105.         public virtual XmlElement this[string localname, string ns]
  1106.         {
  1107.             get {
  1108.                 for (XmlNode n = FirstChild; n != null; n = n.NextSibling) {
  1109.                     if (n.NodeType == XmlNodeType.Element && n.LocalName == localname && n.NamespaceURI == ns)
  1110.                         return (XmlElement)n;
  1111.                 }
  1112.                 return null;
  1113.             }
  1114.         }
  1115.        
  1116.        
  1117.         internal virtual void SetParent(XmlNode node)
  1118.         {
  1119.             if (node == null) {
  1120.                 this.parentNode = OwnerDocument;
  1121.             }
  1122.             else {
  1123.                 this.parentNode = node;
  1124.             }
  1125.         }
  1126.        
  1127.         internal virtual void SetParentForLoad(XmlNode node)
  1128.         {
  1129.             this.parentNode = node;
  1130.         }
  1131.        
  1132.         static internal void SplitName(string name, out string prefix, out string localName)
  1133.         {
  1134.             int colonPos = name.IndexOf(':');
  1135.             // ordinal compare
  1136.             if (-1 == colonPos || 0 == colonPos || name.Length - 1 == colonPos) {
  1137.                 prefix = string.Empty;
  1138.                 localName = name;
  1139.             }
  1140.             else {
  1141.                 prefix = name.Substring(0, colonPos);
  1142.                 localName = name.Substring(colonPos + 1);
  1143.             }
  1144.         }
  1145.        
  1146.         internal virtual XmlNode FindChild(XmlNodeType type)
  1147.         {
  1148.             for (XmlNode child = FirstChild; child != null; child = child.NextSibling) {
  1149.                 if (child.NodeType == type) {
  1150.                     return child;
  1151.                 }
  1152.             }
  1153.             return null;
  1154.         }
  1155.        
  1156.         internal virtual XmlNodeChangedEventArgs GetEventArgs(XmlNode node, XmlNode oldParent, XmlNode newParent, string oldValue, string newValue, XmlNodeChangedAction action)
  1157.         {
  1158.             XmlDocument doc = OwnerDocument;
  1159.             if (doc != null) {
  1160.                 if (!doc.IsLoading) {
  1161.                     if (((newParent != null && newParent.IsReadOnly) || (oldParent != null && oldParent.IsReadOnly)))
  1162.                         throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Modify_ReadOnly));
  1163.                 }
  1164.                 return doc.GetEventArgs(node, oldParent, newParent, oldValue, newValue, action);
  1165.             }
  1166.             return null;
  1167.         }
  1168.        
  1169.         internal virtual void BeforeEvent(XmlNodeChangedEventArgs args)
  1170.         {
  1171.             if (args != null)
  1172.                 OwnerDocument.BeforeEvent(args);
  1173.         }
  1174.        
  1175.         internal virtual void AfterEvent(XmlNodeChangedEventArgs args)
  1176.         {
  1177.             if (args != null)
  1178.                 OwnerDocument.AfterEvent(args);
  1179.         }
  1180.        
  1181.         internal virtual XmlSpace XmlSpace {
  1182.             get {
  1183.                 XmlNode node = this;
  1184.                 XmlElement elem = null;
  1185.                 do {
  1186.                     elem = node as XmlElement;
  1187.                     if (elem != null && elem.HasAttribute("xml:space")) {
  1188.                         string xmlSpaceVal = elem.GetAttribute("xml:space");
  1189.                         if (0 == String.Compare(xmlSpaceVal, "default", StringComparison.OrdinalIgnoreCase))
  1190.                             return XmlSpace.Default;
  1191.                         else if (0 == String.Compare(xmlSpaceVal, "preserve", StringComparison.OrdinalIgnoreCase))
  1192.                             return XmlSpace.Preserve;
  1193.                         //should we throw exception if value is otherwise?
  1194.                     }
  1195.                     node = node.ParentNode;
  1196.                 }
  1197.                 while (node != null);
  1198.                 return XmlSpace.None;
  1199.             }
  1200.         }
  1201.        
  1202.         internal virtual string XmlLang {
  1203.             get {
  1204.                 XmlNode node = this;
  1205.                 XmlElement elem = null;
  1206.                 do {
  1207.                     elem = node as XmlElement;
  1208.                     if (elem != null) {
  1209.                         if (elem.HasAttribute("xml:lang"))
  1210.                             return elem.GetAttribute("xml:lang");
  1211.                     }
  1212.                     node = node.ParentNode;
  1213.                 }
  1214.                 while (node != null);
  1215.                 return String.Empty;
  1216.             }
  1217.         }
  1218.        
  1219.         internal virtual XPathNodeType XPNodeType {
  1220.             get { return (XPathNodeType)(-1); }
  1221.         }
  1222.        
  1223.         internal virtual string XPLocalName {
  1224.             get { return string.Empty; }
  1225.         }
  1226.        
  1227.         internal virtual string GetXPAttribute(string localName, string namespaceURI)
  1228.         {
  1229.             return String.Empty;
  1230.         }
  1231.        
  1232.         internal virtual bool IsText {
  1233.             get { return false; }
  1234.         }
  1235.        
  1236.         internal virtual XmlNode PreviousText {
  1237.             get { return null; }
  1238.         }
  1239.        
  1240.         static internal void NestTextNodes(XmlNode prevNode, XmlNode nextNode)
  1241.         {
  1242.             Debug.Assert(prevNode.IsText);
  1243.             Debug.Assert(nextNode.IsText);
  1244.            
  1245.             nextNode.parentNode = prevNode;
  1246.         }
  1247.        
  1248.         static internal void UnnestTextNodes(XmlNode prevNode, XmlNode nextNode)
  1249.         {
  1250.             Debug.Assert(prevNode.IsText);
  1251.             Debug.Assert(nextNode.IsText);
  1252.            
  1253.             nextNode.parentNode = prevNode.ParentNode;
  1254.         }
  1255.     }
  1256.    
  1257.     internal struct DebuggerDisplayXmlNodeProxy
  1258.     {
  1259.         private XmlNode node;
  1260.        
  1261.         public DebuggerDisplayXmlNodeProxy(XmlNode node)
  1262.         {
  1263.             this.node = node;
  1264.         }
  1265.        
  1266.         public override string ToString()
  1267.         {
  1268.             XmlNodeType nodeType = node.NodeType;
  1269.             string result = nodeType.ToString();
  1270.             switch (nodeType) {
  1271.                 case XmlNodeType.Element:
  1272.                 case XmlNodeType.EntityReference:
  1273.                     result += ", Name=\"" + node.Name + "\"";
  1274.                     break;
  1275.                 case XmlNodeType.Attribute:
  1276.                 case XmlNodeType.ProcessingInstruction:
  1277.                     result += ", Name=\"" + node.Name + "\", Value=\"" + XmlConvert.EscapeValueForDebuggerDisplay(node.Value) + "\"";
  1278.                     break;
  1279.                 case XmlNodeType.Text:
  1280.                 case XmlNodeType.CDATA:
  1281.                 case XmlNodeType.Comment:
  1282.                 case XmlNodeType.Whitespace:
  1283.                 case XmlNodeType.SignificantWhitespace:
  1284.                 case XmlNodeType.XmlDeclaration:
  1285.                     result += ", Value=\"" + XmlConvert.EscapeValueForDebuggerDisplay(node.Value) + "\"";
  1286.                     break;
  1287.                 case XmlNodeType.DocumentType:
  1288.                     XmlDocumentType documentType = (XmlDocumentType)node;
  1289.                     result += ", Name=\"" + documentType.Name + "\", SYSTEM=\"" + documentType.SystemId + "\", PUBLIC=\"" + documentType.PublicId + "\", Value=\"" + XmlConvert.EscapeValueForDebuggerDisplay(documentType.InternalSubset) + "\"";
  1290.                     break;
  1291.                 default:
  1292.                     break;
  1293.             }
  1294.             return result;
  1295.         }
  1296.     }
  1297. }

Developer Fusion