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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="DocumentXPathNavigator.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;
  16. using System.Collections;
  17. using System.Collections.Generic;
  18. using System.Text;
  19. using System.Xml.Schema;
  20. using System.Xml.XPath;
  21. using System.Diagnostics;
  22. namespace System.Xml
  23. {
  24.     internal sealed class DocumentXPathNavigator : XPathNavigator, IHasXmlNode
  25.     {
  26.         private XmlDocument document;
  27.         // owner document
  28.         private XmlNode source;
  29.         // navigator position
  30.         private int attributeIndex;
  31.         // index in attribute collection for attribute
  32.         private XmlElement namespaceParent;
  33.         // parent for namespace
  34.         public DocumentXPathNavigator(XmlDocument document, XmlNode node)
  35.         {
  36.             this.document = document;
  37.             ResetPosition(node);
  38.         }
  39.        
  40.         public DocumentXPathNavigator(DocumentXPathNavigator other)
  41.         {
  42.             document = other.document;
  43.             source = other.source;
  44.             attributeIndex = other.attributeIndex;
  45.             namespaceParent = other.namespaceParent;
  46.         }
  47.        
  48.         public override XPathNavigator Clone()
  49.         {
  50.             return new DocumentXPathNavigator(this);
  51.         }
  52.        
  53.         public override void SetValue(string value)
  54.         {
  55.             if (value == null) {
  56.                 throw new ArgumentNullException("value");
  57.             }
  58.            
  59.             XmlNode node = source;
  60.             XmlNode end;
  61.            
  62.             switch (node.NodeType) {
  63.                 case XmlNodeType.Attribute:
  64.                     if (((XmlAttribute)node).IsNamespace) {
  65.                         goto default;
  66.                     }
  67.                     node.InnerText = value;
  68.                     break;
  69.                 case XmlNodeType.Text:
  70.                 case XmlNodeType.CDATA:
  71.                 case XmlNodeType.Whitespace:
  72.                 case XmlNodeType.SignificantWhitespace:
  73.                     CalibrateText();
  74.                    
  75.                     node = source;
  76.                     end = TextEnd(node);
  77.                     if (node != end) {
  78.                         if (node.IsReadOnly) {
  79.                             throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Modify_ReadOnly));
  80.                         }
  81.                         DeleteToFollowingSibling(node.NextSibling, end);
  82.                     }
  83.                     goto case XmlNodeType.Element;
  84.                     break;
  85.                 case XmlNodeType.Element:
  86.                 case XmlNodeType.ProcessingInstruction:
  87.                 case XmlNodeType.Comment:
  88.                     node.InnerText = value;
  89.                     break;
  90.                 default:
  91.                     throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  92.                     break;
  93.             }
  94.         }
  95.        
  96.         public override XmlNameTable NameTable {
  97.             get { return document.NameTable; }
  98.         }
  99.        
  100.         public override XPathNodeType NodeType {
  101.             get {
  102.                 CalibrateText();
  103.                
  104.                 return (XPathNodeType)source.XPNodeType;
  105.             }
  106.         }
  107.        
  108.         public override string LocalName {
  109.             get { return source.XPLocalName; }
  110.         }
  111.        
  112.         public override string NamespaceURI {
  113.             get {
  114.                 XmlAttribute attribute = source as XmlAttribute;
  115.                 if (attribute != null && attribute.IsNamespace) {
  116.                     return string.Empty;
  117.                 }
  118.                 return source.NamespaceURI;
  119.             }
  120.         }
  121.        
  122.         public override string Name {
  123.             get {
  124.                 switch (source.NodeType) {
  125.                     case XmlNodeType.Element:
  126.                     case XmlNodeType.ProcessingInstruction:
  127.                         return source.Name;
  128.                     case XmlNodeType.Attribute:
  129.                         if (((XmlAttribute)source).IsNamespace) {
  130.                             string localName = source.LocalName;
  131.                             if (Ref.Equals(localName, document.strXmlns)) {
  132.                                 return string.Empty;
  133.                                 // xmlns declaration
  134.                             }
  135.                             return localName;
  136.                             // xmlns:name declaration
  137.                         }
  138.                         return source.Name;
  139.                     default:
  140.                         // attribute
  141.                         return string.Empty;
  142.                 }
  143.             }
  144.         }
  145.        
  146.         public override string Prefix {
  147.             get {
  148.                 XmlAttribute attribute = source as XmlAttribute;
  149.                 if (attribute != null && attribute.IsNamespace) {
  150.                     return string.Empty;
  151.                 }
  152.                 return source.Prefix;
  153.             }
  154.         }
  155.        
  156.         public override string Value {
  157.             get {
  158.                 switch (source.NodeType) {
  159.                     case XmlNodeType.Element:
  160.                     case XmlNodeType.DocumentFragment:
  161.                         return source.InnerText;
  162.                     case XmlNodeType.Document:
  163.                         return ValueDocument;
  164.                     case XmlNodeType.Text:
  165.                     case XmlNodeType.CDATA:
  166.                     case XmlNodeType.Whitespace:
  167.                     case XmlNodeType.SignificantWhitespace:
  168.                         return ValueText;
  169.                     default:
  170.                         return source.Value;
  171.                 }
  172.             }
  173.         }
  174.        
  175.         private string ValueDocument {
  176.             get {
  177.                 XmlElement element = document.DocumentElement;
  178.                 if (element != null) {
  179.                     return element.InnerText;
  180.                 }
  181.                 return string.Empty;
  182.             }
  183.         }
  184.        
  185.         private string ValueText {
  186.             get {
  187.                 CalibrateText();
  188.                
  189.                 string value = source.Value;
  190.                 XmlNode nextSibling = NextSibling(source);
  191.                 if (nextSibling != null && nextSibling.IsText) {
  192.                     StringBuilder builder = new StringBuilder(value);
  193.                     do {
  194.                         builder.Append(nextSibling.Value);
  195.                         nextSibling = NextSibling(nextSibling);
  196.                     }
  197.                     while (nextSibling != null && nextSibling.IsText);
  198.                     value = builder.ToString();
  199.                 }
  200.                 return value;
  201.             }
  202.         }
  203.        
  204.         public override string BaseURI {
  205.             get { return source.BaseURI; }
  206.         }
  207.        
  208.         public override bool IsEmptyElement {
  209.             get {
  210.                 XmlElement element = source as XmlElement;
  211.                 if (element != null) {
  212.                     return element.IsEmpty;
  213.                 }
  214.                 return false;
  215.             }
  216.         }
  217.        
  218.         public override string XmlLang {
  219.             get { return source.XmlLang; }
  220.         }
  221.        
  222.         public override object UnderlyingObject {
  223.             get {
  224.                 CalibrateText();
  225.                
  226.                 return source;
  227.             }
  228.         }
  229.        
  230.         public override bool HasAttributes {
  231.             get {
  232.                 XmlElement element = source as XmlElement;
  233.                 if (element != null && element.HasAttributes) {
  234.                     XmlAttributeCollection attributes = element.Attributes;
  235.                     for (int i = 0; i < attributes.Count; i++) {
  236.                         XmlAttribute attribute = attributes[i];
  237.                         if (!attribute.IsNamespace) {
  238.                             return true;
  239.                         }
  240.                     }
  241.                 }
  242.                 return false;
  243.             }
  244.         }
  245.        
  246.         public override string GetAttribute(string localName, string namespaceURI)
  247.         {
  248.             return source.GetXPAttribute(localName, namespaceURI);
  249.         }
  250.        
  251.         public override bool MoveToAttribute(string localName, string namespaceURI)
  252.         {
  253.             XmlElement element = source as XmlElement;
  254.             if (element != null && element.HasAttributes) {
  255.                 XmlAttributeCollection attributes = element.Attributes;
  256.                 for (int i = 0; i < attributes.Count; i++) {
  257.                     XmlAttribute attribute = attributes[i];
  258.                     if (attribute.LocalName == localName && attribute.NamespaceURI == namespaceURI) {
  259.                         if (!attribute.IsNamespace) {
  260.                             source = attribute;
  261.                             attributeIndex = i;
  262.                             return true;
  263.                         }
  264.                         else {
  265.                             return false;
  266.                         }
  267.                     }
  268.                 }
  269.             }
  270.             return false;
  271.         }
  272.        
  273.         public override bool MoveToFirstAttribute()
  274.         {
  275.             XmlElement element = source as XmlElement;
  276.             if (element != null && element.HasAttributes) {
  277.                 XmlAttributeCollection attributes = element.Attributes;
  278.                 for (int i = 0; i < attributes.Count; i++) {
  279.                     XmlAttribute attribute = attributes[i];
  280.                     if (!attribute.IsNamespace) {
  281.                         source = attribute;
  282.                         attributeIndex = i;
  283.                         return true;
  284.                     }
  285.                 }
  286.             }
  287.             return false;
  288.         }
  289.        
  290.         public override bool MoveToNextAttribute()
  291.         {
  292.             XmlAttribute attribute = source as XmlAttribute;
  293.             if (attribute == null || attribute.IsNamespace) {
  294.                 return false;
  295.             }
  296.             XmlAttributeCollection attributes;
  297.             if (!CheckAttributePosition(attribute, out attributes, attributeIndex) && !ResetAttributePosition(attribute, attributes, out attributeIndex)) {
  298.                 return false;
  299.             }
  300.             for (int i = attributeIndex + 1; i < attributes.Count; i++) {
  301.                 attribute = attributes[i];
  302.                 if (!attribute.IsNamespace) {
  303.                     source = attribute;
  304.                     attributeIndex = i;
  305.                     return true;
  306.                 }
  307.             }
  308.             return false;
  309.         }
  310.        
  311.         public override string GetNamespace(string name)
  312.         {
  313.             XmlNode node = source;
  314.             while (node != null && node.NodeType != XmlNodeType.Element) {
  315.                 XmlAttribute attribute = node as XmlAttribute;
  316.                 if (attribute != null) {
  317.                     node = attribute.OwnerElement;
  318.                 }
  319.                 else {
  320.                     node = node.ParentNode;
  321.                 }
  322.             }
  323.            
  324.             XmlElement element = node as XmlElement;
  325.             if (element != null) {
  326.                 string localName;
  327.                 if (name != null && name.Length != 0) {
  328.                     localName = name;
  329.                 }
  330.                 else {
  331.                     localName = document.strXmlns;
  332.                 }
  333.                 string namespaceUri = document.strReservedXmlns;
  334.                
  335.                 do {
  336.                     XmlAttribute attribute = element.GetAttributeNode(localName, namespaceUri);
  337.                     if (attribute != null) {
  338.                         return attribute.Value;
  339.                     }
  340.                     element = element.ParentNode as XmlElement;
  341.                 }
  342.                 while (element != null);
  343.             }
  344.            
  345.             if (name == document.strXml) {
  346.                 return document.strReservedXml;
  347.             }
  348.             else if (name == document.strXmlns) {
  349.                 return document.strReservedXmlns;
  350.             }
  351.             return string.Empty;
  352.         }
  353.        
  354.         public override bool MoveToNamespace(string name)
  355.         {
  356.             if (name == document.strXmlns) {
  357.                 return false;
  358.             }
  359.             XmlElement element = source as XmlElement;
  360.             if (element != null) {
  361.                 string localName;
  362.                 if (name != null && name.Length != 0) {
  363.                     localName = name;
  364.                 }
  365.                 else {
  366.                     localName = document.strXmlns;
  367.                 }
  368.                 string namespaceUri = document.strReservedXmlns;
  369.                
  370.                 do {
  371.                     XmlAttribute attribute = element.GetAttributeNode(localName, namespaceUri);
  372.                     if (attribute != null) {
  373.                         namespaceParent = (XmlElement)source;
  374.                         source = attribute;
  375.                         return true;
  376.                     }
  377.                     element = element.ParentNode as XmlElement;
  378.                 }
  379.                 while (element != null);
  380.                
  381.                 if (name == document.strXml) {
  382.                     namespaceParent = (XmlElement)source;
  383.                     source = document.NamespaceXml;
  384.                     return true;
  385.                 }
  386.             }
  387.             return false;
  388.         }
  389.        
  390.         public override bool MoveToFirstNamespace(XPathNamespaceScope scope)
  391.         {
  392.             XmlElement element = source as XmlElement;
  393.             if (element == null) {
  394.                 return false;
  395.             }
  396.             XmlAttributeCollection attributes;
  397.             int index = Int32.MaxValue;
  398.             switch (scope) {
  399.                 case XPathNamespaceScope.Local:
  400.                     if (!element.HasAttributes) {
  401.                         return false;
  402.                     }
  403.                     attributes = element.Attributes;
  404.                     if (!MoveToFirstNamespaceLocal(attributes, ref index)) {
  405.                         return false;
  406.                     }
  407.                     source = attributes[index];
  408.                     attributeIndex = index;
  409.                     namespaceParent = element;
  410.                     break;
  411.                 case XPathNamespaceScope.ExcludeXml:
  412.                     attributes = element.Attributes;
  413.                     if (!MoveToFirstNamespaceGlobal(ref attributes, ref index)) {
  414.                         return false;
  415.                     }
  416.                     XmlAttribute attribute = attributes[index];
  417.                     while (Ref.Equals(attribute.LocalName, document.strXml)) {
  418.                         if (!MoveToNextNamespaceGlobal(ref attributes, ref index)) {
  419.                             return false;
  420.                         }
  421.                         attribute = attributes[index];
  422.                     }
  423.                     source = attribute;
  424.                     attributeIndex = index;
  425.                     namespaceParent = element;
  426.                     break;
  427.                 case XPathNamespaceScope.All:
  428.                     attributes = element.Attributes;
  429.                     if (!MoveToFirstNamespaceGlobal(ref attributes, ref index)) {
  430.                         source = document.NamespaceXml;
  431.                         // attributeIndex = 0;
  432.                     }
  433.                     else {
  434.                         source = attributes[index];
  435.                         attributeIndex = index;
  436.                     }
  437.                     namespaceParent = element;
  438.                     break;
  439.                 default:
  440.                     Debug.Assert(false);
  441.                     return false;
  442.             }
  443.             return true;
  444.         }
  445.        
  446.         private static bool MoveToFirstNamespaceLocal(XmlAttributeCollection attributes, ref int index)
  447.         {
  448.             Debug.Assert(attributes != null);
  449.             for (int i = attributes.Count - 1; i >= 0; i--) {
  450.                 XmlAttribute attribute = attributes[i];
  451.                 if (attribute.IsNamespace) {
  452.                     index = i;
  453.                     return true;
  454.                 }
  455.             }
  456.             return false;
  457.         }
  458.        
  459.         private static bool MoveToFirstNamespaceGlobal(ref XmlAttributeCollection attributes, ref int index)
  460.         {
  461.             if (MoveToFirstNamespaceLocal(attributes, ref index)) {
  462.                 return true;
  463.             }
  464.            
  465.             Debug.Assert(attributes != null && attributes.parent != null);
  466.             XmlElement element = attributes.parent.ParentNode as XmlElement;
  467.             while (element != null) {
  468.                 if (element.HasAttributes) {
  469.                     attributes = element.Attributes;
  470.                     if (MoveToFirstNamespaceLocal(attributes, ref index)) {
  471.                         return true;
  472.                     }
  473.                 }
  474.                 element = element.ParentNode as XmlElement;
  475.             }
  476.             return false;
  477.         }
  478.        
  479.         public override bool MoveToNextNamespace(XPathNamespaceScope scope)
  480.         {
  481.             XmlAttribute attribute = source as XmlAttribute;
  482.             if (attribute == null || !attribute.IsNamespace) {
  483.                 return false;
  484.             }
  485.             XmlAttributeCollection attributes;
  486.             int index = attributeIndex;
  487.             if (!CheckAttributePosition(attribute, out attributes, index) && !ResetAttributePosition(attribute, attributes, out index)) {
  488.                 return false;
  489.             }
  490.             Debug.Assert(namespaceParent != null);
  491.             switch (scope) {
  492.                 case XPathNamespaceScope.Local:
  493.                     if (attribute.OwnerElement != namespaceParent) {
  494.                         return false;
  495.                     }
  496.                     if (!MoveToNextNamespaceLocal(attributes, ref index)) {
  497.                         return false;
  498.                     }
  499.                     source = attributes[index];
  500.                     attributeIndex = index;
  501.                     break;
  502.                 case XPathNamespaceScope.ExcludeXml:
  503.                     string localName;
  504.                     do {
  505.                         if (!MoveToNextNamespaceGlobal(ref attributes, ref index)) {
  506.                             return false;
  507.                         }
  508.                         attribute = attributes[index];
  509.                         localName = attribute.LocalName;
  510.                     }
  511.                     while (PathHasDuplicateNamespace(attribute.OwnerElement, namespaceParent, localName) || Ref.Equals(localName, document.strXml));
  512.                     source = attribute;
  513.                     attributeIndex = index;
  514.                     break;
  515.                 case XPathNamespaceScope.All:
  516.                     do {
  517.                         if (!MoveToNextNamespaceGlobal(ref attributes, ref index)) {
  518.                             if (PathHasDuplicateNamespace(null, namespaceParent, document.strXml)) {
  519.                                 return false;
  520.                             }
  521.                             else {
  522.                                 source = document.NamespaceXml;
  523.                                 // attributeIndex = 0;
  524.                                 return true;
  525.                             }
  526.                         }
  527.                         attribute = attributes[index];
  528.                     }
  529.                     while (PathHasDuplicateNamespace(attribute.OwnerElement, namespaceParent, attribute.LocalName));
  530.                     source = attribute;
  531.                     attributeIndex = index;
  532.                     break;
  533.                 default:
  534.                     Debug.Assert(false);
  535.                     return false;
  536.             }
  537.             return true;
  538.         }
  539.        
  540.         private static bool MoveToNextNamespaceLocal(XmlAttributeCollection attributes, ref int index)
  541.         {
  542.             Debug.Assert(attributes != null);
  543.             Debug.Assert(0 <= index && index < attributes.Count);
  544.             for (int i = index - 1; i >= 0; i--) {
  545.                 XmlAttribute attribute = attributes[i];
  546.                 if (attribute.IsNamespace) {
  547.                     index = i;
  548.                     return true;
  549.                 }
  550.             }
  551.             return false;
  552.         }
  553.        
  554.         private static bool MoveToNextNamespaceGlobal(ref XmlAttributeCollection attributes, ref int index)
  555.         {
  556.             if (MoveToNextNamespaceLocal(attributes, ref index)) {
  557.                 return true;
  558.             }
  559.            
  560.             Debug.Assert(attributes != null && attributes.parent != null);
  561.             XmlElement element = attributes.parent.ParentNode as XmlElement;
  562.             while (element != null) {
  563.                 if (element.HasAttributes) {
  564.                     attributes = element.Attributes;
  565.                     if (MoveToFirstNamespaceLocal(attributes, ref index)) {
  566.                         return true;
  567.                     }
  568.                 }
  569.                 element = element.ParentNode as XmlElement;
  570.             }
  571.             return false;
  572.         }
  573.        
  574.         private bool PathHasDuplicateNamespace(XmlElement top, XmlElement bottom, string localName)
  575.         {
  576.             string namespaceUri = document.strReservedXmlns;
  577.             while (bottom != null && bottom != top) {
  578.                 XmlAttribute attribute = bottom.GetAttributeNode(localName, namespaceUri);
  579.                 if (attribute != null) {
  580.                     return true;
  581.                 }
  582.                 bottom = bottom.ParentNode as XmlElement;
  583.             }
  584.             return false;
  585.         }
  586.        
  587.         public override bool MoveToNext()
  588.         {
  589.             XmlNode sibling = NextSibling(source);
  590.             if (sibling == null) {
  591.                 return false;
  592.             }
  593.             if (sibling.IsText) {
  594.                 if (source.IsText) {
  595.                     sibling = NextSibling(TextEnd(sibling));
  596.                     if (sibling == null) {
  597.                         return false;
  598.                     }
  599.                 }
  600.             }
  601.             XmlNode parent = ParentNode(sibling);
  602.             Debug.Assert(parent != null);
  603.             while (!IsValidChild(parent, sibling)) {
  604.                 sibling = NextSibling(sibling);
  605.                 if (sibling == null) {
  606.                     return false;
  607.                 }
  608.             }
  609.             source = sibling;
  610.             return true;
  611.         }
  612.        
  613.         public override bool MoveToPrevious()
  614.         {
  615.             XmlNode sibling = PreviousSibling(source);
  616.             if (sibling == null) {
  617.                 return false;
  618.             }
  619.             if (sibling.IsText) {
  620.                 if (source.IsText) {
  621.                     sibling = PreviousSibling(TextStart(sibling));
  622.                     if (sibling == null) {
  623.                         return false;
  624.                     }
  625.                 }
  626.                 else {
  627.                     sibling = TextStart(sibling);
  628.                 }
  629.             }
  630.             XmlNode parent = ParentNode(sibling);
  631.             Debug.Assert(parent != null);
  632.             while (!IsValidChild(parent, sibling)) {
  633.                 sibling = PreviousSibling(sibling);
  634.                 if (sibling == null) {
  635.                     return false;
  636.                 }
  637.                 // if (sibling.IsText) {
  638.                 // sibling = TextStart(sibling);
  639.                 // }
  640.             }
  641.             source = sibling;
  642.             return true;
  643.         }
  644.        
  645.         public override bool MoveToFirst()
  646.         {
  647.             if (source.NodeType == XmlNodeType.Attribute) {
  648.                 return false;
  649.             }
  650.             XmlNode parent = ParentNode(source);
  651.             if (parent == null) {
  652.                 return false;
  653.             }
  654.             XmlNode sibling = FirstChild(parent);
  655.             Debug.Assert(sibling != null);
  656.             while (!IsValidChild(parent, sibling)) {
  657.                 sibling = NextSibling(sibling);
  658.                 if (sibling == null) {
  659.                     return false;
  660.                 }
  661.             }
  662.             source = sibling;
  663.             return true;
  664.         }
  665.        
  666.         public override bool MoveToFirstChild()
  667.         {
  668.             XmlNode child;
  669.             switch (source.NodeType) {
  670.                 case XmlNodeType.Element:
  671.                     child = FirstChild(source);
  672.                     if (child == null) {
  673.                         return false;
  674.                     }
  675.                     break;
  676.                 case XmlNodeType.DocumentFragment:
  677.                 case XmlNodeType.Document:
  678.                     child = FirstChild(source);
  679.                     if (child == null) {
  680.                         return false;
  681.                     }
  682.                     while (!IsValidChild(source, child)) {
  683.                         child = NextSibling(child);
  684.                         if (child == null) {
  685.                             return false;
  686.                         }
  687.                     }
  688.                     break;
  689.                 default:
  690.                     return false;
  691.                
  692.             }
  693.             source = child;
  694.             return true;
  695.         }
  696.        
  697.         public override bool MoveToParent()
  698.         {
  699.             XmlNode parent = ParentNode(source);
  700.             if (parent != null) {
  701.                 source = parent;
  702.                 return true;
  703.             }
  704.             XmlAttribute attribute = source as XmlAttribute;
  705.             if (attribute != null) {
  706.                 parent = attribute.IsNamespace ? namespaceParent : attribute.OwnerElement;
  707.                 if (parent != null) {
  708.                     source = parent;
  709.                     namespaceParent = null;
  710.                     return true;
  711.                 }
  712.             }
  713.             return false;
  714.         }
  715.        
  716.         public override void MoveToRoot()
  717.         {
  718.             for (;;) {
  719.                 XmlNode parent = source.ParentNode;
  720.                 if (parent == null) {
  721.                     XmlAttribute attribute = source as XmlAttribute;
  722.                     if (attribute == null) {
  723.                         break;
  724.                     }
  725.                     parent = attribute.IsNamespace ? namespaceParent : attribute.OwnerElement;
  726.                     if (parent == null) {
  727.                         break;
  728.                     }
  729.                 }
  730.                 source = parent;
  731.             }
  732.             namespaceParent = null;
  733.         }
  734.        
  735.         public override bool MoveTo(XPathNavigator other)
  736.         {
  737.             DocumentXPathNavigator that = other as DocumentXPathNavigator;
  738.             if (that != null && document == that.document) {
  739.                 source = that.source;
  740.                 attributeIndex = that.attributeIndex;
  741.                 namespaceParent = that.namespaceParent;
  742.                 return true;
  743.             }
  744.             return false;
  745.         }
  746.        
  747.         public override bool MoveToId(string id)
  748.         {
  749.             XmlElement element = document.GetElementById(id);
  750.             if (element != null) {
  751.                 source = element;
  752.                 namespaceParent = null;
  753.                 return true;
  754.             }
  755.             return false;
  756.         }
  757.        
  758.         public override bool MoveToChild(string localName, string namespaceUri)
  759.         {
  760.             if (source.NodeType == XmlNodeType.Attribute) {
  761.                 return false;
  762.             }
  763.            
  764.             XmlNode child = FirstChild(source);
  765.             if (child != null) {
  766.                 do {
  767.                     if (child.NodeType == XmlNodeType.Element && child.LocalName == localName && child.NamespaceURI == namespaceUri) {
  768.                         source = child;
  769.                         return true;
  770.                     }
  771.                     child = NextSibling(child);
  772.                 }
  773.                 while (child != null);
  774.             }
  775.             return false;
  776.         }
  777.        
  778.         public override bool MoveToChild(XPathNodeType type)
  779.         {
  780.             if (source.NodeType == XmlNodeType.Attribute) {
  781.                 return false;
  782.             }
  783.            
  784.             XmlNode child = FirstChild(source);
  785.             if (child != null) {
  786.                 int mask = GetContentKindMask(type);
  787.                 if (mask == 0) {
  788.                     return false;
  789.                 }
  790.                 do {
  791.                     if (((1 << (int)child.XPNodeType) & mask) != 0) {
  792.                         source = child;
  793.                         return true;
  794.                     }
  795.                     child = NextSibling(child);
  796.                 }
  797.                 while (child != null);
  798.             }
  799.             return false;
  800.         }
  801.        
  802.         public override bool MoveToFollowing(string localName, string namespaceUri, XPathNavigator end)
  803.         {
  804.             XmlNode pastFollowing = null;
  805.             DocumentXPathNavigator that = end as DocumentXPathNavigator;
  806.             if (that != null) {
  807.                 if (document != that.document) {
  808.                     return false;
  809.                 }
  810.                 switch (that.source.NodeType) {
  811.                     case XmlNodeType.Attribute:
  812.                         that = (DocumentXPathNavigator)that.Clone();
  813.                         if (!that.MoveToNonDescendant()) {
  814.                             return false;
  815.                         }
  816.                         break;
  817.                 }
  818.                 pastFollowing = that.source;
  819.             }
  820.            
  821.             XmlNode following = source;
  822.             if (following.NodeType == XmlNodeType.Attribute) {
  823.                 following = ((XmlAttribute)following).OwnerElement;
  824.                 if (following == null) {
  825.                     return false;
  826.                 }
  827.             }
  828.             do {
  829.                 XmlNode firstChild = following.FirstChild;
  830.                 if (firstChild != null) {
  831.                     following = firstChild;
  832.                 }
  833.                 else {
  834.                     for (;;) {
  835.                         XmlNode nextSibling = following.NextSibling;
  836.                         if (nextSibling != null) {
  837.                             following = nextSibling;
  838.                             break;
  839.                         }
  840.                         else {
  841.                             XmlNode parent = following.ParentNode;
  842.                             if (parent != null) {
  843.                                 following = parent;
  844.                             }
  845.                             else {
  846.                                 return false;
  847.                             }
  848.                         }
  849.                     }
  850.                 }
  851.                 if (following == pastFollowing) {
  852.                     return false;
  853.                 }
  854.             }
  855.             while (following.NodeType != XmlNodeType.Element || following.LocalName != localName || following.NamespaceURI != namespaceUri);
  856.            
  857.             source = following;
  858.             return true;
  859.         }
  860.        
  861.         public override bool MoveToFollowing(XPathNodeType type, XPathNavigator end)
  862.         {
  863.             XmlNode pastFollowing = null;
  864.             DocumentXPathNavigator that = end as DocumentXPathNavigator;
  865.             if (that != null) {
  866.                 if (document != that.document) {
  867.                     return false;
  868.                 }
  869.                 switch (that.source.NodeType) {
  870.                     case XmlNodeType.Attribute:
  871.                         that = (DocumentXPathNavigator)that.Clone();
  872.                         if (!that.MoveToNonDescendant()) {
  873.                             return false;
  874.                         }
  875.                         break;
  876.                 }
  877.                 pastFollowing = that.source;
  878.             }
  879.            
  880.             int mask = GetContentKindMask(type);
  881.             if (mask == 0) {
  882.                 return false;
  883.             }
  884.             XmlNode following = source;
  885.             switch (following.NodeType) {
  886.                 case XmlNodeType.Attribute:
  887.                     following = ((XmlAttribute)following).OwnerElement;
  888.                     if (following == null) {
  889.                         return false;
  890.                     }
  891.                     break;
  892.                 case XmlNodeType.Text:
  893.                 case XmlNodeType.CDATA:
  894.                 case XmlNodeType.SignificantWhitespace:
  895.                 case XmlNodeType.Whitespace:
  896.                     following = TextEnd(following);
  897.                     break;
  898.             }
  899.             do {
  900.                 XmlNode firstChild = following.FirstChild;
  901.                 if (firstChild != null) {
  902.                     following = firstChild;
  903.                 }
  904.                 else {
  905.                     for (;;) {
  906.                         XmlNode nextSibling = following.NextSibling;
  907.                         if (nextSibling != null) {
  908.                             following = nextSibling;
  909.                             break;
  910.                         }
  911.                         else {
  912.                             XmlNode parent = following.ParentNode;
  913.                             if (parent != null) {
  914.                                 following = parent;
  915.                             }
  916.                             else {
  917.                                 return false;
  918.                             }
  919.                         }
  920.                     }
  921.                 }
  922.                 if (following == pastFollowing) {
  923.                     return false;
  924.                 }
  925.             }
  926.             while (((1 << (int)following.XPNodeType) & mask) == 0);
  927.            
  928.             source = following;
  929.             return true;
  930.         }
  931.        
  932.         public override bool MoveToNext(string localName, string namespaceUri)
  933.         {
  934.             XmlNode sibling = NextSibling(source);
  935.             if (sibling == null) {
  936.                 return false;
  937.             }
  938.             do {
  939.                 if (sibling.NodeType == XmlNodeType.Element && sibling.LocalName == localName && sibling.NamespaceURI == namespaceUri) {
  940.                     source = sibling;
  941.                     return true;
  942.                 }
  943.                 sibling = NextSibling(sibling);
  944.             }
  945.             while (sibling != null);
  946.             return false;
  947.         }
  948.        
  949.         public override bool MoveToNext(XPathNodeType type)
  950.         {
  951.             XmlNode sibling = NextSibling(source);
  952.             if (sibling == null) {
  953.                 return false;
  954.             }
  955.             if (sibling.IsText && source.IsText) {
  956.                 sibling = NextSibling(TextEnd(sibling));
  957.                 if (sibling == null) {
  958.                     return false;
  959.                 }
  960.             }
  961.            
  962.             int mask = GetContentKindMask(type);
  963.             if (mask == 0) {
  964.                 return false;
  965.             }
  966.             do {
  967.                 if (((1 << (int)sibling.XPNodeType) & mask) != 0) {
  968.                     source = sibling;
  969.                     return true;
  970.                 }
  971.                 sibling = NextSibling(sibling);
  972.             }
  973.             while (sibling != null);
  974.             return false;
  975.         }
  976.        
  977.         public override bool HasChildren {
  978.             get {
  979.                 XmlNode child;
  980.                 switch (source.NodeType) {
  981.                     case XmlNodeType.Element:
  982.                         child = FirstChild(source);
  983.                         if (child == null) {
  984.                             return false;
  985.                         }
  986.                         return true;
  987.                     case XmlNodeType.DocumentFragment:
  988.                     case XmlNodeType.Document:
  989.                         child = FirstChild(source);
  990.                         if (child == null) {
  991.                             return false;
  992.                         }
  993.                         while (!IsValidChild(source, child)) {
  994.                             child = NextSibling(child);
  995.                             if (child == null) {
  996.                                 return false;
  997.                             }
  998.                         }
  999.                         return true;
  1000.                     default:
  1001.                         return false;
  1002.                 }
  1003.             }
  1004.         }
  1005.        
  1006.         public override bool IsSamePosition(XPathNavigator other)
  1007.         {
  1008.             DocumentXPathNavigator that = other as DocumentXPathNavigator;
  1009.             if (that != null) {
  1010.                 this.CalibrateText();
  1011.                 that.CalibrateText();
  1012.                
  1013.                 return this.source == that.source && this.namespaceParent == that.namespaceParent;
  1014.             }
  1015.             return false;
  1016.         }
  1017.        
  1018.         public override bool IsDescendant(XPathNavigator other)
  1019.         {
  1020.             DocumentXPathNavigator that = other as DocumentXPathNavigator;
  1021.             if (that != null) {
  1022.                 return IsDescendant(this.source, that.source);
  1023.             }
  1024.             return false;
  1025.         }
  1026.        
  1027.         public override IXmlSchemaInfo SchemaInfo {
  1028.             get { return source.SchemaInfo; }
  1029.         }
  1030.        
  1031.         public override bool CheckValidity(XmlSchemaSet schemas, ValidationEventHandler validationEventHandler)
  1032.         {
  1033.             XmlDocument ownerDocument;
  1034.            
  1035.             if (source.NodeType == XmlNodeType.Document) {
  1036.                 ownerDocument = (XmlDocument)source;
  1037.             }
  1038.             else {
  1039.                 ownerDocument = source.OwnerDocument;
  1040.                
  1041.                 if (schemas != null) {
  1042.                     throw new ArgumentException(Res.GetString(Res.XPathDocument_SchemaSetNotAllowed, null));
  1043.                 }
  1044.             }
  1045.             if (schemas == null && ownerDocument != null) {
  1046.                 schemas = ownerDocument.Schemas;
  1047.             }
  1048.            
  1049.             if (schemas == null || schemas.Count == 0) {
  1050.                 throw new InvalidOperationException(Res.GetString(Res.XmlDocument_NoSchemaInfo));
  1051.             }
  1052.            
  1053.             DocumentSchemaValidator validator = new DocumentSchemaValidator(ownerDocument, schemas, validationEventHandler);
  1054.             validator.PsviAugmentation = false;
  1055.             return validator.Validate(source);
  1056.         }
  1057.        
  1058.         private static XmlNode OwnerNode(XmlNode node)
  1059.         {
  1060.             XmlNode parent = node.ParentNode;
  1061.             if (parent != null) {
  1062.                 return parent;
  1063.             }
  1064.             XmlAttribute attribute = node as XmlAttribute;
  1065.             if (attribute != null) {
  1066.                 return attribute.OwnerElement;
  1067.             }
  1068.             return null;
  1069.         }
  1070.        
  1071.         private static int GetDepth(XmlNode node)
  1072.         {
  1073.             int depth = 0;
  1074.             XmlNode owner = OwnerNode(node);
  1075.             while (owner != null) {
  1076.                 depth++;
  1077.                 owner = OwnerNode(owner);
  1078.             }
  1079.             return depth;
  1080.         }
  1081.        
  1082.         //Assuming that node1 and node2 are in the same level; Except when they are namespace nodes, they should have the same parent node
  1083.         //the returned value is node2's position corresponding to node1
  1084.         private XmlNodeOrder Compare(XmlNode node1, XmlNode node2)
  1085.         {
  1086.             Debug.Assert(node1 != null);
  1087.             Debug.Assert(node2 != null);
  1088.             Debug.Assert(node1 != node2, "Should be handled by ComparePosition()");
  1089.             //Attribute nodes come before other children nodes except namespace nodes
  1090.             Debug.Assert(OwnerNode(node1) == OwnerNode(node2));
  1091.             if (node1.XPNodeType == XPathNodeType.Attribute) {
  1092.                 if (node2.XPNodeType == XPathNodeType.Attribute) {
  1093.                     XmlElement element = ((XmlAttribute)node1).OwnerElement;
  1094.                     if (element.HasAttributes) {
  1095.                         XmlAttributeCollection attributes = element.Attributes;
  1096.                         for (int i = 0; i < attributes.Count; i++) {
  1097.                             XmlAttribute attribute = attributes[i];
  1098.                             if (attribute == node1) {
  1099.                                 return XmlNodeOrder.Before;
  1100.                             }
  1101.                             else if (attribute == node2) {
  1102.                                 return XmlNodeOrder.After;
  1103.                             }
  1104.                         }
  1105.                     }
  1106.                     return XmlNodeOrder.Unknown;
  1107.                 }
  1108.                 else {
  1109.                     return XmlNodeOrder.Before;
  1110.                 }
  1111.             }
  1112.             if (node2.XPNodeType == XPathNodeType.Attribute) {
  1113.                 return XmlNodeOrder.After;
  1114.             }
  1115.            
  1116.             //neither of the node is Namespace node or Attribute node
  1117.             XmlNode nextNode = node1.NextSibling;
  1118.             while (nextNode != null && nextNode != node2)
  1119.                 nextNode = nextNode.NextSibling;
  1120.             if (nextNode == null)
  1121.                 return XmlNodeOrder.After;
  1122.             else
  1123.                 //didn't meet node2 in the path to the end, thus it has to be in the front of node1
  1124.                 //met node2 in the path to the end, so node1 is at front
  1125.                 return XmlNodeOrder.Before;
  1126.         }
  1127.        
  1128.         public override XmlNodeOrder ComparePosition(XPathNavigator other)
  1129.         {
  1130.             DocumentXPathNavigator that = other as DocumentXPathNavigator;
  1131.             if (that == null) {
  1132.                 return XmlNodeOrder.Unknown;
  1133.             }
  1134.            
  1135.             this.CalibrateText();
  1136.             that.CalibrateText();
  1137.            
  1138.             if (this.source == that.source && this.namespaceParent == that.namespaceParent) {
  1139.                 return XmlNodeOrder.Same;
  1140.             }
  1141.            
  1142.             if (this.namespaceParent != null || that.namespaceParent != null) {
  1143.                 return base.ComparePosition(other);
  1144.             }
  1145.            
  1146.             XmlNode node1 = this.source;
  1147.             XmlNode node2 = that.source;
  1148.            
  1149.             XmlNode parent1 = OwnerNode(node1);
  1150.             XmlNode parent2 = OwnerNode(node2);
  1151.             if (parent1 == parent2) {
  1152.                 if (parent1 == null) {
  1153.                     return XmlNodeOrder.Unknown;
  1154.                 }
  1155.                 else {
  1156.                     Debug.Assert(node1 != node2);
  1157.                     return Compare(node1, node2);
  1158.                 }
  1159.             }
  1160.            
  1161.             int depth1 = GetDepth(node1);
  1162.             int depth2 = GetDepth(node2);
  1163.             if (depth2 > depth1) {
  1164.                 while (node2 != null && depth2 > depth1) {
  1165.                     node2 = OwnerNode(node2);
  1166.                     depth2--;
  1167.                 }
  1168.                 if (node1 == node2) {
  1169.                     return XmlNodeOrder.Before;
  1170.                 }
  1171.                 parent2 = OwnerNode(node2);
  1172.             }
  1173.             else if (depth1 > depth2) {
  1174.                 while (node1 != null && depth1 > depth2) {
  1175.                     node1 = OwnerNode(node1);
  1176.                     depth1--;
  1177.                 }
  1178.                 if (node1 == node2) {
  1179.                     return XmlNodeOrder.After;
  1180.                 }
  1181.                 parent1 = OwnerNode(node1);
  1182.             }
  1183.            
  1184.             while (parent1 != null && parent2 != null) {
  1185.                 if (parent1 == parent2) {
  1186.                     Debug.Assert(node1 != node2);
  1187.                     return Compare(node1, node2);
  1188.                 }
  1189.                 node1 = parent1;
  1190.                 node2 = parent2;
  1191.                 parent1 = OwnerNode(node1);
  1192.                 parent2 = OwnerNode(node2);
  1193.             }
  1194.             return XmlNodeOrder.Unknown;
  1195.         }
  1196.        
  1197.         //the function just for XPathNodeList to enumerate current Node.
  1198.         XmlNode IHasXmlNode.GetNode()
  1199.         {
  1200.             return source;
  1201.         }
  1202.        
  1203.         public override XPathNodeIterator SelectDescendants(string localName, string namespaceURI, bool matchSelf)
  1204.         {
  1205.             string nsAtom = document.NameTable.Get(namespaceURI);
  1206.             if (nsAtom == null || this.source.NodeType == XmlNodeType.Attribute)
  1207.                 return new DocumentXPathNodeIterator_Empty(this);
  1208.            
  1209.             Debug.Assert(this.NodeType != XPathNodeType.Attribute && this.NodeType != XPathNodeType.Namespace && this.NodeType != XPathNodeType.All);
  1210.            
  1211.             string localNameAtom = document.NameTable.Get(localName);
  1212.             if (localNameAtom == null)
  1213.                 return new DocumentXPathNodeIterator_Empty(this);
  1214.            
  1215.             if (localNameAtom.Length == 0) {
  1216.                 if (matchSelf)
  1217.                     return new DocumentXPathNodeIterator_ElemChildren_AndSelf_NoLocalName(this, nsAtom);
  1218.                 return new DocumentXPathNodeIterator_ElemChildren_NoLocalName(this, nsAtom);
  1219.             }
  1220.            
  1221.             if (matchSelf)
  1222.                 return new DocumentXPathNodeIterator_ElemChildren_AndSelf(this, localNameAtom, nsAtom);
  1223.             return new DocumentXPathNodeIterator_ElemChildren(this, localNameAtom, nsAtom);
  1224.         }
  1225.        
  1226.         public override XPathNodeIterator SelectDescendants(XPathNodeType nt, bool includeSelf)
  1227.         {
  1228.             if (nt == XPathNodeType.Element) {
  1229.                 XmlNodeType curNT = source.NodeType;
  1230.                 if (curNT != XmlNodeType.Document && curNT != XmlNodeType.Element) {
  1231.                     //only Document, Entity, Element node can have Element node as children ( descendant )
  1232.                     //entity nodes should be invisible to XPath data model
  1233.                     return new DocumentXPathNodeIterator_Empty(this);
  1234.                 }
  1235.                 if (includeSelf)
  1236.                     return new DocumentXPathNodeIterator_AllElemChildren_AndSelf(this);
  1237.                 return new DocumentXPathNodeIterator_AllElemChildren(this);
  1238.             }
  1239.             return base.SelectDescendants(nt, includeSelf);
  1240.         }
  1241.        
  1242.         public override bool CanEdit {
  1243.             get { return true; }
  1244.         }
  1245.        
  1246.         public override XmlWriter PrependChild()
  1247.         {
  1248.             switch (source.NodeType) {
  1249.                 case XmlNodeType.Element:
  1250.                 case XmlNodeType.Document:
  1251.                 case XmlNodeType.DocumentFragment:
  1252.                     break;
  1253.                 default:
  1254.                     throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  1255.                     break;
  1256.             }
  1257.            
  1258.             DocumentXmlWriter writer = new DocumentXmlWriter(DocumentXmlWriterType.PrependChild, source, document);
  1259.             writer.NamespaceManager = GetNamespaceManager(source, document);
  1260.             return new XmlWellFormedWriter(writer, writer.Settings);
  1261.         }
  1262.        
  1263.         public override XmlWriter AppendChild()
  1264.         {
  1265.             switch (source.NodeType) {
  1266.                 case XmlNodeType.Element:
  1267.                 case XmlNodeType.Document:
  1268.                 case XmlNodeType.DocumentFragment:
  1269.                     break;
  1270.                 default:
  1271.                     throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  1272.                     break;
  1273.             }
  1274.            
  1275.             DocumentXmlWriter writer = new DocumentXmlWriter(DocumentXmlWriterType.AppendChild, source, document);
  1276.             writer.NamespaceManager = GetNamespaceManager(source, document);
  1277.             return new XmlWellFormedWriter(writer, writer.Settings);
  1278.         }
  1279.        
  1280.         public override XmlWriter InsertAfter()
  1281.         {
  1282.             XmlNode node = source;
  1283.            
  1284.             switch (node.NodeType) {
  1285.                 case XmlNodeType.Attribute:
  1286.                 case XmlNodeType.Document:
  1287.                 case XmlNodeType.DocumentFragment:
  1288.                     throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  1289.                     break;
  1290.                 case XmlNodeType.Text:
  1291.                 case XmlNodeType.CDATA:
  1292.                 case XmlNodeType.SignificantWhitespace:
  1293.                 case XmlNodeType.Whitespace:
  1294.                     node = TextEnd(node);
  1295.                     break;
  1296.                 default:
  1297.                     break;
  1298.             }
  1299.            
  1300.             DocumentXmlWriter writer = new DocumentXmlWriter(DocumentXmlWriterType.InsertSiblingAfter, node, document);
  1301.             writer.NamespaceManager = GetNamespaceManager(node.ParentNode, document);
  1302.             return new XmlWellFormedWriter(writer, writer.Settings);
  1303.         }
  1304.        
  1305.         public override XmlWriter InsertBefore()
  1306.         {
  1307.             switch (source.NodeType) {
  1308.                 case XmlNodeType.Attribute:
  1309.                 case XmlNodeType.Document:
  1310.                 case XmlNodeType.DocumentFragment:
  1311.                     throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  1312.                     break;
  1313.                 case XmlNodeType.Text:
  1314.                 case XmlNodeType.CDATA:
  1315.                 case XmlNodeType.SignificantWhitespace:
  1316.                 case XmlNodeType.Whitespace:
  1317.                     CalibrateText();
  1318.                    
  1319.                     break;
  1320.                 default:
  1321.                     break;
  1322.             }
  1323.            
  1324.             DocumentXmlWriter writer = new DocumentXmlWriter(DocumentXmlWriterType.InsertSiblingBefore, source, document);
  1325.             writer.NamespaceManager = GetNamespaceManager(source.ParentNode, document);
  1326.             return new XmlWellFormedWriter(writer, writer.Settings);
  1327.         }
  1328.        
  1329.         public override XmlWriter CreateAttributes()
  1330.         {
  1331.             if (source.NodeType != XmlNodeType.Element) {
  1332.                 throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  1333.             }
  1334.            
  1335.             DocumentXmlWriter writer = new DocumentXmlWriter(DocumentXmlWriterType.AppendAttribute, source, document);
  1336.             writer.NamespaceManager = GetNamespaceManager(source, document);
  1337.             return new XmlWellFormedWriter(writer, writer.Settings);
  1338.         }
  1339.        
  1340.         public override XmlWriter ReplaceRange(XPathNavigator lastSiblingToReplace)
  1341.         {
  1342.             DocumentXPathNavigator that = lastSiblingToReplace as DocumentXPathNavigator;
  1343.             if (that == null) {
  1344.                 if (lastSiblingToReplace == null) {
  1345.                     throw new ArgumentNullException("lastSiblingToReplace");
  1346.                 }
  1347.                 else {
  1348.                     throw new NotSupportedException();
  1349.                 }
  1350.             }
  1351.            
  1352.             this.CalibrateText();
  1353.             that.CalibrateText();
  1354.            
  1355.             XmlNode node = this.source;
  1356.             XmlNode end = that.source;
  1357.            
  1358.             if (node == end) {
  1359.                 switch (node.NodeType) {
  1360.                     case XmlNodeType.Attribute:
  1361.                     case XmlNodeType.Document:
  1362.                     case XmlNodeType.DocumentFragment:
  1363.                         throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  1364.                         break;
  1365.                     case XmlNodeType.Text:
  1366.                     case XmlNodeType.CDATA:
  1367.                     case XmlNodeType.SignificantWhitespace:
  1368.                     case XmlNodeType.Whitespace:
  1369.                         end = that.TextEnd(end);
  1370.                         break;
  1371.                     default:
  1372.                         break;
  1373.                 }
  1374.             }
  1375.             else {
  1376.                 if (end.IsText) {
  1377.                     end = that.TextEnd(end);
  1378.                 }
  1379.                 if (!IsFollowingSibling(node, end)) {
  1380.                     throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  1381.                 }
  1382.             }
  1383.            
  1384.             DocumentXmlWriter writer = new DocumentXmlWriter(DocumentXmlWriterType.ReplaceToFollowingSibling, node, document);
  1385.             writer.NamespaceManager = GetNamespaceManager(node.ParentNode, document);
  1386.             writer.Navigator = this;
  1387.             writer.EndNode = end;
  1388.             return new XmlWellFormedWriter(writer, writer.Settings);
  1389.         }
  1390.        
  1391.         public override void DeleteRange(XPathNavigator lastSiblingToDelete)
  1392.         {
  1393.             DocumentXPathNavigator that = lastSiblingToDelete as DocumentXPathNavigator;
  1394.             if (that == null) {
  1395.                 if (lastSiblingToDelete == null) {
  1396.                     throw new ArgumentNullException("lastSiblingToDelete");
  1397.                 }
  1398.                 else {
  1399.                     throw new NotSupportedException();
  1400.                 }
  1401.             }
  1402.            
  1403.             this.CalibrateText();
  1404.             that.CalibrateText();
  1405.            
  1406.             XmlNode node = this.source;
  1407.             XmlNode end = that.source;
  1408.            
  1409.             if (node == end) {
  1410.                 switch (node.NodeType) {
  1411.                     case XmlNodeType.Attribute:
  1412.                         XmlAttribute attribute = (XmlAttribute)node;
  1413.                         if (attribute.IsNamespace) {
  1414.                             goto default;
  1415.                         }
  1416.                         XmlNode parent = OwnerNode(attribute);
  1417.                         DeleteAttribute(attribute, attributeIndex);
  1418.                         if (parent != null) {
  1419.                             ResetPosition(parent);
  1420.                         }
  1421.                         break;
  1422.                     case XmlNodeType.Text:
  1423.                     case XmlNodeType.CDATA:
  1424.                     case XmlNodeType.SignificantWhitespace:
  1425.                     case XmlNodeType.Whitespace:
  1426.                         end = that.TextEnd(end);
  1427.                         goto case XmlNodeType.Element;
  1428.                         break;
  1429.                     case XmlNodeType.Element:
  1430.                     case XmlNodeType.ProcessingInstruction:
  1431.                     case XmlNodeType.Comment:
  1432.                         parent = OwnerNode(node);
  1433.                         DeleteToFollowingSibling(node, end);
  1434.                         if (parent != null) {
  1435.                             ResetPosition(parent);
  1436.                         }
  1437.                         break;
  1438.                     default:
  1439.                         throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  1440.                         break;
  1441.                 }
  1442.             }
  1443.             else {
  1444.                 if (end.IsText) {
  1445.                     end = that.TextEnd(end);
  1446.                 }
  1447.                 if (!IsFollowingSibling(node, end)) {
  1448.                     throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  1449.                 }
  1450.                 XmlNode parent = OwnerNode(node);
  1451.                 DeleteToFollowingSibling(node, end);
  1452.                 if (parent != null) {
  1453.                     ResetPosition(parent);
  1454.                 }
  1455.             }
  1456.         }
  1457.        
  1458.         public override void DeleteSelf()
  1459.         {
  1460.             XmlNode node = source;
  1461.             XmlNode end = node;
  1462.            
  1463.             switch (node.NodeType) {
  1464.                 case XmlNodeType.Attribute:
  1465.                     XmlAttribute attribute = (XmlAttribute)node;
  1466.                     if (attribute.IsNamespace) {
  1467.                         goto default;
  1468.                     }
  1469.                     XmlNode parent = OwnerNode(attribute);
  1470.                     DeleteAttribute(attribute, attributeIndex);
  1471.                     if (parent != null) {
  1472.                         ResetPosition(parent);
  1473.                     }
  1474.                     break;
  1475.                 case XmlNodeType.Text:
  1476.                 case XmlNodeType.CDATA:
  1477.                 case XmlNodeType.SignificantWhitespace:
  1478.                 case XmlNodeType.Whitespace:
  1479.                     CalibrateText();
  1480.                    
  1481.                     node = source;
  1482.                     end = TextEnd(node);
  1483.                     goto case XmlNodeType.Element;
  1484.                     break;
  1485.                 case XmlNodeType.Element:
  1486.                 case XmlNodeType.ProcessingInstruction:
  1487.                 case XmlNodeType.Comment:
  1488.                     parent = OwnerNode(node);
  1489.                     DeleteToFollowingSibling(node, end);
  1490.                     if (parent != null) {
  1491.                         ResetPosition(parent);
  1492.                     }
  1493.                     break;
  1494.                 default:
  1495.                     throw new InvalidOperationException(Res.GetString(Res.Xpn_BadPosition));
  1496.                     break;
  1497.             }
  1498.         }
  1499.        
  1500.         private static void DeleteAttribute(XmlAttribute attribute, int index)
  1501.         {
  1502.             XmlAttributeCollection attributes;
  1503.            
  1504.             if (!CheckAttributePosition(attribute, out attributes, index) && !ResetAttributePosition(attribute, attributes, out index)) {
  1505.                 throw new InvalidOperationException(Res.GetString(Res.Xpn_MissingParent));
  1506.             }
  1507.             if (attribute.IsReadOnly) {
  1508.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Modify_ReadOnly));
  1509.             }
  1510.             attributes.RemoveAt(index);
  1511.         }
  1512.        
  1513.         static internal void DeleteToFollowingSibling(XmlNode node, XmlNode end)
  1514.         {
  1515.             XmlNode parent = node.ParentNode;
  1516.            
  1517.             if (parent == null) {
  1518.                 throw new InvalidOperationException(Res.GetString(Res.Xpn_MissingParent));
  1519.             }
  1520.             if (node.IsReadOnly || end.IsReadOnly) {
  1521.                 throw new InvalidOperationException(Res.GetString(Res.Xdom_Node_Modify_ReadOnly));
  1522.             }
  1523.             while (node != end) {
  1524.                 XmlNode temp = node;
  1525.                 node = node.NextSibling;
  1526.                 parent.RemoveChild(temp);
  1527.             }
  1528.             parent.RemoveChild(node);
  1529.         }
  1530.        
  1531.         private static XmlNamespaceManager GetNamespaceManager(XmlNode node, XmlDocument document)
  1532.         {
  1533.             XmlNamespaceManager namespaceManager = new XmlNamespaceManager(document.NameTable);
  1534.             List<XmlElement> elements = new List<XmlElement>();
  1535.            
  1536.             while (node != null) {
  1537.                 XmlElement element = node as XmlElement;
  1538.                 if (element != null && element.HasAttributes) {
  1539.                     elements.Add(element);
  1540.                 }
  1541.                 node = node.ParentNode;
  1542.             }
  1543.             for (int i = elements.Count - 1; i >= 0; i--) {
  1544.                 namespaceManager.PushScope();
  1545.                 XmlAttributeCollection attributes = elements[i].Attributes;
  1546.                 for (int j = 0; j < attributes.Count; j++) {
  1547.                     XmlAttribute attribute = attributes[j];
  1548.                     if (attribute.IsNamespace) {
  1549.                         string prefix = attribute.Prefix.Length == 0 ? string.Empty : attribute.LocalName;
  1550.                         namespaceManager.AddNamespace(prefix, attribute.Value);
  1551.                     }
  1552.                 }
  1553.             }
  1554.             return namespaceManager;
  1555.         }
  1556.        
  1557.         internal void ResetPosition(XmlNode node)
  1558.         {
  1559.             Debug.Assert(node != null, "Undefined navigator position");
  1560.             Debug.Assert(node == document || node.OwnerDocument == document, "Navigator switched documents");
  1561.             source = node;
  1562.             XmlAttribute attribute = node as XmlAttribute;
  1563.             if (attribute != null) {
  1564.                 XmlElement element = attribute.OwnerElement;
  1565.                 if (element != null) {
  1566.                     ResetAttributePosition(attribute, element.Attributes, out attributeIndex);
  1567.                     if (attribute.IsNamespace) {
  1568.                         namespaceParent = element;
  1569.                     }
  1570.                 }
  1571.             }
  1572.         }
  1573.        
  1574.         private static bool ResetAttributePosition(XmlAttribute attribute, XmlAttributeCollection attributes, out int index)
  1575.         {
  1576.             if (attributes != null) {
  1577.                 for (int i = 0; i < attributes.Count; i++) {
  1578.                     if (attribute == attributes[i]) {
  1579.                         index = i;
  1580.                         return true;
  1581.                     }
  1582.                 }
  1583.             }
  1584.             index = 0;
  1585.             return false;
  1586.         }
  1587.        
  1588.         private static bool CheckAttributePosition(XmlAttribute attribute, out XmlAttributeCollection attributes, int index)
  1589.         {
  1590.             XmlElement element = attribute.OwnerElement;
  1591.             if (element != null) {
  1592.                 attributes = element.Attributes;
  1593.                 if (index >= 0 && index < attributes.Count && attribute == attributes[index]) {
  1594.                     return true;
  1595.                 }
  1596.             }
  1597.             else {
  1598.                 attributes = null;
  1599.             }
  1600.             return false;
  1601.         }
  1602.        
  1603.         private void CalibrateText()
  1604.         {
  1605.             XmlNode text = PreviousText(source);
  1606.             while (text != null) {
  1607.                 ResetPosition(text);
  1608.                 text = PreviousText(text);
  1609.             }
  1610.         }
  1611.        
  1612.         private XmlNode ParentNode(XmlNode node)
  1613.         {
  1614.             XmlNode parent = node.ParentNode;
  1615.            
  1616.             if (!document.HasEntityReferences) {
  1617.                 return parent;
  1618.             }
  1619.             return ParentNodeTail(parent);
  1620.         }
  1621.        
  1622.         private XmlNode ParentNodeTail(XmlNode parent)
  1623.         {
  1624.             while (parent != null && parent.NodeType == XmlNodeType.EntityReference) {
  1625.                 parent = parent.ParentNode;
  1626.             }
  1627.             return parent;
  1628.         }
  1629.        
  1630.         private XmlNode FirstChild(XmlNode node)
  1631.         {
  1632.             XmlNode child = node.FirstChild;
  1633.            
  1634.             if (!document.HasEntityReferences) {
  1635.                 return child;
  1636.             }
  1637.             return FirstChildTail(child);
  1638.         }
  1639.        
  1640.         private XmlNode FirstChildTail(XmlNode child)
  1641.         {
  1642.             while (child != null && child.NodeType == XmlNodeType.EntityReference) {
  1643.                 child = child.FirstChild;
  1644.             }
  1645.             return child;
  1646.         }
  1647.        
  1648.         private XmlNode NextSibling(XmlNode node)
  1649.         {
  1650.             XmlNode sibling = node.NextSibling;
  1651.            
  1652.             if (!document.HasEntityReferences) {
  1653.                 return sibling;
  1654.             }
  1655.             return NextSiblingTail(node, sibling);
  1656.         }
  1657.        
  1658.         private XmlNode NextSiblingTail(XmlNode node, XmlNode sibling)
  1659.         {
  1660.             while (sibling == null) {
  1661.                 node = node.ParentNode;
  1662.                 if (node == null || node.NodeType != XmlNodeType.EntityReference) {
  1663.                     return null;
  1664.                 }
  1665.                 sibling = node.NextSibling;
  1666.             }
  1667.             while (sibling != null && sibling.NodeType == XmlNodeType.EntityReference) {
  1668.                 sibling = sibling.FirstChild;
  1669.             }
  1670.             return sibling;
  1671.         }
  1672.        
  1673.         private XmlNode PreviousSibling(XmlNode node)
  1674.         {
  1675.             XmlNode sibling = node.PreviousSibling;
  1676.            
  1677.             if (!document.HasEntityReferences) {
  1678.                 return sibling;
  1679.             }
  1680.             return PreviousSiblingTail(node, sibling);
  1681.         }
  1682.        
  1683.         private XmlNode PreviousSiblingTail(XmlNode node, XmlNode sibling)
  1684.         {
  1685.             while (sibling == null) {
  1686.                 node = node.ParentNode;
  1687.                 if (node == null || node.NodeType != XmlNodeType.EntityReference) {
  1688.                     return null;
  1689.                 }
  1690.                 sibling = node.PreviousSibling;
  1691.             }
  1692.             while (sibling != null && sibling.NodeType == XmlNodeType.EntityReference) {
  1693.                 sibling = sibling.LastChild;
  1694.             }
  1695.             return sibling;
  1696.         }
  1697.        
  1698.         private XmlNode PreviousText(XmlNode node)
  1699.         {
  1700.             XmlNode text = node.PreviousText;
  1701.            
  1702.             if (!document.HasEntityReferences) {
  1703.                 return text;
  1704.             }
  1705.             return PreviousTextTail(node, text);
  1706.         }
  1707.        
  1708.         private XmlNode PreviousTextTail(XmlNode node, XmlNode text)
  1709.         {
  1710.             if (text != null) {
  1711.                 return text;
  1712.             }
  1713.             if (!node.IsText) {
  1714.                 return null;
  1715.             }
  1716.             XmlNode sibling = node.PreviousSibling;
  1717.             while (sibling == null) {
  1718.                 node = node.ParentNode;
  1719.                 if (node == null || node.NodeType != XmlNodeType.EntityReference) {
  1720.                     return null;
  1721.                 }
  1722.                 sibling = node.PreviousSibling;
  1723.             }
  1724.             while (sibling != null) {
  1725.                 switch (sibling.NodeType) {
  1726.                     case XmlNodeType.EntityReference:
  1727.                         sibling = sibling.LastChild;
  1728.                         break;
  1729.                     case XmlNodeType.Text:
  1730.                     case XmlNodeType.CDATA:
  1731.                     case XmlNodeType.Whitespace:
  1732.                     case XmlNodeType.SignificantWhitespace:
  1733.                         return sibling;
  1734.                     default:
  1735.                         return null;
  1736.                 }
  1737.             }
  1738.             return null;
  1739.         }
  1740.        
  1741.         static internal bool IsFollowingSibling(XmlNode left, XmlNode right)
  1742.         {
  1743.             for (;;) {
  1744.                 left = left.NextSibling;
  1745.                 if (left == null) {
  1746.                     break;
  1747.                 }
  1748.                 if (left == right) {
  1749.                     return true;
  1750.                 }
  1751.             }
  1752.             return false;
  1753.         }
  1754.        
  1755.         private static bool IsDescendant(XmlNode top, XmlNode bottom)
  1756.         {
  1757.             for (;;) {
  1758.                 XmlNode parent = bottom.ParentNode;
  1759.                 if (parent == null) {
  1760.                     XmlAttribute attribute = bottom as XmlAttribute;
  1761.                     if (attribute == null) {
  1762.                         break;
  1763.                     }
  1764.                     parent = attribute.OwnerElement;
  1765.                     if (parent == null) {
  1766.                         break;
  1767.                     }
  1768.                 }
  1769.                 bottom = parent;
  1770.                 if (top == bottom) {
  1771.                     return true;
  1772.                 }
  1773.             }
  1774.             return false;
  1775.         }
  1776.        
  1777.         private static bool IsValidChild(XmlNode parent, XmlNode child)
  1778.         {
  1779.             switch (parent.NodeType) {
  1780.                 case XmlNodeType.Element:
  1781.                     return true;
  1782.                 case XmlNodeType.DocumentFragment:
  1783.                     switch (child.NodeType) {
  1784.                         case XmlNodeType.Element:
  1785.                         case XmlNodeType.Text:
  1786.                         case XmlNodeType.CDATA:
  1787.                         case XmlNodeType.ProcessingInstruction:
  1788.                         case XmlNodeType.Comment:
  1789.                         case XmlNodeType.Whitespace:
  1790.                         case XmlNodeType.SignificantWhitespace:
  1791.                             return true;
  1792.                     }
  1793.                     break;
  1794.                 case XmlNodeType.Document:
  1795.                     switch (child.NodeType) {
  1796.                         case XmlNodeType.Element:
  1797.                         case XmlNodeType.ProcessingInstruction:
  1798.                         case XmlNodeType.Comment:
  1799.                             return true;
  1800.                     }
  1801.                     break;
  1802.                 default:
  1803.                     break;
  1804.             }
  1805.             return false;
  1806.         }
  1807.        
  1808.         private XmlNode TextStart(XmlNode node)
  1809.         {
  1810.             XmlNode start;
  1811.            
  1812.             do {
  1813.                 start = node;
  1814.                 node = PreviousSibling(node);
  1815.             }
  1816.             while (node != null && node.IsText);
  1817.             return start;
  1818.         }
  1819.        
  1820.         private XmlNode TextEnd(XmlNode node)
  1821.         {
  1822.             XmlNode end;
  1823.            
  1824.             do {
  1825.                 end = node;
  1826.                 node = NextSibling(node);
  1827.             }
  1828.             while (node != null && node.IsText);
  1829.             return end;
  1830.         }
  1831.     }
  1832.    
  1833.     // An iterator that matches no nodes
  1834.     internal sealed class DocumentXPathNodeIterator_Empty : XPathNodeIterator
  1835.     {
  1836.         private XPathNavigator nav;
  1837.        
  1838.         internal DocumentXPathNodeIterator_Empty(DocumentXPathNavigator nav)
  1839.         {
  1840.             this.nav = nav.Clone();
  1841.         }
  1842.         internal DocumentXPathNodeIterator_Empty(DocumentXPathNodeIterator_Empty other)
  1843.         {
  1844.             this.nav = other.nav.Clone();
  1845.         }
  1846.         public override XPathNodeIterator Clone()
  1847.         {
  1848.             return new DocumentXPathNodeIterator_Empty(this);
  1849.         }
  1850.         public override bool MoveNext()
  1851.         {
  1852.             return false;
  1853.         }
  1854.         public override XPathNavigator Current {
  1855.             get { return nav; }
  1856.         }
  1857.         public override int CurrentPosition {
  1858.             get { return 0; }
  1859.         }
  1860.         public override int Count {
  1861.             get { return 0; }
  1862.         }
  1863.     }
  1864.    
  1865.     // An iterator that can match any child elements that match the Match condition (overrided in the derived class)
  1866.     internal abstract class DocumentXPathNodeIterator_ElemDescendants : XPathNodeIterator
  1867.     {
  1868.         private DocumentXPathNavigator nav;
  1869.         private int level;
  1870.         private int position;
  1871.        
  1872.         internal DocumentXPathNodeIterator_ElemDescendants(DocumentXPathNavigator nav)
  1873.         {
  1874.             this.nav = (DocumentXPathNavigator)(nav.Clone());
  1875.             this.level = 0;
  1876.             this.position = 0;
  1877.         }
  1878.         internal DocumentXPathNodeIterator_ElemDescendants(DocumentXPathNodeIterator_ElemDescendants other)
  1879.         {
  1880.             this.nav = (DocumentXPathNavigator)(other.nav.Clone());
  1881.             this.level = other.level;
  1882.             this.position = other.position;
  1883.         }
  1884.        
  1885.         protected abstract bool Match(XmlNode node);
  1886.        
  1887.         public override XPathNavigator Current {
  1888.             get { return nav; }
  1889.         }
  1890.        
  1891.         public override int CurrentPosition {
  1892.             get { return position; }
  1893.         }
  1894.        
  1895.         protected void SetPosition(int pos)
  1896.         {
  1897.             position = pos;
  1898.         }
  1899.        
  1900.         public override bool MoveNext()
  1901.         {
  1902.             for (;;) {
  1903.                 if (nav.MoveToFirstChild()) {
  1904.                     level++;
  1905.                 }
  1906.                 else {
  1907.                     if (level == 0) {
  1908.                         return false;
  1909.                     }
  1910.                     while (!nav.MoveToNext()) {
  1911.                         level--;
  1912.                         if (level == 0) {
  1913.                             return false;
  1914.                         }
  1915.                         if (!nav.MoveToParent()) {
  1916.                             return false;
  1917.                         }
  1918.                     }
  1919.                 }
  1920.                 XmlNode node = (XmlNode)nav.UnderlyingObject;
  1921.                 if (node.NodeType == XmlNodeType.Element && Match(node)) {
  1922.                     position++;
  1923.                     return true;
  1924.                 }
  1925.             }
  1926.         }
  1927.     }
  1928.    
  1929.     // Iterate over all element children irrespective of the localName and namespace
  1930.     internal class DocumentXPathNodeIterator_AllElemChildren : DocumentXPathNodeIterator_ElemDescendants
  1931.     {
  1932.         internal DocumentXPathNodeIterator_AllElemChildren(DocumentXPathNavigator nav) : base(nav)
  1933.         {
  1934.             Debug.Assert(((XmlNode)nav.UnderlyingObject).NodeType != XmlNodeType.Attribute);
  1935.         }
  1936.         internal DocumentXPathNodeIterator_AllElemChildren(DocumentXPathNodeIterator_AllElemChildren other) : base(other)
  1937.         {
  1938.         }
  1939.        
  1940.         public override XPathNodeIterator Clone()
  1941.         {
  1942.             return new DocumentXPathNodeIterator_AllElemChildren(this);
  1943.         }
  1944.        
  1945.         protected override bool Match(XmlNode node)
  1946.         {
  1947.             Debug.Assert(node != null);
  1948.             return (node.NodeType == XmlNodeType.Element);
  1949.         }
  1950.     }
  1951.     // Iterate over all element children irrespective of the localName and namespace, include the self node when testing for localName/ns
  1952.     internal sealed class DocumentXPathNodeIterator_AllElemChildren_AndSelf : DocumentXPathNodeIterator_AllElemChildren
  1953.     {
  1954.         internal DocumentXPathNodeIterator_AllElemChildren_AndSelf(DocumentXPathNavigator nav) : base(nav)
  1955.         {
  1956.         }
  1957.         internal DocumentXPathNodeIterator_AllElemChildren_AndSelf(DocumentXPathNodeIterator_AllElemChildren_AndSelf other) : base(other)
  1958.         {
  1959.         }
  1960.        
  1961.         public override XPathNodeIterator Clone()
  1962.         {
  1963.             return new DocumentXPathNodeIterator_AllElemChildren_AndSelf(this);
  1964.         }
  1965.        
  1966.         public override bool MoveNext()
  1967.         {
  1968.             if (CurrentPosition == 0) {
  1969.                 DocumentXPathNavigator nav = (DocumentXPathNavigator)this.Current;
  1970.                 XmlNode node = (XmlNode)nav.UnderlyingObject;
  1971.                 if (node.NodeType == XmlNodeType.Element && Match(node)) {
  1972.                     SetPosition(1);
  1973.                     return true;
  1974.                 }
  1975.             }
  1976.             return base.MoveNext();
  1977.         }
  1978.     }
  1979.     // Iterate over all element children that have a given namespace but irrespective of the localName
  1980.     internal class DocumentXPathNodeIterator_ElemChildren_NoLocalName : DocumentXPathNodeIterator_ElemDescendants
  1981.     {
  1982.         private string nsAtom;
  1983.        
  1984.         internal DocumentXPathNodeIterator_ElemChildren_NoLocalName(DocumentXPathNavigator nav, string nsAtom) : base(nav)
  1985.         {
  1986.             Debug.Assert(((XmlNode)nav.UnderlyingObject).NodeType != XmlNodeType.Attribute);
  1987.             Debug.Assert(Ref.Equal(nav.NameTable.Get(nsAtom), nsAtom));
  1988.             this.nsAtom = nsAtom;
  1989.         }
  1990.         internal DocumentXPathNodeIterator_ElemChildren_NoLocalName(DocumentXPathNodeIterator_ElemChildren_NoLocalName other) : base(other)
  1991.         {
  1992.             this.nsAtom = other.nsAtom;
  1993.         }
  1994.         public override XPathNodeIterator Clone()
  1995.         {
  1996.             return new DocumentXPathNodeIterator_ElemChildren_NoLocalName(this);
  1997.         }
  1998.        
  1999.         protected override bool Match(XmlNode node)
  2000.         {
  2001.             Debug.Assert(node != null);
  2002.             Debug.Assert(node.NodeType == XmlNodeType.Element);
  2003.             return Ref.Equal(node.NamespaceURI, nsAtom);
  2004.         }
  2005.     }
  2006.     // Iterate over all element children that have a given namespace but irrespective of the localName, include self node when checking for ns
  2007.     internal sealed class DocumentXPathNodeIterator_ElemChildren_AndSelf_NoLocalName : DocumentXPathNodeIterator_ElemChildren_NoLocalName
  2008.     {
  2009.        
  2010.         internal DocumentXPathNodeIterator_ElemChildren_AndSelf_NoLocalName(DocumentXPathNavigator nav, string nsAtom) : base(nav, nsAtom)
  2011.         {
  2012.         }
  2013.         internal DocumentXPathNodeIterator_ElemChildren_AndSelf_NoLocalName(DocumentXPathNodeIterator_ElemChildren_AndSelf_NoLocalName other) : base(other)
  2014.         {
  2015.         }
  2016.        
  2017.         public override XPathNodeIterator Clone()
  2018.         {
  2019.             return new DocumentXPathNodeIterator_ElemChildren_AndSelf_NoLocalName(this);
  2020.         }
  2021.        
  2022.         public override bool MoveNext()
  2023.         {
  2024.             if (CurrentPosition == 0) {
  2025.                 DocumentXPathNavigator nav = (DocumentXPathNavigator)this.Current;
  2026.                 XmlNode node = (XmlNode)nav.UnderlyingObject;
  2027.                 if (node.NodeType == XmlNodeType.Element && Match(node)) {
  2028.                     SetPosition(1);
  2029.                     return true;
  2030.                 }
  2031.             }
  2032.             return base.MoveNext();
  2033.         }
  2034.     }
  2035.     // Iterate over all element children that have a given name and namespace
  2036.     internal class DocumentXPathNodeIterator_ElemChildren : DocumentXPathNodeIterator_ElemDescendants
  2037.     {
  2038.         protected string localNameAtom;
  2039.         protected string nsAtom;
  2040.        
  2041.         internal DocumentXPathNodeIterator_ElemChildren(DocumentXPathNavigator nav, string localNameAtom, string nsAtom) : base(nav)
  2042.         {
  2043.             Debug.Assert(((XmlNode)nav.UnderlyingObject).NodeType != XmlNodeType.Attribute);
  2044.             Debug.Assert(Ref.Equal(nav.NameTable.Get(localNameAtom), localNameAtom));
  2045.             Debug.Assert(Ref.Equal(nav.NameTable.Get(nsAtom), nsAtom));
  2046.             Debug.Assert(localNameAtom.Length > 0);
  2047.             // Use DocumentXPathNodeIterator_ElemChildren_NoLocalName class for special magic value of localNameAtom
  2048.             this.localNameAtom = localNameAtom;
  2049.             this.nsAtom = nsAtom;
  2050.         }
  2051.        
  2052.         internal DocumentXPathNodeIterator_ElemChildren(DocumentXPathNodeIterator_ElemChildren other) : base(other)
  2053.         {
  2054.             this.localNameAtom = other.localNameAtom;
  2055.             this.nsAtom = other.nsAtom;
  2056.         }
  2057.        
  2058.         public override XPathNodeIterator Clone()
  2059.         {
  2060.             return new DocumentXPathNodeIterator_ElemChildren(this);
  2061.         }
  2062.        
  2063.         protected override bool Match(XmlNode node)
  2064.         {
  2065.             Debug.Assert(node != null);
  2066.             Debug.Assert(node.NodeType == XmlNodeType.Element);
  2067.             return Ref.Equal(node.LocalName, localNameAtom) && Ref.Equal(node.NamespaceURI, nsAtom);
  2068.         }
  2069.     }
  2070.     // Iterate over all elem children and itself and check for the given localName (including the magic value "") and namespace
  2071.     internal sealed class DocumentXPathNodeIterator_ElemChildren_AndSelf : DocumentXPathNodeIterator_ElemChildren
  2072.     {
  2073.        
  2074.         internal DocumentXPathNodeIterator_ElemChildren_AndSelf(DocumentXPathNavigator nav, string localNameAtom, string nsAtom) : base(nav, localNameAtom, nsAtom)
  2075.         {
  2076.             Debug.Assert(localNameAtom.Length > 0);
  2077.             // Use DocumentXPathNodeIterator_ElemChildren_AndSelf_NoLocalName if localName == String.Empty
  2078.         }
  2079.         internal DocumentXPathNodeIterator_ElemChildren_AndSelf(DocumentXPathNodeIterator_ElemChildren_AndSelf other) : base(other)
  2080.         {
  2081.         }
  2082.        
  2083.         public override XPathNodeIterator Clone()
  2084.         {
  2085.             return new DocumentXPathNodeIterator_ElemChildren_AndSelf(this);
  2086.         }
  2087.        
  2088.         public override bool MoveNext()
  2089.         {
  2090.             if (CurrentPosition == 0) {
  2091.                 DocumentXPathNavigator nav = (DocumentXPathNavigator)this.Current;
  2092.                 XmlNode node = (XmlNode)nav.UnderlyingObject;
  2093.                 if (node.NodeType == XmlNodeType.Element && Match(node)) {
  2094.                     SetPosition(1);
  2095.                     return true;
  2096.                 }
  2097.             }
  2098.             return base.MoveNext();
  2099.         }
  2100.     }
  2101. }

Developer Fusion