The Labs \ Source Viewer \ SSCLI \ System.Xml.XPath \ DebuggerDisplayProxy

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XPathNavigator.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. using System.ComponentModel;
  16. using System.IO;
  17. using System.Collections;
  18. using System.Collections.Generic;
  19. using System.Globalization;
  20. using System.Xml.Schema;
  21. using System.Diagnostics;
  22. using System.Security;
  23. using System.Security.Policy;
  24. using System.Security.Permissions;
  25. using System.Text;
  26. using System.Xml;
  27. using MS.Internal.Xml.Cache;
  28. using MS.Internal.Xml.XPath;
  29. namespace System.Xml.XPath
  30. {
  31.     // Provides a navigation interface API using XPath data model.
  32.     [DebuggerDisplay("{new DebuggerDisplayProxy(this)}")]
  33.     public abstract class XPathNavigator : XPathItem, ICloneable, IXPathNavigable, IXmlNamespaceResolver
  34.     {
  35.         static internal readonly XPathNavigatorKeyComparer comparer = new XPathNavigatorKeyComparer();
  36.        
  37.         //-----------------------------------------------
  38.         // Object
  39.         //-----------------------------------------------
  40.        
  41.         public override string ToString()
  42.         {
  43.             return Value;
  44.         }
  45.        
  46.         //-----------------------------------------------
  47.         // XPathItem
  48.         //-----------------------------------------------
  49.        
  50.         public override sealed bool IsNode {
  51.             get { return true; }
  52.         }
  53.        
  54.         public override XmlSchemaType XmlType {
  55.             get {
  56.                 IXmlSchemaInfo schemaInfo = SchemaInfo;
  57.                 if (schemaInfo != null) {
  58.                     if (schemaInfo.Validity == XmlSchemaValidity.Valid) {
  59.                         XmlSchemaType memberType = schemaInfo.MemberType;
  60.                         if (memberType != null) {
  61.                             return memberType;
  62.                         }
  63.                         return schemaInfo.SchemaType;
  64.                     }
  65.                 }
  66.                 return null;
  67.             }
  68.         }
  69.        
  70.         public virtual void SetValue(string value)
  71.         {
  72.             throw new NotSupportedException();
  73.         }
  74.        
  75.         public override object TypedValue {
  76.             get {
  77.                 IXmlSchemaInfo schemaInfo = SchemaInfo;
  78.                 XmlSchemaType schemaType;
  79.                 XmlSchemaDatatype datatype;
  80.                 if (schemaInfo != null) {
  81.                     if (schemaInfo.Validity == XmlSchemaValidity.Valid) {
  82.                         schemaType = schemaInfo.MemberType;
  83.                         if (schemaType == null) {
  84.                             schemaType = schemaInfo.SchemaType;
  85.                         }
  86.                         if (schemaType != null) {
  87.                             datatype = schemaType.Datatype;
  88.                             if (datatype != null) {
  89.                                 return schemaType.ValueConverter.ChangeType(Value, datatype.ValueType, this);
  90.                             }
  91.                         }
  92.                     }
  93.                     else {
  94.                         schemaType = schemaInfo.SchemaType;
  95.                         if (schemaType != null) {
  96.                             datatype = schemaType.Datatype;
  97.                             if (datatype != null) {
  98.                                 return schemaType.ValueConverter.ChangeType(datatype.ParseValue(Value, NameTable, this), datatype.ValueType, this);
  99.                             }
  100.                         }
  101.                     }
  102.                 }
  103.                 return Value;
  104.             }
  105.         }
  106.        
  107.         public virtual void SetTypedValue(object typedValue)
  108.         {
  109.             if (typedValue == null) {
  110.                 throw new ArgumentNullException("typedValue");
  111.             }
  112.             switch (NodeType) {
  113.                 case XPathNodeType.Element:
  114.                 case XPathNodeType.Attribute:
  115.                     break;
  116.                 default:
  117.                     throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  118.                     break;
  119.             }
  120.             string value = null;
  121.             IXmlSchemaInfo schemaInfo = SchemaInfo;
  122.             if (schemaInfo != null) {
  123.                 XmlSchemaType schemaType = schemaInfo.SchemaType;
  124.                 if (schemaType != null) {
  125.                     value = schemaType.ValueConverter.ToString(typedValue, this);
  126.                     XmlSchemaDatatype datatype = schemaType.Datatype;
  127.                     if (datatype != null) {
  128.                         datatype.ParseValue(value, NameTable, this);
  129.                     }
  130.                 }
  131.             }
  132.             if (value == null) {
  133.                 value = XmlUntypedConverter.Untyped.ToString(typedValue, this);
  134.             }
  135.             SetValue(value);
  136.         }
  137.        
  138.         public override Type ValueType {
  139.             get {
  140.                 IXmlSchemaInfo schemaInfo = SchemaInfo;
  141.                 XmlSchemaType schemaType;
  142.                 XmlSchemaDatatype datatype;
  143.                 if (schemaInfo != null) {
  144.                     if (schemaInfo.Validity == XmlSchemaValidity.Valid) {
  145.                         schemaType = schemaInfo.MemberType;
  146.                         if (schemaType == null) {
  147.                             schemaType = schemaInfo.SchemaType;
  148.                         }
  149.                         if (schemaType != null) {
  150.                             datatype = schemaType.Datatype;
  151.                             if (datatype != null) {
  152.                                 return datatype.ValueType;
  153.                             }
  154.                         }
  155.                     }
  156.                     else {
  157.                         schemaType = schemaInfo.SchemaType;
  158.                         if (schemaType != null) {
  159.                             datatype = schemaType.Datatype;
  160.                             if (datatype != null) {
  161.                                 return datatype.ValueType;
  162.                             }
  163.                         }
  164.                     }
  165.                 }
  166.                 return typeof(string);
  167.             }
  168.         }
  169.        
  170.         public override bool ValueAsBoolean {
  171.             get {
  172.                 IXmlSchemaInfo schemaInfo = SchemaInfo;
  173.                 XmlSchemaType schemaType;
  174.                 XmlSchemaDatatype datatype;
  175.                 if (schemaInfo != null) {
  176.                     if (schemaInfo.Validity == XmlSchemaValidity.Valid) {
  177.                         schemaType = schemaInfo.MemberType;
  178.                         if (schemaType == null) {
  179.                             schemaType = schemaInfo.SchemaType;
  180.                         }
  181.                         if (schemaType != null) {
  182.                             return schemaType.ValueConverter.ToBoolean(Value);
  183.                         }
  184.                     }
  185.                     else {
  186.                         schemaType = schemaInfo.SchemaType;
  187.                         if (schemaType != null) {
  188.                             datatype = schemaType.Datatype;
  189.                             if (datatype != null) {
  190.                                 return schemaType.ValueConverter.ToBoolean(datatype.ParseValue(Value, NameTable, this));
  191.                             }
  192.                         }
  193.                     }
  194.                 }
  195.                 return XmlUntypedConverter.Untyped.ToBoolean(Value);
  196.             }
  197.         }
  198.        
  199.         public override DateTime ValueAsDateTime {
  200.             get {
  201.                 IXmlSchemaInfo schemaInfo = SchemaInfo;
  202.                 XmlSchemaType schemaType;
  203.                 XmlSchemaDatatype datatype;
  204.                 if (schemaInfo != null) {
  205.                     if (schemaInfo.Validity == XmlSchemaValidity.Valid) {
  206.                         schemaType = schemaInfo.MemberType;
  207.                         if (schemaType == null) {
  208.                             schemaType = schemaInfo.SchemaType;
  209.                         }
  210.                         if (schemaType != null) {
  211.                             return schemaType.ValueConverter.ToDateTime(Value);
  212.                         }
  213.                     }
  214.                     else {
  215.                         schemaType = schemaInfo.SchemaType;
  216.                         if (schemaType != null) {
  217.                             datatype = schemaType.Datatype;
  218.                             if (datatype != null) {
  219.                                 return schemaType.ValueConverter.ToDateTime(datatype.ParseValue(Value, NameTable, this));
  220.                             }
  221.                         }
  222.                     }
  223.                 }
  224.                 return XmlUntypedConverter.Untyped.ToDateTime(Value);
  225.             }
  226.         }
  227.        
  228.         public override double ValueAsDouble {
  229.             get {
  230.                 IXmlSchemaInfo schemaInfo = SchemaInfo;
  231.                 XmlSchemaType schemaType;
  232.                 XmlSchemaDatatype datatype;
  233.                 if (schemaInfo != null) {
  234.                     if (schemaInfo.Validity == XmlSchemaValidity.Valid) {
  235.                         schemaType = schemaInfo.MemberType;
  236.                         if (schemaType == null) {
  237.                             schemaType = schemaInfo.SchemaType;
  238.                         }
  239.                         if (schemaType != null) {
  240.                             return schemaType.ValueConverter.ToDouble(Value);
  241.                         }
  242.                     }
  243.                     else {
  244.                         schemaType = schemaInfo.SchemaType;
  245.                         if (schemaType != null) {
  246.                             datatype = schemaType.Datatype;
  247.                             if (datatype != null) {
  248.                                 return schemaType.ValueConverter.ToDouble(datatype.ParseValue(Value, NameTable, this));
  249.                             }
  250.                         }
  251.                     }
  252.                 }
  253.                 return XmlUntypedConverter.Untyped.ToDouble(Value);
  254.             }
  255.         }
  256.        
  257.         public override int ValueAsInt {
  258.             get {
  259.                 IXmlSchemaInfo schemaInfo = SchemaInfo;
  260.                 XmlSchemaType schemaType;
  261.                 XmlSchemaDatatype datatype;
  262.                 if (schemaInfo != null) {
  263.                     if (schemaInfo.Validity == XmlSchemaValidity.Valid) {
  264.                         schemaType = schemaInfo.MemberType;
  265.                         if (schemaType == null) {
  266.                             schemaType = schemaInfo.SchemaType;
  267.                         }
  268.                         if (schemaType != null) {
  269.                             return schemaType.ValueConverter.ToInt32(Value);
  270.                         }
  271.                     }
  272.                     else {
  273.                         schemaType = schemaInfo.SchemaType;
  274.                         if (schemaType != null) {
  275.                             datatype = schemaType.Datatype;
  276.                             if (datatype != null) {
  277.                                 return schemaType.ValueConverter.ToInt32(datatype.ParseValue(Value, NameTable, this));
  278.                             }
  279.                         }
  280.                     }
  281.                 }
  282.                 return XmlUntypedConverter.Untyped.ToInt32(Value);
  283.             }
  284.         }
  285.        
  286.         public override long ValueAsLong {
  287.             get {
  288.                 IXmlSchemaInfo schemaInfo = SchemaInfo;
  289.                 XmlSchemaType schemaType;
  290.                 XmlSchemaDatatype datatype;
  291.                 if (schemaInfo != null) {
  292.                     if (schemaInfo.Validity == XmlSchemaValidity.Valid) {
  293.                         schemaType = schemaInfo.MemberType;
  294.                         if (schemaType == null) {
  295.                             schemaType = schemaInfo.SchemaType;
  296.                         }
  297.                         if (schemaType != null) {
  298.                             return schemaType.ValueConverter.ToInt64(Value);
  299.                         }
  300.                     }
  301.                     else {
  302.                         schemaType = schemaInfo.SchemaType;
  303.                         if (schemaType != null) {
  304.                             datatype = schemaType.Datatype;
  305.                             if (datatype != null) {
  306.                                 return schemaType.ValueConverter.ToInt64(datatype.ParseValue(Value, NameTable, this));
  307.                             }
  308.                         }
  309.                     }
  310.                 }
  311.                 return XmlUntypedConverter.Untyped.ToInt64(Value);
  312.             }
  313.         }
  314.        
  315.         public override object ValueAs(Type returnType, IXmlNamespaceResolver nsResolver)
  316.         {
  317.             if (nsResolver == null) {
  318.                 nsResolver = this;
  319.             }
  320.             IXmlSchemaInfo schemaInfo = SchemaInfo;
  321.             XmlSchemaType schemaType;
  322.             XmlSchemaDatatype datatype;
  323.             if (schemaInfo != null) {
  324.                 if (schemaInfo.Validity == XmlSchemaValidity.Valid) {
  325.                     schemaType = schemaInfo.MemberType;
  326.                     if (schemaType == null) {
  327.                         schemaType = schemaInfo.SchemaType;
  328.                     }
  329.                     if (schemaType != null) {
  330.                         return schemaType.ValueConverter.ChangeType(Value, returnType, nsResolver);
  331.                     }
  332.                 }
  333.                 else {
  334.                     schemaType = schemaInfo.SchemaType;
  335.                     if (schemaType != null) {
  336.                         datatype = schemaType.Datatype;
  337.                         if (datatype != null) {
  338.                             return schemaType.ValueConverter.ChangeType(datatype.ParseValue(Value, NameTable, nsResolver), returnType, nsResolver);
  339.                         }
  340.                     }
  341.                 }
  342.             }
  343.             return XmlUntypedConverter.Untyped.ChangeType(Value, returnType, nsResolver);
  344.         }
  345.        
  346.         //-----------------------------------------------
  347.         // ICloneable
  348.         //-----------------------------------------------
  349.        
  350.         object ICloneable.Clone()
  351.         {
  352.             return Clone();
  353.         }
  354.        
  355.         //-----------------------------------------------
  356.         // IXPathNavigable
  357.         //-----------------------------------------------
  358.        
  359.         public virtual XPathNavigator CreateNavigator()
  360.         {
  361.             return Clone();
  362.         }
  363.        
  364.         //-----------------------------------------------
  365.         // IXmlNamespaceResolver
  366.         //-----------------------------------------------
  367.        
  368.         public abstract XmlNameTable NameTable {
  369.             get;
  370.         }
  371.        
  372.         public virtual string LookupNamespace(string prefix)
  373.         {
  374.             if (prefix == null)
  375.                 return null;
  376.            
  377.             if (NodeType != XPathNodeType.Element) {
  378.                 XPathNavigator navSave = Clone();
  379.                
  380.                 // If current item is not an element, then try parent
  381.                 if (navSave.MoveToParent())
  382.                     return navSave.LookupNamespace(prefix);
  383.             }
  384.             else if (MoveToNamespace(prefix)) {
  385.                 string namespaceURI = Value;
  386.                 MoveToParent();
  387.                 return namespaceURI;
  388.             }
  389.            
  390.             // Check for "", "xml", and "xmlns" prefixes
  391.             if (prefix.Length == 0)
  392.                 return string.Empty;
  393.             else if (prefix == "xml")
  394.                 return XmlReservedNs.NsXml;
  395.             else if (prefix == "xmlns")
  396.                 return XmlReservedNs.NsXmlNs;
  397.            
  398.             return null;
  399.         }
  400.        
  401.         public virtual string LookupPrefix(string namespaceURI)
  402.         {
  403.             if (namespaceURI == null)
  404.                 return null;
  405.            
  406.             XPathNavigator navClone = Clone();
  407.            
  408.             if (NodeType != XPathNodeType.Element) {
  409.                 // If current item is not an element, then try parent
  410.                 if (navClone.MoveToParent())
  411.                     return navClone.LookupPrefix(namespaceURI);
  412.             }
  413.             else {
  414.                 if (navClone.MoveToFirstNamespace(XPathNamespaceScope.All)) {
  415.                     // Loop until a matching namespace is found
  416.                     do {
  417.                         if (namespaceURI == navClone.Value)
  418.                             return navClone.LocalName;
  419.                     }
  420.                     while (navClone.MoveToNextNamespace(XPathNamespaceScope.All));
  421.                 }
  422.             }
  423.            
  424.             // Check for default, "xml", and "xmlns" namespaces
  425.             if (namespaceURI == LookupNamespace(string.Empty))
  426.                 return string.Empty;
  427.             else if (namespaceURI == XmlReservedNs.NsXml)
  428.                 return "xml";
  429.             else if (namespaceURI == XmlReservedNs.NsXmlNs)
  430.                 return "xmlns";
  431.            
  432.             return null;
  433.         }
  434.        
  435.         #pragma warning disable 3002
  436.         public virtual IDictionary<string, string> GetNamespacesInScope(XmlNamespaceScope scope)
  437.         {
  438.             #pragma warning restore 3002
  439.             XPathNodeType nt = NodeType;
  440.             if ((nt != XPathNodeType.Element && scope != XmlNamespaceScope.Local) || nt == XPathNodeType.Attribute || nt == XPathNodeType.Namespace) {
  441.                 XPathNavigator navSave = Clone();
  442.                
  443.                 // If current item is not an element, then try parent
  444.                 if (navSave.MoveToParent())
  445.                     return navSave.GetNamespacesInScope(scope);
  446.             }
  447.            
  448.             Dictionary<string, string> dict = new Dictionary<string, string>();
  449.            
  450.             // "xml" prefix always in scope
  451.             if (scope == XmlNamespaceScope.All)
  452.                 dict["xml"] = XmlReservedNs.NsXml;
  453.            
  454.             // Now add all in-scope namespaces
  455.             if (MoveToFirstNamespace((XPathNamespaceScope)scope)) {
  456.                 do {
  457.                     string prefix = LocalName;
  458.                     string ns = Value;
  459.                    
  460.                     // Exclude xmlns="" declarations unless scope = Local
  461.                     if (prefix.Length != 0 || ns.Length != 0 || scope == XmlNamespaceScope.Local)
  462.                         dict[prefix] = ns;
  463.                 }
  464.                 while (MoveToNextNamespace((XPathNamespaceScope)scope));
  465.                
  466.                 MoveToParent();
  467.             }
  468.            
  469.             return dict;
  470.         }
  471.        
  472.         //-----------------------------------------------
  473.         // XPathNavigator
  474.         //-----------------------------------------------
  475.        
  476.         // Returns an object of type IKeyComparer. Using this the navigators can be hashed
  477.         // on the basis of actual position it represents rather than the clr reference of
  478.         // the navigator object.
  479.         public static IEqualityComparer NavigatorComparer {
  480.             get { return comparer; }
  481.         }
  482.        
  483.         public abstract XPathNavigator Clone();
  484.        
  485.         public abstract XPathNodeType NodeType {
  486.             get;
  487.         }
  488.        
  489.         public abstract string LocalName {
  490.             get;
  491.         }
  492.        
  493.         public abstract string Name {
  494.             get;
  495.         }
  496.        
  497.         public abstract string NamespaceURI {
  498.             get;
  499.         }
  500.        
  501.         public abstract string Prefix {
  502.             get;
  503.         }
  504.        
  505.         public abstract string BaseURI {
  506.             get;
  507.         }
  508.        
  509.         public abstract bool IsEmptyElement {
  510.             get;
  511.         }
  512.        
  513.         public virtual string XmlLang {
  514.             get {
  515.                 XPathNavigator navClone = Clone();
  516.                 do {
  517.                     if (navClone.MoveToAttribute("lang", XmlReservedNs.NsXml))
  518.                         return navClone.Value;
  519.                 }
  520.                 while (navClone.MoveToParent());
  521.                
  522.                 return string.Empty;
  523.             }
  524.         }
  525.        
  526.         public virtual XmlReader ReadSubtree()
  527.         {
  528.             switch (NodeType) {
  529.                 case XPathNodeType.Root:
  530.                 case XPathNodeType.Element:
  531.                     break;
  532.                 default:
  533.                     throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  534.                     break;
  535.             }
  536.             return CreateReader();
  537.         }
  538.        
  539.         public virtual void WriteSubtree(XmlWriter writer)
  540.         {
  541.             if (null == writer)
  542.                 throw new ArgumentNullException("writer");
  543.             writer.WriteNode(this, true);
  544.         }
  545.        
  546.         public virtual object UnderlyingObject {
  547.             get { return null; }
  548.         }
  549.        
  550.         public virtual bool HasAttributes {
  551.             get {
  552.                 if (!MoveToFirstAttribute())
  553.                     return false;
  554.                
  555.                 MoveToParent();
  556.                 return true;
  557.             }
  558.         }
  559.        
  560.         public virtual string GetAttribute(string localName, string namespaceURI)
  561.         {
  562.             string value;
  563.            
  564.             if (!MoveToAttribute(localName, namespaceURI))
  565.                 return "";
  566.            
  567.             value = Value;
  568.             MoveToParent();
  569.            
  570.             return value;
  571.         }
  572.        
  573.         public virtual bool MoveToAttribute(string localName, string namespaceURI)
  574.         {
  575.             if (MoveToFirstAttribute()) {
  576.                 do {
  577.                     if (localName == LocalName && namespaceURI == NamespaceURI)
  578.                         return true;
  579.                 }
  580.                 while (MoveToNextAttribute());
  581.                
  582.                 MoveToParent();
  583.             }
  584.            
  585.             return false;
  586.         }
  587.        
  588.         public abstract bool MoveToFirstAttribute();
  589.        
  590.         public abstract bool MoveToNextAttribute();
  591.        
  592.         public virtual string GetNamespace(string name)
  593.         {
  594.             string value;
  595.            
  596.             if (!MoveToNamespace(name)) {
  597.                 if (name == "xml")
  598.                     return XmlReservedNs.NsXml;
  599.                 if (name == "xmlns")
  600.                     return XmlReservedNs.NsXmlNs;
  601.                 return string.Empty;
  602.             }
  603.            
  604.             value = Value;
  605.             MoveToParent();
  606.            
  607.             return value;
  608.         }
  609.        
  610.         public virtual bool MoveToNamespace(string name)
  611.         {
  612.             if (MoveToFirstNamespace(XPathNamespaceScope.All)) {
  613.                
  614.                 do {
  615.                     if (name == LocalName)
  616.                         return true;
  617.                 }
  618.                 while (MoveToNextNamespace(XPathNamespaceScope.All));
  619.                
  620.                 MoveToParent();
  621.             }
  622.            
  623.             return false;
  624.         }
  625.        
  626.         public abstract bool MoveToFirstNamespace(XPathNamespaceScope namespaceScope);
  627.        
  628.         public abstract bool MoveToNextNamespace(XPathNamespaceScope namespaceScope);
  629.        
  630.         public bool MoveToFirstNamespace()
  631.         {
  632.             return MoveToFirstNamespace(XPathNamespaceScope.All);
  633.         }
  634.        
  635.         public bool MoveToNextNamespace()
  636.         {
  637.             return MoveToNextNamespace(XPathNamespaceScope.All);
  638.         }
  639.        
  640.         public abstract bool MoveToNext();
  641.        
  642.         public abstract bool MoveToPrevious();
  643.        
  644.         public virtual bool MoveToFirst()
  645.         {
  646.             switch (NodeType) {
  647.                 case XPathNodeType.Attribute:
  648.                 case XPathNodeType.Namespace:
  649.                     // MoveToFirst should only succeed for content-typed nodes
  650.                     return false;
  651.             }
  652.            
  653.             if (!MoveToParent())
  654.                 return false;
  655.            
  656.             return MoveToFirstChild();
  657.         }
  658.        
  659.         public abstract bool MoveToFirstChild();
  660.        
  661.         public abstract bool MoveToParent();
  662.        
  663.         public virtual void MoveToRoot()
  664.         {
  665.             while (MoveToParent())
  666.                 ;
  667.         }
  668.        
  669.         public abstract bool MoveTo(XPathNavigator other);
  670.        
  671.         public abstract bool MoveToId(string id);
  672.        
  673.         public virtual bool MoveToChild(string localName, string namespaceURI)
  674.         {
  675.             if (MoveToFirstChild()) {
  676.                 do {
  677.                     if (NodeType == XPathNodeType.Element && localName == LocalName && namespaceURI == NamespaceURI)
  678.                         return true;
  679.                 }
  680.                 while (MoveToNext());
  681.                 MoveToParent();
  682.             }
  683.            
  684.             return false;
  685.         }
  686.        
  687.         public virtual bool MoveToChild(XPathNodeType type)
  688.         {
  689.             if (MoveToFirstChild()) {
  690.                 int mask = GetContentKindMask(type);
  691.                 do {
  692.                     if (((1 << (int)NodeType) & mask) != 0)
  693.                         return true;
  694.                 }
  695.                 while (MoveToNext());
  696.                
  697.                 MoveToParent();
  698.             }
  699.            
  700.             return false;
  701.         }
  702.        
  703.         public virtual bool MoveToFollowing(string localName, string namespaceURI)
  704.         {
  705.             return MoveToFollowing(localName, namespaceURI, null);
  706.         }
  707.        
  708.         public virtual bool MoveToFollowing(string localName, string namespaceURI, XPathNavigator end)
  709.         {
  710.             XPathNavigator navSave = Clone();
  711.            
  712.             if (end != null) {
  713.                 switch (end.NodeType) {
  714.                     case XPathNodeType.Attribute:
  715.                     case XPathNodeType.Namespace:
  716.                         // Scan until we come to the next content-typed node
  717.                         // after the attribute or namespace node
  718.                         end = end.Clone();
  719.                         end.MoveToNonDescendant();
  720.                         break;
  721.                 }
  722.             }
  723.             switch (NodeType) {
  724.                 case XPathNodeType.Attribute:
  725.                 case XPathNodeType.Namespace:
  726.                     if (!MoveToParent()) {
  727.                         // Restore previous position and return false
  728.                         // MoveTo(navSave);
  729.                         return false;
  730.                     }
  731.                     break;
  732.             }
  733.             do {
  734.                 if (!MoveToFirstChild()) {
  735.                     // Look for next sibling
  736.                     while (true) {
  737.                         if (MoveToNext())
  738.                             break;
  739.                        
  740.                         if (!MoveToParent()) {
  741.                             // Restore previous position and return false
  742.                             MoveTo(navSave);
  743.                             return false;
  744.                         }
  745.                     }
  746.                 }
  747.                
  748.                 // Have we reached the end of the scan?
  749.                 if (end != null && IsSamePosition(end)) {
  750.                     // Restore previous position and return false
  751.                     MoveTo(navSave);
  752.                     return false;
  753.                 }
  754.             }
  755.             while (NodeType != XPathNodeType.Element || localName != LocalName || namespaceURI != NamespaceURI);
  756.            
  757.             return true;
  758.         }
  759.        
  760.         public virtual bool MoveToFollowing(XPathNodeType type)
  761.         {
  762.             return MoveToFollowing(type, null);
  763.         }
  764.        
  765.         public virtual bool MoveToFollowing(XPathNodeType type, XPathNavigator end)
  766.         {
  767.             XPathNavigator navSave = Clone();
  768.             int mask = GetContentKindMask(type);
  769.            
  770.             if (end != null) {
  771.                 switch (end.NodeType) {
  772.                     case XPathNodeType.Attribute:
  773.                     case XPathNodeType.Namespace:
  774.                         // Scan until we come to the next content-typed node
  775.                         // after the attribute or namespace node
  776.                         end = end.Clone();
  777.                         end.MoveToNonDescendant();
  778.                         break;
  779.                 }
  780.             }
  781.             switch (NodeType) {
  782.                 case XPathNodeType.Attribute:
  783.                 case XPathNodeType.Namespace:
  784.                     if (!MoveToParent()) {
  785.                         // Restore previous position and return false
  786.                         // MoveTo(navSave);
  787.                         return false;
  788.                     }
  789.                     break;
  790.             }
  791.             do {
  792.                 if (!MoveToFirstChild()) {
  793.                     // Look for next sibling
  794.                     while (true) {
  795.                         if (MoveToNext())
  796.                             break;
  797.                        
  798.                         if (!MoveToParent()) {
  799.                             // Restore previous position and return false
  800.                             MoveTo(navSave);
  801.                             return false;
  802.                         }
  803.                     }
  804.                 }
  805.                
  806.                 // Have we reached the end of the scan?
  807.                 if (end != null && IsSamePosition(end)) {
  808.                     // Restore previous position and return false
  809.                     MoveTo(navSave);
  810.                     return false;
  811.                 }
  812.             }
  813.             while (((1 << (int)NodeType) & mask) == 0);
  814.            
  815.             return true;
  816.         }
  817.        
  818.         public virtual bool MoveToNext(string localName, string namespaceURI)
  819.         {
  820.             XPathNavigator navClone = Clone();
  821.            
  822.             while (MoveToNext()) {
  823.                 if (NodeType == XPathNodeType.Element && localName == LocalName && namespaceURI == NamespaceURI)
  824.                     return true;
  825.             }
  826.             MoveTo(navClone);
  827.             return false;
  828.         }
  829.        
  830.         public virtual bool MoveToNext(XPathNodeType type)
  831.         {
  832.             XPathNavigator navClone = Clone();
  833.             int mask = GetContentKindMask(type);
  834.            
  835.             while (MoveToNext()) {
  836.                 if (((1 << (int)NodeType) & mask) != 0)
  837.                     return true;
  838.             }
  839.            
  840.             MoveTo(navClone);
  841.             return false;
  842.         }
  843.        
  844.         public virtual bool HasChildren {
  845.             get {
  846.                 if (MoveToFirstChild()) {
  847.                     MoveToParent();
  848.                     return true;
  849.                 }
  850.                 return false;
  851.             }
  852.         }
  853.        
  854.         public abstract bool IsSamePosition(XPathNavigator other);
  855.        
  856.         public virtual bool IsDescendant(XPathNavigator nav)
  857.         {
  858.             if (nav != null) {
  859.                 nav = nav.Clone();
  860.                 while (nav.MoveToParent())
  861.                     if (nav.IsSamePosition(this))
  862.                         return true;
  863.             }
  864.             return false;
  865.         }
  866.        
  867.         public virtual XmlNodeOrder ComparePosition(XPathNavigator nav)
  868.         {
  869.             if (nav == null) {
  870.                 return XmlNodeOrder.Unknown;
  871.             }
  872.            
  873.             if (IsSamePosition(nav))
  874.                 return XmlNodeOrder.Same;
  875.            
  876.             XPathNavigator n1 = this.Clone();
  877.             XPathNavigator n2 = nav.Clone();
  878.            
  879.             int depth1 = GetDepth(n1.Clone());
  880.             int depth2 = GetDepth(n2.Clone());
  881.            
  882.             if (depth1 > depth2) {
  883.                 while (depth1 > depth2) {
  884.                     n1.MoveToParent();
  885.                     depth1--;
  886.                 }
  887.                 if (n1.IsSamePosition(n2))
  888.                     return XmlNodeOrder.After;
  889.             }
  890.            
  891.             if (depth2 > depth1) {
  892.                 while (depth2 > depth1) {
  893.                     n2.MoveToParent();
  894.                     depth2--;
  895.                 }
  896.                 if (n1.IsSamePosition(n2))
  897.                     return XmlNodeOrder.Before;
  898.             }
  899.            
  900.             XPathNavigator parent1 = n1.Clone();
  901.             XPathNavigator parent2 = n2.Clone();
  902.            
  903.             while (true) {
  904.                 if (!parent1.MoveToParent() || !parent2.MoveToParent())
  905.                     return XmlNodeOrder.Unknown;
  906.                
  907.                 if (parent1.IsSamePosition(parent2)) {
  908.                     if (n1.GetType().ToString() != "Microsoft.VisualStudio.Modeling.StoreNavigator") {
  909.                         Debug.Assert(CompareSiblings(n1.Clone(), n2.Clone()) != CompareSiblings(n2.Clone(), n1.Clone()), "IsSamePosition() on custom navigator returns incosistent results");
  910.                     }
  911.                     return CompareSiblings(n1, n2);
  912.                 }
  913.                
  914.                 n1.MoveToParent();
  915.                 n2.MoveToParent();
  916.             }
  917.         }
  918.        
  919.         public virtual IXmlSchemaInfo SchemaInfo {
  920.             get { return this as IXmlSchemaInfo; }
  921.         }
  922.        
  923.         public virtual bool CheckValidity(XmlSchemaSet schemas, ValidationEventHandler validationEventHandler)
  924.         {
  925.             IXmlSchemaInfo schemaInfo;
  926.             XmlSchemaType schemaType = null;
  927.             XmlSchemaElement schemaElement = null;
  928.             XmlSchemaAttribute schemaAttribute = null;
  929.            
  930.             switch (NodeType) {
  931.                 case XPathNodeType.Root:
  932.                     if (schemas == null) {
  933.                         throw new InvalidOperationException(Res.GetString(Res.XPathDocument_MissingSchemas));
  934.                     }
  935.                     schemaType = null;
  936.                     break;
  937.                 case XPathNodeType.Element:
  938.                     if (schemas == null) {
  939.                         throw new InvalidOperationException(Res.GetString(Res.XPathDocument_MissingSchemas));
  940.                     }
  941.                     schemaInfo = SchemaInfo;
  942.                     if (schemaInfo != null) {
  943.                         schemaType = schemaInfo.SchemaType;
  944.                         schemaElement = schemaInfo.SchemaElement;
  945.                     }
  946.                     if (schemaType == null && schemaElement == null) {
  947.                         throw new InvalidOperationException(Res.GetString(Res.XPathDocument_NotEnoughSchemaInfo, null));
  948.                     }
  949.                     break;
  950.                 case XPathNodeType.Attribute:
  951.                     if (schemas == null) {
  952.                         throw new InvalidOperationException(Res.GetString(Res.XPathDocument_MissingSchemas));
  953.                     }
  954.                     schemaInfo = SchemaInfo;
  955.                     if (schemaInfo != null) {
  956.                         schemaType = schemaInfo.SchemaType;
  957.                         schemaAttribute = schemaInfo.SchemaAttribute;
  958.                     }
  959.                     if (schemaType == null && schemaAttribute == null) {
  960.                         throw new InvalidOperationException(Res.GetString(Res.XPathDocument_NotEnoughSchemaInfo, null));
  961.                     }
  962.                     break;
  963.                 default:
  964.                     throw new InvalidOperationException(Res.GetString(Res.XPathDocument_ValidateInvalidNodeType, null));
  965.                     break;
  966.                
  967.             }
  968.            
  969.             Debug.Assert(schemaType != null || this.NodeType == XPathNodeType.Root, "schemaType != null || this.NodeType == XPathNodeType.Root");
  970.            
  971.             XmlReader reader = CreateReader();
  972.            
  973.             CheckValidityHelper validityTracker = new CheckValidityHelper(validationEventHandler, reader as XPathNavigatorReader);
  974.             validationEventHandler = new ValidationEventHandler(validityTracker.ValidationCallback);
  975.             XmlReader validatingReader = GetValidatingReader(reader, schemas, validationEventHandler, schemaType, schemaElement, schemaAttribute);
  976.            
  977.             while (validatingReader.Read())
  978.                 ;
  979.            
  980.             return validityTracker.IsValid;
  981.         }
  982.        
  983.         private XmlReader GetValidatingReader(XmlReader reader, XmlSchemaSet schemas, ValidationEventHandler validationEvent, XmlSchemaType schemaType, XmlSchemaElement schemaElement, XmlSchemaAttribute schemaAttribute)
  984.         {
  985.             if (schemaAttribute != null) {
  986.                 return schemaAttribute.Validate(reader, null, schemas, validationEvent);
  987.             }
  988.             else if (schemaElement != null) {
  989.                 return schemaElement.Validate(reader, null, schemas, validationEvent);
  990.             }
  991.             else if (schemaType != null) {
  992.                 return schemaType.Validate(reader, null, schemas, validationEvent);
  993.             }
  994.             Debug.Assert(schemas != null, "schemas != null");
  995.             XmlReaderSettings readerSettings = new XmlReaderSettings();
  996.             readerSettings.ConformanceLevel = ConformanceLevel.Auto;
  997.             readerSettings.ValidationType = ValidationType.Schema;
  998.             readerSettings.Schemas = schemas;
  999.             readerSettings.ValidationEventHandler += validationEvent;
  1000.             return XmlReader.Create(reader, readerSettings);
  1001.         }
  1002.        
  1003.         class CheckValidityHelper
  1004.         {
  1005.             bool isValid;
  1006.             ValidationEventHandler nextEventHandler;
  1007.             XPathNavigatorReader reader;
  1008.            
  1009.             internal CheckValidityHelper(ValidationEventHandler nextEventHandler, XPathNavigatorReader reader)
  1010.             {
  1011.                 this.isValid = true;
  1012.                 this.nextEventHandler = nextEventHandler;
  1013.                 this.reader = reader;
  1014.             }
  1015.            
  1016.             internal void ValidationCallback(object sender, ValidationEventArgs args)
  1017.             {
  1018.                 Debug.Assert(args != null);
  1019.                 if (args.Severity == XmlSeverityType.Error)
  1020.                     this.isValid = false;
  1021.                 XmlSchemaValidationException exception = args.Exception as XmlSchemaValidationException;
  1022.                 if (exception != null && reader != null)
  1023.                     exception.SetSourceObject(reader.UnderlyingObject);
  1024.                
  1025.                 if (this.nextEventHandler != null) {
  1026.                     this.nextEventHandler(sender, args);
  1027.                 }
  1028.                 else if (exception != null && args.Severity == XmlSeverityType.Error) {
  1029.                     throw exception;
  1030.                 }
  1031.             }
  1032.            
  1033.             internal bool IsValid {
  1034.                 get { return this.isValid; }
  1035.             }
  1036.         }
  1037.        
  1038.         public virtual XPathExpression Compile(string xpath)
  1039.         {
  1040.             return XPathExpression.Compile(xpath);
  1041.         }
  1042.        
  1043.         public virtual XPathNavigator SelectSingleNode(string xpath)
  1044.         {
  1045.             return SelectSingleNode(XPathExpression.Compile(xpath));
  1046.         }
  1047.        
  1048.         public virtual XPathNavigator SelectSingleNode(string xpath, IXmlNamespaceResolver resolver)
  1049.         {
  1050.             return SelectSingleNode(XPathExpression.Compile(xpath, resolver));
  1051.         }
  1052.        
  1053.         public virtual XPathNavigator SelectSingleNode(XPathExpression expression)
  1054.         {
  1055.             XPathNodeIterator iter = this.Select(expression);
  1056.             if (iter.MoveNext()) {
  1057.                 return iter.Current;
  1058.             }
  1059.             return null;
  1060.         }
  1061.        
  1062.         public virtual XPathNodeIterator Select(string xpath)
  1063.         {
  1064.             return this.Select(XPathExpression.Compile(xpath));
  1065.         }
  1066.        
  1067.         public virtual XPathNodeIterator Select(string xpath, IXmlNamespaceResolver resolver)
  1068.         {
  1069.             return this.Select(XPathExpression.Compile(xpath, resolver));
  1070.         }
  1071.        
  1072.         public virtual XPathNodeIterator Select(XPathExpression expr)
  1073.         {
  1074.             XPathNodeIterator result = Evaluate(expr) as XPathNodeIterator;
  1075.             if (result == null) {
  1076.                 throw XPathException.Create(Res.Xp_NodeSetExpected);
  1077.             }
  1078.             return result;
  1079.         }
  1080.        
  1081.         public virtual object Evaluate(string xpath)
  1082.         {
  1083.             return Evaluate(XPathExpression.Compile(xpath), null);
  1084.         }
  1085.        
  1086.         public virtual object Evaluate(string xpath, IXmlNamespaceResolver resolver)
  1087.         {
  1088.             return this.Evaluate(XPathExpression.Compile(xpath, resolver));
  1089.         }
  1090.        
  1091.         public virtual object Evaluate(XPathExpression expr)
  1092.         {
  1093.             return Evaluate(expr, null);
  1094.         }
  1095.        
  1096.         public virtual object Evaluate(XPathExpression expr, XPathNodeIterator context)
  1097.         {
  1098.             CompiledXpathExpr cexpr = expr as CompiledXpathExpr;
  1099.             if (cexpr == null) {
  1100.                 throw XPathException.Create(Res.Xp_BadQueryObject);
  1101.             }
  1102.             Query query = Query.Clone(cexpr.QueryTree);
  1103.             query.Reset();
  1104.            
  1105.             if (context == null) {
  1106.                     /*moved:*/                context = new XPathSingletonIterator(this.Clone(), true);
  1107.             }
  1108.            
  1109.             object result = query.Evaluate(context);
  1110.            
  1111.             if (result is XPathNodeIterator) {
  1112.                 return new XPathSelectionIterator(context.Current, query);
  1113.             }
  1114.            
  1115.             return result;
  1116.         }
  1117.        
  1118.         public virtual bool Matches(XPathExpression expr)
  1119.         {
  1120.             CompiledXpathExpr cexpr = expr as CompiledXpathExpr;
  1121.             if (cexpr == null)
  1122.                 throw XPathException.Create(Res.Xp_BadQueryObject);
  1123.            
  1124.             // We should clone query because some Query.MatchNode() alter expression state and this may brake
  1125.             // SelectionIterators that are runing using this Query
  1126.             // Excample of MatchNode() that alret the state is FilterQuery.MatchNode()
  1127.             Query query = Query.Clone(cexpr.QueryTree);
  1128.            
  1129.             try {
  1130.                 return query.MatchNode(this) != null;
  1131.             }
  1132.             catch (XPathException) {
  1133.                 throw XPathException.Create(Res.Xp_InvalidPattern, cexpr.Expression);
  1134.             }
  1135.         }
  1136.        
  1137.         public virtual bool Matches(string xpath)
  1138.         {
  1139.             return Matches(CompileMatchPattern(xpath));
  1140.         }
  1141.        
  1142.         public virtual XPathNodeIterator SelectChildren(XPathNodeType type)
  1143.         {
  1144.             return new XPathChildIterator(this.Clone(), type);
  1145.         }
  1146.        
  1147.         public virtual XPathNodeIterator SelectChildren(string name, string namespaceURI)
  1148.         {
  1149.             return new XPathChildIterator(this.Clone(), name, namespaceURI);
  1150.         }
  1151.        
  1152.         public virtual XPathNodeIterator SelectAncestors(XPathNodeType type, bool matchSelf)
  1153.         {
  1154.             return new XPathAncestorIterator(this.Clone(), type, matchSelf);
  1155.         }
  1156.        
  1157.         public virtual XPathNodeIterator SelectAncestors(string name, string namespaceURI, bool matchSelf)
  1158.         {
  1159.             return new XPathAncestorIterator(this.Clone(), name, namespaceURI, matchSelf);
  1160.         }
  1161.        
  1162.         public virtual XPathNodeIterator SelectDescendants(XPathNodeType type, bool matchSelf)
  1163.         {
  1164.             return new XPathDescendantIterator(this.Clone(), type, matchSelf);
  1165.         }
  1166.        
  1167.         public virtual XPathNodeIterator SelectDescendants(string name, string namespaceURI, bool matchSelf)
  1168.         {
  1169.             return new XPathDescendantIterator(this.Clone(), name, namespaceURI, matchSelf);
  1170.         }
  1171.        
  1172.         public virtual bool CanEdit {
  1173.             get { return false; }
  1174.         }
  1175.        
  1176.         public virtual XmlWriter PrependChild()
  1177.         {
  1178.             throw new NotSupportedException();
  1179.         }
  1180.        
  1181.         public virtual XmlWriter AppendChild()
  1182.         {
  1183.             throw new NotSupportedException();
  1184.         }
  1185.        
  1186.         public virtual XmlWriter InsertAfter()
  1187.         {
  1188.             throw new NotSupportedException();
  1189.         }
  1190.        
  1191.         public virtual XmlWriter InsertBefore()
  1192.         {
  1193.             throw new NotSupportedException();
  1194.         }
  1195.        
  1196.         public virtual XmlWriter CreateAttributes()
  1197.         {
  1198.             throw new NotSupportedException();
  1199.         }
  1200.        
  1201.         public virtual XmlWriter ReplaceRange(XPathNavigator lastSiblingToReplace)
  1202.         {
  1203.             throw new NotSupportedException();
  1204.         }
  1205.        
  1206.         public virtual void ReplaceSelf(string newNode)
  1207.         {
  1208.             XmlReader reader = CreateContextReader(newNode, false);
  1209.             ReplaceSelf(reader);
  1210.         }
  1211.        
  1212.         public virtual void ReplaceSelf(XmlReader newNode)
  1213.         {
  1214.             if (newNode == null) {
  1215.                 throw new ArgumentNullException("newNode");
  1216.             }
  1217.             XPathNodeType type = NodeType;
  1218.             if (type == XPathNodeType.Root || type == XPathNodeType.Attribute || type == XPathNodeType.Namespace) {
  1219.                 throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  1220.             }
  1221.             XmlWriter writer = ReplaceRange(this);
  1222.             BuildSubtree(newNode, writer);
  1223.             writer.Close();
  1224.         }
  1225.        
  1226.         public virtual void ReplaceSelf(XPathNavigator newNode)
  1227.         {
  1228.             if (newNode == null) {
  1229.                 throw new ArgumentNullException("newNode");
  1230.             }
  1231.             XmlReader reader = newNode.CreateReader();
  1232.             ReplaceSelf(reader);
  1233.         }
  1234.        
  1235.         // Returns the markup representing the current node and all of its children.
  1236.         public virtual string OuterXml {
  1237.             get {
  1238.                 StringWriter stringWriter;
  1239.                 XmlWriterSettings writerSettings;
  1240.                 XmlWriter xmlWriter;
  1241.                
  1242.                 // Attributes and namespaces are not allowed at the top-level by the well-formed writer
  1243.                 if (NodeType == XPathNodeType.Attribute) {
  1244.                     return string.Concat(Name, "=\"", Value, "\"");
  1245.                 }
  1246.                 else if (NodeType == XPathNodeType.Namespace) {
  1247.                     if (LocalName.Length == 0)
  1248.                         return string.Concat("xmlns=\"", Value, "\"");
  1249.                     else
  1250.                         return string.Concat("xmlns:", LocalName, "=\"", Value, "\"");
  1251.                 }
  1252.                
  1253.                 stringWriter = new StringWriter(CultureInfo.InvariantCulture);
  1254.                
  1255.                 writerSettings = new XmlWriterSettings();
  1256.                 writerSettings.Indent = true;
  1257.                 writerSettings.OmitXmlDeclaration = true;
  1258.                 writerSettings.ConformanceLevel = ConformanceLevel.Auto;
  1259.                
  1260.                 xmlWriter = XmlWriter.Create(stringWriter, writerSettings);
  1261.                 try {
  1262.                     xmlWriter.WriteNode(this, true);
  1263.                 }
  1264.                 finally {
  1265.                     xmlWriter.Close();
  1266.                 }
  1267.                
  1268.                 return stringWriter.ToString();
  1269.             }
  1270.            
  1271.             set { ReplaceSelf(value); }
  1272.         }
  1273.        
  1274.         // Returns the markup representing just the children of the current node.
  1275.         public virtual string InnerXml {
  1276.             get {
  1277.                 switch (NodeType) {
  1278.                     case XPathNodeType.Root:
  1279.                     case XPathNodeType.Element:
  1280.                         StringWriter stringWriter;
  1281.                         XmlWriterSettings writerSettings;
  1282.                         XmlWriter xmlWriter;
  1283.                        
  1284.                         stringWriter = new StringWriter(CultureInfo.InvariantCulture);
  1285.                        
  1286.                         writerSettings = new XmlWriterSettings();
  1287.                         writerSettings.Indent = true;
  1288.                         writerSettings.OmitXmlDeclaration = true;
  1289.                         writerSettings.ConformanceLevel = ConformanceLevel.Auto;
  1290.                         xmlWriter = XmlWriter.Create(stringWriter, writerSettings);
  1291.                        
  1292.                         try {
  1293.                             if (MoveToFirstChild()) {
  1294.                                 do {
  1295.                                     xmlWriter.WriteNode(this, true);
  1296.                                 }
  1297.                                 while (MoveToNext());
  1298.                                
  1299.                                 // Restore position
  1300.                                 MoveToParent();
  1301.                             }
  1302.                         }
  1303.                         finally {
  1304.                             xmlWriter.Close();
  1305.                         }
  1306.                         return stringWriter.ToString();
  1307.                     case XPathNodeType.Attribute:
  1308.                     case XPathNodeType.Namespace:
  1309.                         return Value;
  1310.                     default:
  1311.                         return string.Empty;
  1312.                 }
  1313.             }
  1314.            
  1315.             set {
  1316.                 if (value == null) {
  1317.                     throw new ArgumentNullException("value");
  1318.                 }
  1319.                
  1320.                 switch (NodeType) {
  1321.                     case XPathNodeType.Root:
  1322.                     case XPathNodeType.Element:
  1323.                         XPathNavigator edit = CreateNavigator();
  1324.                         while (edit.MoveToFirstChild()) {
  1325.                             edit.DeleteSelf();
  1326.                         }
  1327.                         if (value.Length != 0) {
  1328.                             edit.AppendChild(value);
  1329.                         }
  1330.                         break;
  1331.                     case XPathNodeType.Attribute:
  1332.                         SetValue(value);
  1333.                         break;
  1334.                     default:
  1335.                         throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  1336.                         break;
  1337.                 }
  1338.             }
  1339.         }
  1340.        
  1341.         public virtual void AppendChild(string newChild)
  1342.         {
  1343.             XmlReader reader = CreateContextReader(newChild, true);
  1344.             AppendChild(reader);
  1345.         }
  1346.        
  1347.         public virtual void AppendChild(XmlReader newChild)
  1348.         {
  1349.             if (newChild == null) {
  1350.                 throw new ArgumentNullException("newChild");
  1351.             }
  1352.             XmlWriter writer = AppendChild();
  1353.             BuildSubtree(newChild, writer);
  1354.             writer.Close();
  1355.         }
  1356.        
  1357.         public virtual void AppendChild(XPathNavigator newChild)
  1358.         {
  1359.             if (newChild == null) {
  1360.                 throw new ArgumentNullException("newChild");
  1361.             }
  1362.             if (!IsValidChildType(newChild.NodeType)) {
  1363.                 throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  1364.             }
  1365.             XmlReader reader = newChild.CreateReader();
  1366.             AppendChild(reader);
  1367.         }
  1368.        
  1369.         public virtual void PrependChild(string newChild)
  1370.         {
  1371.             XmlReader reader = CreateContextReader(newChild, true);
  1372.             PrependChild(reader);
  1373.         }
  1374.        
  1375.         public virtual void PrependChild(XmlReader newChild)
  1376.         {
  1377.             if (newChild == null) {
  1378.                 throw new ArgumentNullException("newChild");
  1379.             }
  1380.             XmlWriter writer = PrependChild();
  1381.             BuildSubtree(newChild, writer);
  1382.             writer.Close();
  1383.         }
  1384.        
  1385.         public virtual void PrependChild(XPathNavigator newChild)
  1386.         {
  1387.             if (newChild == null) {
  1388.                 throw new ArgumentNullException("newChild");
  1389.             }
  1390.             if (!IsValidChildType(newChild.NodeType)) {
  1391.                 throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  1392.             }
  1393.             XmlReader reader = newChild.CreateReader();
  1394.             PrependChild(reader);
  1395.         }
  1396.        
  1397.         public virtual void InsertBefore(string newSibling)
  1398.         {
  1399.             XmlReader reader = CreateContextReader(newSibling, false);
  1400.             InsertBefore(reader);
  1401.         }
  1402.        
  1403.         public virtual void InsertBefore(XmlReader newSibling)
  1404.         {
  1405.             if (newSibling == null) {
  1406.                 throw new ArgumentNullException("newSibling");
  1407.             }
  1408.             XmlWriter writer = InsertBefore();
  1409.             BuildSubtree(newSibling, writer);
  1410.             writer.Close();
  1411.         }
  1412.        
  1413.         public virtual void InsertBefore(XPathNavigator newSibling)
  1414.         {
  1415.             if (newSibling == null) {
  1416.                 throw new ArgumentNullException("newSibling");
  1417.             }
  1418.             if (!IsValidSiblingType(newSibling.NodeType)) {
  1419.                 throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  1420.             }
  1421.             XmlReader reader = newSibling.CreateReader();
  1422.             InsertBefore(reader);
  1423.         }
  1424.        
  1425.         public virtual void InsertAfter(string newSibling)
  1426.         {
  1427.             XmlReader reader = CreateContextReader(newSibling, false);
  1428.             InsertAfter(reader);
  1429.         }
  1430.        
  1431.         public virtual void InsertAfter(XmlReader newSibling)
  1432.         {
  1433.             if (newSibling == null) {
  1434.                 throw new ArgumentNullException("newSibling");
  1435.             }
  1436.             XmlWriter writer = InsertAfter();
  1437.             BuildSubtree(newSibling, writer);
  1438.             writer.Close();
  1439.         }
  1440.        
  1441.         public virtual void InsertAfter(XPathNavigator newSibling)
  1442.         {
  1443.             if (newSibling == null) {
  1444.                 throw new ArgumentNullException("newSibling");
  1445.             }
  1446.             if (!IsValidSiblingType(newSibling.NodeType)) {
  1447.                 throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  1448.             }
  1449.             XmlReader reader = newSibling.CreateReader();
  1450.             InsertAfter(reader);
  1451.         }
  1452.        
  1453.         public virtual void DeleteRange(XPathNavigator lastSiblingToDelete)
  1454.         {
  1455.             throw new NotSupportedException();
  1456.         }
  1457.        
  1458.         public virtual void DeleteSelf()
  1459.         {
  1460.             DeleteRange(this);
  1461.         }
  1462.        
  1463.         public virtual void PrependChildElement(string prefix, string localName, string namespaceURI, string value)
  1464.         {
  1465.             XmlWriter writer = PrependChild();
  1466.             writer.WriteStartElement(prefix, localName, namespaceURI);
  1467.             if (value != null) {
  1468.                 writer.WriteString(value);
  1469.             }
  1470.             writer.WriteEndElement();
  1471.             writer.Close();
  1472.         }
  1473.        
  1474.         public virtual void AppendChildElement(string prefix, string localName, string namespaceURI, string value)
  1475.         {
  1476.             XmlWriter writer = AppendChild();
  1477.             writer.WriteStartElement(prefix, localName, namespaceURI);
  1478.             if (value != null) {
  1479.                 writer.WriteString(value);
  1480.             }
  1481.             writer.WriteEndElement();
  1482.             writer.Close();
  1483.         }
  1484.        
  1485.         public virtual void InsertElementBefore(string prefix, string localName, string namespaceURI, string value)
  1486.         {
  1487.             XmlWriter writer = InsertBefore();
  1488.             writer.WriteStartElement(prefix, localName, namespaceURI);
  1489.             if (value != null) {
  1490.                 writer.WriteString(value);
  1491.             }
  1492.             writer.WriteEndElement();
  1493.             writer.Close();
  1494.         }
  1495.        
  1496.         public virtual void InsertElementAfter(string prefix, string localName, string namespaceURI, string value)
  1497.         {
  1498.             XmlWriter writer = InsertAfter();
  1499.             writer.WriteStartElement(prefix, localName, namespaceURI);
  1500.             if (value != null) {
  1501.                 writer.WriteString(value);
  1502.             }
  1503.             writer.WriteEndElement();
  1504.             writer.Close();
  1505.         }
  1506.        
  1507.         public virtual void CreateAttribute(string prefix, string localName, string namespaceURI, string value)
  1508.         {
  1509.             XmlWriter writer = CreateAttributes();
  1510.             writer.WriteStartAttribute(prefix, localName, namespaceURI);
  1511.             if (value != null) {
  1512.                 writer.WriteString(value);
  1513.             }
  1514.             writer.WriteEndAttribute();
  1515.             writer.Close();
  1516.         }
  1517.        
  1518.         //-----------------------------------------------
  1519.         // Internal
  1520.         //-----------------------------------------------
  1521.        
  1522.         internal bool MoveToPrevious(string localName, string namespaceURI)
  1523.         {
  1524.             XPathNavigator navClone = Clone();
  1525.            
  1526.             localName = (localName != null) ? NameTable.Get(localName) : null;
  1527.             while (MoveToPrevious()) {
  1528.                 if (NodeType == XPathNodeType.Element && (object)localName == (object)LocalName && namespaceURI == NamespaceURI)
  1529.                     return true;
  1530.             }
  1531.            
  1532.             MoveTo(navClone);
  1533.             return false;
  1534.         }
  1535.        
  1536.         internal bool MoveToPrevious(XPathNodeType type)
  1537.         {
  1538.             XPathNavigator navClone = Clone();
  1539.             int mask = GetContentKindMask(type);
  1540.            
  1541.             while (MoveToPrevious()) {
  1542.                 if (((1 << (int)NodeType) & mask) != 0)
  1543.                     return true;
  1544.             }
  1545.            
  1546.             MoveTo(navClone);
  1547.             return false;
  1548.         }
  1549.        
  1550.         internal bool MoveToNonDescendant()
  1551.         {
  1552.             // If current node is document, there is no next non-descendant
  1553.             if (NodeType == XPathNodeType.Root)
  1554.                 return false;
  1555.            
  1556.             // If sibling exists, it is the next non-descendant
  1557.             if (MoveToNext())
  1558.                 return true;
  1559.            
  1560.             // The current node is either an attribute, namespace, or last child node
  1561.             XPathNavigator navSave = Clone();
  1562.            
  1563.             if (!MoveToParent())
  1564.                 return false;
  1565.            
  1566.             switch (navSave.NodeType) {
  1567.                 case XPathNodeType.Attribute:
  1568.                 case XPathNodeType.Namespace:
  1569.                     // Next node in document order is first content-child of parent
  1570.                     if (MoveToFirstChild())
  1571.                         return true;
  1572.                     break;
  1573.             }
  1574.            
  1575.             while (!MoveToNext()) {
  1576.                 if (!MoveToParent()) {
  1577.                     // Restore original position and return false
  1578.                     MoveTo(navSave);
  1579.                     return false;
  1580.                 }
  1581.             }
  1582.            
  1583.             return true;
  1584.         }
  1585.        
  1586.         /// <summary>
  1587.         /// Returns ordinal number of attribute, namespace or child node within its parent.
  1588.         /// Order is reversed for attributes and child nodes to avoid O(N**2) running time.
  1589.         /// This property is useful for debugging, and also used in UniqueId implementation.
  1590.         /// </summary>
  1591.         internal uint IndexInParent {
  1592.             get {
  1593.                 XPathNavigator nav = this.Clone();
  1594.                 uint idx = 0;
  1595.                
  1596.                 switch (NodeType) {
  1597.                     case XPathNodeType.Attribute:
  1598.                         while (nav.MoveToNextAttribute()) {
  1599.                             idx++;
  1600.                         }
  1601.                         break;
  1602.                     case XPathNodeType.Namespace:
  1603.                         while (nav.MoveToNextNamespace()) {
  1604.                             idx++;
  1605.                         }
  1606.                         break;
  1607.                     default:
  1608.                         while (nav.MoveToNext()) {
  1609.                             idx++;
  1610.                         }
  1611.                         break;
  1612.                 }
  1613.                 return idx;
  1614.             }
  1615.         }
  1616.        
  1617.         static internal readonly char[] NodeTypeLetter = new char[] {'R', 'E', 'A', 'N', 'T', 'S', 'W', 'P', 'C', 'X'
  1618.             // Root
  1619.             // Element
  1620.             // Attribute
  1621.             // Namespace
  1622.             // Text
  1623.             // SignificantWhitespace
  1624.             // Whitespace
  1625.             // ProcessingInstruction
  1626.             // Comment
  1627.             // All
  1628.         };
  1629.        
  1630.         static internal readonly char[] UniqueIdTbl = new char[] {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
  1631.         'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
  1632.         'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4',
  1633.         '5', '6'};
  1634.        
  1635.         // Requirements for id:
  1636.         // 1. must consist of alphanumeric characters only
  1637.         // 2. must begin with an alphabetic character
  1638.         // 3. same id is generated for the same node
  1639.         // 4. ids are unique
  1640.         //
  1641.         // id = node type letter + reverse path to root in terms of encoded IndexInParent integers from node to root seperated by 0's if needed
  1642.         internal virtual string UniqueId {
  1643.             get {
  1644.                 XPathNavigator nav = this.Clone();
  1645.                 BufferBuilder sb = new BufferBuilder();
  1646.                
  1647.                 // Ensure distinguishing attributes, namespaces and child nodes
  1648.                 sb.Append(NodeTypeLetter[(int)NodeType]);
  1649.                
  1650.                 while (true) {
  1651.                     uint idx = nav.IndexInParent;
  1652.                     if (!nav.MoveToParent()) {
  1653.                         break;
  1654.                     }
  1655.                     if (idx <= 31) {
  1656.                         sb.Append(UniqueIdTbl[idx]);
  1657.                     }
  1658.                     else {
  1659.                         sb.Append('0');
  1660.                         do {
  1661.                             sb.Append(UniqueIdTbl[idx & 31]);
  1662.                             idx >>= 5;
  1663.                         }
  1664.                         while (idx != 0);
  1665.                         sb.Append('0');
  1666.                     }
  1667.                 }
  1668.                 return sb.ToString();
  1669.             }
  1670.         }
  1671.        
  1672.         private static XPathExpression CompileMatchPattern(string xpath)
  1673.         {
  1674.             bool hasPrefix;
  1675.             Query query = new QueryBuilder().BuildPatternQuery(xpath, out hasPrefix);
  1676.             return new CompiledXpathExpr(query, xpath, hasPrefix);
  1677.         }
  1678.        
  1679.         private static int GetDepth(XPathNavigator nav)
  1680.         {
  1681.             int depth = 0;
  1682.             while (nav.MoveToParent()) {
  1683.                 depth++;
  1684.             }
  1685.             return depth;
  1686.         }
  1687.        
  1688.         // XPath based comparison for namespaces, attributes and other
  1689.         // items with the same parent element.
  1690.         //
  1691.         // n2
  1692.         // namespace(0) attribute(-1) other(-2)
  1693.         // n1
  1694.         // namespace(0) ?(0) before(-1) before(-2)
  1695.         // attribute(1) after(1) ?(0) before(-1)
  1696.         // other (2) after(2) after(1) ?(0)
  1697.         private XmlNodeOrder CompareSiblings(XPathNavigator n1, XPathNavigator n2)
  1698.         {
  1699.             int cmp = 0;
  1700.            
  1701.             #if DEBUG
  1702.             Debug.Assert(!n1.IsSamePosition(n2));
  1703.             XPathNavigator p1 = n1.Clone();
  1704.             XPathNavigator p2 = n2.Clone();
  1705.             Debug.Assert(p1.MoveToParent() && p2.MoveToParent() && p1.IsSamePosition(p2));
  1706.             #endif
  1707.             switch (n1.NodeType) {
  1708.                 case XPathNodeType.Namespace:
  1709.                     break;
  1710.                 case XPathNodeType.Attribute:
  1711.                     cmp += 1;
  1712.                     break;
  1713.                 default:
  1714.                     cmp += 2;
  1715.                     break;
  1716.             }
  1717.             switch (n2.NodeType) {
  1718.                 case XPathNodeType.Namespace:
  1719.                     if (cmp == 0) {
  1720.                         while (n1.MoveToNextNamespace()) {
  1721.                             if (n1.IsSamePosition(n2)) {
  1722.                                 return XmlNodeOrder.Before;
  1723.                             }
  1724.                         }
  1725.                     }
  1726.                     break;
  1727.                 case XPathNodeType.Attribute:
  1728.                     cmp -= 1;
  1729.                     if (cmp == 0) {
  1730.                         while (n1.MoveToNextAttribute()) {
  1731.                             if (n1.IsSamePosition(n2)) {
  1732.                                 return XmlNodeOrder.Before;
  1733.                             }
  1734.                         }
  1735.                     }
  1736.                     break;
  1737.                 default:
  1738.                     cmp -= 2;
  1739.                     if (cmp == 0) {
  1740.                         while (n1.MoveToNext()) {
  1741.                             if (n1.IsSamePosition(n2)) {
  1742.                                 return XmlNodeOrder.Before;
  1743.                             }
  1744.                         }
  1745.                     }
  1746.                     break;
  1747.             }
  1748.             return cmp < 0 ? XmlNodeOrder.Before : XmlNodeOrder.After;
  1749.         }
  1750.        
  1751.         static internal XmlNamespaceManager GetNamespaces(IXmlNamespaceResolver resolver)
  1752.         {
  1753.             XmlNamespaceManager mngr = new XmlNamespaceManager(new NameTable());
  1754.             IDictionary<string, string> dictionary = resolver.GetNamespacesInScope(XmlNamespaceScope.All);
  1755.             foreach (KeyValuePair<string, string> pair in dictionary) {
  1756.                 //"xmlns " is always in the namespace manager so adding it would throw an exception
  1757.                 if (pair.Key != "xmlns")
  1758.                     mngr.AddNamespace(pair.Key, pair.Value);
  1759.             }
  1760.             return mngr;
  1761.         }
  1762.        
  1763.         // Get mask that will allow XPathNodeType content matching to be performed using only a shift and an and operation
  1764.         internal const int AllMask = 2147483647;
  1765.         internal const int NoAttrNmspMask = AllMask & ~(1 << (int)XPathNodeType.Attribute) & ~(1 << (int)XPathNodeType.Namespace);
  1766.         internal const int TextMask = (1 << (int)XPathNodeType.Text) | (1 << (int)XPathNodeType.SignificantWhitespace) | (1 << (int)XPathNodeType.Whitespace);
  1767.         static internal readonly int[] ContentKindMasks = {(1 << (int)XPathNodeType.Root), (1 << (int)XPathNodeType.Element), 0, 0, TextMask, (1 << (int)XPathNodeType.SignificantWhitespace), (1 << (int)XPathNodeType.Whitespace), (1 << (int)XPathNodeType.ProcessingInstruction), (1 << (int)XPathNodeType.Comment), NoAttrNmspMask
  1768.             // Root
  1769.             // Element
  1770.             // Attribute (not content)
  1771.             // Namespace (not content)
  1772.             // Text
  1773.             // SignificantWhitespace
  1774.             // Whitespace
  1775.             // ProcessingInstruction
  1776.             // Comment
  1777.             // All
  1778.         };
  1779.        
  1780.         static internal int GetContentKindMask(XPathNodeType type)
  1781.         {
  1782.             return ContentKindMasks[(int)type];
  1783.         }
  1784.        
  1785.         static internal int GetKindMask(XPathNodeType type)
  1786.         {
  1787.             if (type == XPathNodeType.All)
  1788.                 return AllMask;
  1789.             else if (type == XPathNodeType.Text)
  1790.                 return TextMask;
  1791.            
  1792.             return (1 << (int)type);
  1793.         }
  1794.        
  1795.         static internal bool IsText(XPathNodeType type)
  1796.         {
  1797.             return ((1 << (int)type) & TextMask) != 0;
  1798.         }
  1799.        
  1800.         // Lax check for potential child item.
  1801.         private bool IsValidChildType(XPathNodeType type)
  1802.         {
  1803.             switch (NodeType) {
  1804.                 case XPathNodeType.Root:
  1805.                     switch (type) {
  1806.                         case XPathNodeType.Element:
  1807.                         case XPathNodeType.SignificantWhitespace:
  1808.                         case XPathNodeType.Whitespace:
  1809.                         case XPathNodeType.ProcessingInstruction:
  1810.                         case XPathNodeType.Comment:
  1811.                             return true;
  1812.                     }
  1813.                     break;
  1814.                 case XPathNodeType.Element:
  1815.                     switch (type) {
  1816.                         case XPathNodeType.Element:
  1817.                         case XPathNodeType.Text:
  1818.                         case XPathNodeType.SignificantWhitespace:
  1819.                         case XPathNodeType.Whitespace:
  1820.                         case XPathNodeType.ProcessingInstruction:
  1821.                         case XPathNodeType.Comment:
  1822.                             return true;
  1823.                     }
  1824.                     break;
  1825.             }
  1826.             return false;
  1827.         }
  1828.        
  1829.         // Lax check for potential sibling item.
  1830.         private bool IsValidSiblingType(XPathNodeType type)
  1831.         {
  1832.             switch (NodeType) {
  1833.                 case XPathNodeType.Element:
  1834.                 case XPathNodeType.Text:
  1835.                 case XPathNodeType.SignificantWhitespace:
  1836.                 case XPathNodeType.Whitespace:
  1837.                 case XPathNodeType.ProcessingInstruction:
  1838.                 case XPathNodeType.Comment:
  1839.                     switch (type) {
  1840.                         case XPathNodeType.Element:
  1841.                         case XPathNodeType.Text:
  1842.                         case XPathNodeType.SignificantWhitespace:
  1843.                         case XPathNodeType.Whitespace:
  1844.                         case XPathNodeType.ProcessingInstruction:
  1845.                         case XPathNodeType.Comment:
  1846.                             return true;
  1847.                     }
  1848.                     break;
  1849.             }
  1850.             return false;
  1851.         }
  1852.        
  1853.         private XmlReader CreateReader()
  1854.         {
  1855.             return XPathNavigatorReader.Create(this);
  1856.         }
  1857.        
  1858.         private XmlReader CreateContextReader(string xml, bool fromCurrentNode)
  1859.         {
  1860.             if (xml == null) {
  1861.                 throw new ArgumentNullException("xml");
  1862.             }
  1863.            
  1864.             // We have to set the namespace context for the reader.
  1865.             XPathNavigator editor = CreateNavigator();
  1866.             // scope starts from parent.
  1867.             XmlNamespaceManager mgr = new XmlNamespaceManager(NameTable);
  1868.             if (!fromCurrentNode) {
  1869.                 editor.MoveToParent();
  1870.                 // should always succeed.
  1871.             }
  1872.             if (editor.MoveToFirstNamespace(XPathNamespaceScope.All)) {
  1873.                 do {
  1874.                     mgr.AddNamespace(editor.LocalName, editor.Value);
  1875.                 }
  1876.                 while (editor.MoveToNextNamespace(XPathNamespaceScope.All));
  1877.             }
  1878.             XmlParserContext context = new XmlParserContext(NameTable, mgr, null, XmlSpace.Default);
  1879.             XmlTextReader reader = new XmlTextReader(xml, XmlNodeType.Element, context);
  1880.             reader.WhitespaceHandling = WhitespaceHandling.Significant;
  1881.             return reader;
  1882.         }
  1883.        
  1884.         internal void BuildSubtree(XmlReader reader, XmlWriter writer)
  1885.         {
  1886.             // important (perf) string literal...
  1887.             string xmlnsUri = XmlReservedNs.NsXmlNs;
  1888.             // http://www.w3.org/2000/xmlns/
  1889.             ReadState readState = reader.ReadState;
  1890.            
  1891.             if (readState != ReadState.Initial && readState != ReadState.Interactive) {
  1892.                 throw new ArgumentException(Res.GetString(Res.Xml_InvalidOperation), "reader");
  1893.             }
  1894.             int level = 0;
  1895.             if (readState == ReadState.Initial) {
  1896.                 if (!reader.Read())
  1897.                     return;
  1898.                 level++;
  1899.                 // if start in initial, read everything (not just first)
  1900.             }
  1901.             do {
  1902.                 switch (reader.NodeType) {
  1903.                     case XmlNodeType.Element:
  1904.                         writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
  1905.                         bool isEmptyElement = reader.IsEmptyElement;
  1906.                        
  1907.                         while (reader.MoveToNextAttribute()) {
  1908.                             if ((object)reader.NamespaceURI == (object)xmlnsUri) {
  1909.                                 if (reader.Prefix.Length == 0) {
  1910.                                     // Default namespace declaration "xmlns"
  1911.                                     Debug.Assert(reader.LocalName == "xmlns");
  1912.                                     writer.WriteAttributeString("", "xmlns", xmlnsUri, reader.Value);
  1913.                                 }
  1914.                                 else {
  1915.                                     Debug.Assert(reader.Prefix == "xmlns");
  1916.                                     writer.WriteAttributeString("xmlns", reader.LocalName, xmlnsUri, reader.Value);
  1917.                                 }
  1918.                             }
  1919.                             else {
  1920.                                 writer.WriteStartAttribute(reader.Prefix, reader.LocalName, reader.NamespaceURI);
  1921.                                 writer.WriteString(reader.Value);
  1922.                                 writer.WriteEndAttribute();
  1923.                             }
  1924.                         }
  1925.                        
  1926.                         reader.MoveToElement();
  1927.                         if (isEmptyElement) {
  1928.                             // there might still be a value, if there is a default value specified in the schema
  1929.                             writer.WriteEndElement();
  1930.                         }
  1931.                         else {
  1932.                             level++;
  1933.                         }
  1934.                         break;
  1935.                     case XmlNodeType.EndElement:
  1936.                         writer.WriteFullEndElement();
  1937.                         //should not read beyond the level of the reader's original position.
  1938.                         level--;
  1939.                         break;
  1940.                     case XmlNodeType.Text:
  1941.                     case XmlNodeType.CDATA:
  1942.                         writer.WriteString(reader.Value);
  1943.                         break;
  1944.                     case XmlNodeType.SignificantWhitespace:
  1945.                     case XmlNodeType.Whitespace:
  1946.                         writer.WriteString(reader.Value);
  1947.                         break;
  1948.                     case XmlNodeType.Comment:
  1949.                         writer.WriteComment(reader.Value);
  1950.                         break;
  1951.                     case XmlNodeType.ProcessingInstruction:
  1952.                         writer.WriteProcessingInstruction(reader.LocalName, reader.Value);
  1953.                         break;
  1954.                     case XmlNodeType.EntityReference:
  1955.                         reader.ResolveEntity();
  1956.                         break;
  1957.                     case XmlNodeType.EndEntity:
  1958.                     case XmlNodeType.None:
  1959.                     case XmlNodeType.DocumentType:
  1960.                     case XmlNodeType.XmlDeclaration:
  1961.                         break;
  1962.                     case XmlNodeType.Attribute:
  1963.                         if ((object)reader.NamespaceURI == (object)xmlnsUri) {
  1964.                             if (reader.Prefix.Length == 0) {
  1965.                                 // Default namespace declaration "xmlns"
  1966.                                 Debug.Assert(reader.LocalName == "xmlns");
  1967.                                 writer.WriteAttributeString("", "xmlns", xmlnsUri, reader.Value);
  1968.                             }
  1969.                             else {
  1970.                                 Debug.Assert(reader.Prefix == "xmlns");
  1971.                                 writer.WriteAttributeString("xmlns", reader.LocalName, xmlnsUri, reader.Value);
  1972.                             }
  1973.                         }
  1974.                         else {
  1975.                             writer.WriteStartAttribute(reader.Prefix, reader.LocalName, reader.NamespaceURI);
  1976.                             writer.WriteString(reader.Value);
  1977.                             writer.WriteEndAttribute();
  1978.                         }
  1979.                         break;
  1980.                 }
  1981.             }
  1982.             while (reader.Read() && (level > 0));
  1983.         }
  1984.        
  1985.         internal struct DebuggerDisplayProxy
  1986.         {
  1987.             XPathNavigator nav;
  1988.             public DebuggerDisplayProxy(XPathNavigator nav)
  1989.             {
  1990.                 this.nav = nav;
  1991.             }
  1992.             public override string ToString()
  1993.             {
  1994.                 string result = nav.NodeType.ToString();
  1995.                 switch (nav.NodeType) {
  1996.                     case XPathNodeType.Element:
  1997.                         result += ", Name=\"" + nav.Name + '"';
  1998.                         break;
  1999.                     case XPathNodeType.Attribute:
  2000.                     case XPathNodeType.Namespace:
  2001.                     case XPathNodeType.ProcessingInstruction:
  2002.                         result += ", Name=\"" + nav.Name + '"';
  2003.                         result += ", Value=\"" + XmlConvert.EscapeValueForDebuggerDisplay(nav.Value) + '"';
  2004.                         break;
  2005.                     case XPathNodeType.Text:
  2006.                     case XPathNodeType.Whitespace:
  2007.                     case XPathNodeType.SignificantWhitespace:
  2008.                     case XPathNodeType.Comment:
  2009.                         result += ", Value=\"" + XmlConvert.EscapeValueForDebuggerDisplay(nav.Value) + '"';
  2010.                         break;
  2011.                 }
  2012.                 return result;
  2013.             }
  2014.         }
  2015.     }
  2016. }

Developer Fusion