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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlNavigatorReader.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.IO;
  16. using System.Xml.Schema;
  17. using System.Collections;
  18. using System.Diagnostics;
  19. using System.Collections.Generic;
  20. namespace System.Xml.XPath
  21. {
  22.    
  23.     /// <summary>
  24.     /// Reader that traverses the subtree rooted at the current position of the specified navigator.
  25.     /// </summary>
  26.     internal class XPathNavigatorReader : XmlReader, IXmlNamespaceResolver
  27.     {
  28.         enum State
  29.         {
  30.             Initial,
  31.             Content,
  32.             EndElement,
  33.             Attribute,
  34.             AttrVal,
  35.             InReadBinary,
  36.             EOF,
  37.             Closed,
  38.             Error
  39.         }
  40.        
  41.         private XPathNavigator nav;
  42.         private XPathNavigator navToRead;
  43.         private int depth;
  44.         private State state;
  45.         private XmlNodeType nodeType;
  46.         private int attrCount;
  47.         private bool readEntireDocument;
  48.        
  49.         protected IXmlLineInfo lineInfo;
  50.         protected IXmlSchemaInfo schemaInfo;
  51.        
  52.         private ReadContentAsBinaryHelper readBinaryHelper;
  53.         private State savedState;
  54.        
  55.         internal const string space = "space";
  56.        
  57.         static internal XmlNodeType[] convertFromXPathNodeType = {XmlNodeType.Document, XmlNodeType.Element, XmlNodeType.Attribute, XmlNodeType.Attribute, XmlNodeType.Text, XmlNodeType.SignificantWhitespace, XmlNodeType.Whitespace, XmlNodeType.ProcessingInstruction, XmlNodeType.Comment, XmlNodeType.None
  58.             // XPathNodeType.Root
  59.             // XPathNodeType.Element
  60.             // XPathNodeType.Attribute
  61.             // XPathNodeType.Namespace
  62.             // XPathNodeType.Text
  63.             // XPathNodeType.SignificantWhitespace
  64.             // XPathNodeType.Whitespace
  65.             // XPathNodeType.ProcessingInstruction
  66.             // XPathNodeType.Comment
  67.             // XPathNodeType.All
  68.         };
  69.        
  70.         /// <summary>
  71.         /// Translates an XPathNodeType value into the corresponding XmlNodeType value.
  72.         /// XPathNodeType.Whitespace and XPathNodeType.SignificantWhitespace are mapped into XmlNodeType.Text.
  73.         /// </summary>
  74.         static internal XmlNodeType ToXmlNodeType(XPathNodeType typ)
  75.         {
  76.             return XPathNavigatorReader.convertFromXPathNodeType[(int)typ];
  77.         }
  78.        
  79.         internal object UnderlyingObject {
  80.             get { return this.nav.UnderlyingObject; }
  81.         }
  82.        
  83.         public static XPathNavigatorReader Create(XPathNavigator navToRead)
  84.         {
  85.             XPathNavigator nav = navToRead.Clone();
  86.             IXmlLineInfo xli = nav as IXmlLineInfo;
  87.             IXmlSchemaInfo xsi = nav as IXmlSchemaInfo;
  88.             #if NAVREADER_SUPPORTSLINEINFO
  89.             if (null == xsi) {
  90.                 if (null == xli) {
  91.                     return new XPathNavigatorReader(nav, xli, xsi);
  92.                 }
  93.                 else {
  94.                     return new XPathNavigatorReaderWithLI(nav, xli, xsi);
  95.                 }
  96.             }
  97.             else {
  98.                 if (null == xli) {
  99.                     return new XPathNavigatorReaderWithSI(nav, xli, xsi);
  100.                 }
  101.                 else {
  102.                     return new XPathNavigatorReaderWithLIAndSI(nav, xli, xsi);
  103.                 }
  104.             }
  105.             #else
  106.             if (null == xsi) {
  107.                 return new XPathNavigatorReader(nav, xli, xsi);
  108.             }
  109.             else {
  110.                 return new XPathNavigatorReaderWithSI(nav, xli, xsi);
  111.             }
  112.             #endif
  113.         }
  114.        
  115.         protected XPathNavigatorReader(XPathNavigator navToRead, IXmlLineInfo xli, IXmlSchemaInfo xsi)
  116.         {
  117.             // Need clone that can be moved independently of original navigator
  118.             this.navToRead = navToRead;
  119.             this.lineInfo = xli;
  120.             this.schemaInfo = xsi;
  121.             this.nav = XmlEmptyNavigator.Singleton;
  122.             this.state = State.Initial;
  123.             this.depth = 0;
  124.             this.nodeType = XPathNavigatorReader.ToXmlNodeType(this.nav.NodeType);
  125.         }
  126.        
  127.         protected bool IsReading {
  128.             get { return this.state > State.Initial && this.state < State.EOF; }
  129.         }
  130.        
  131.         internal override XmlNamespaceManager NamespaceManager {
  132.             get { return XPathNavigator.GetNamespaces(this); }
  133.         }
  134.        
  135.        
  136.         //-----------------------------------------------
  137.         // IXmlNamespaceResolver -- pass through to Navigator
  138.         //-----------------------------------------------
  139.         public override XmlNameTable NameTable {
  140.             get { return this.navToRead.NameTable; }
  141.         }
  142.        
  143.         IDictionary<string, string> IXmlNamespaceResolver.GetNamespacesInScope(XmlNamespaceScope scope)
  144.         {
  145.             return this.nav.GetNamespacesInScope(scope);
  146.         }
  147.        
  148.         string IXmlNamespaceResolver.LookupNamespace(string prefix)
  149.         {
  150.             return this.nav.LookupNamespace(prefix);
  151.         }
  152.        
  153.         string IXmlNamespaceResolver.LookupPrefix(string namespaceName)
  154.         {
  155.             return this.nav.LookupPrefix(namespaceName);
  156.         }
  157.        
  158.         //-----------------------------------------------
  159.         // XmlReader -- pass through to Navigator
  160.         //-----------------------------------------------
  161.        
  162.         public override XmlReaderSettings Settings {
  163.             get {
  164.                 XmlReaderSettings rs = new XmlReaderSettings();
  165.                 rs.NameTable = this.NameTable;
  166.                 rs.ConformanceLevel = ConformanceLevel.Fragment;
  167.                 rs.CheckCharacters = false;
  168.                 rs.ReadOnly = true;
  169.                 return rs;
  170.             }
  171.         }
  172.        
  173.         public override IXmlSchemaInfo SchemaInfo {
  174.             get {
  175.                 // Special case attribute text (this.nav points to attribute even though current state is Text)
  176.                 if (this.nodeType == XmlNodeType.Text)
  177.                     return null;
  178.                 return this.nav.SchemaInfo;
  179.             }
  180.         }
  181.        
  182.         public override System.Type ValueType {
  183.             get { return this.nav.ValueType; }
  184.         }
  185.        
  186.         public override XmlNodeType NodeType {
  187.             get { return this.nodeType; }
  188.         }
  189.        
  190.         public override string NamespaceURI {
  191.             get {
  192.                 //NamespaceUri for namespace nodes is different in case of XPathNavigator and Reader
  193.                 if (this.nav.NodeType == XPathNodeType.Namespace)
  194.                     return this.NameTable.Add(XmlReservedNs.NsXmlNs);
  195.                 //Special case attribute text node
  196.                 if (this.NodeType == XmlNodeType.Text)
  197.                     return string.Empty;
  198.                 return this.nav.NamespaceURI;
  199.             }
  200.         }
  201.        
  202.         public override string LocalName {
  203.             get {
  204.                 //Default namespace in case of reader has a local name value of 'xmlns'
  205.                 if (this.nav.NodeType == XPathNodeType.Namespace && this.nav.LocalName.Length == 0)
  206.                     return this.NameTable.Add("xmlns");
  207.                 //Special case attribute text node
  208.                 if (this.NodeType == XmlNodeType.Text)
  209.                     return string.Empty;
  210.                 return this.nav.LocalName;
  211.             }
  212.         }
  213.        
  214.         public override string Prefix {
  215.             get {
  216.                 //Prefix for namespace nodes is different in case of XPathNavigator and Reader
  217.                 if (this.nav.NodeType == XPathNodeType.Namespace && this.nav.LocalName.Length != 0)
  218.                     return this.NameTable.Add("xmlns");
  219.                 //Special case attribute text node
  220.                 if (this.NodeType == XmlNodeType.Text)
  221.                     return string.Empty;
  222.                 return this.nav.Prefix;
  223.             }
  224.         }
  225.        
  226.         public override string BaseURI {
  227.             get {
  228.                 //reader returns BaseUri even before read method is called.
  229.                 if (this.state == State.Initial)
  230.                     return this.navToRead.BaseURI;
  231.                 return this.nav.BaseURI;
  232.             }
  233.         }
  234.        
  235.         public override bool IsEmptyElement {
  236.             get { return this.nav.IsEmptyElement; }
  237.         }
  238.        
  239.         public override XmlSpace XmlSpace {
  240.             get {
  241.                 string val = string.Empty;
  242.                 XPathNavigator tempNav = this.nav.Clone();
  243.                 do {
  244.                     if (tempNav.MoveToAttribute(XPathNavigatorReader.space, XmlReservedNs.NsXml)) {
  245.                         val = tempNav.Value;
  246.                         if (val == "default")
  247.                             return XmlSpace.Default;
  248.                         else if (val == "preserve")
  249.                             return XmlSpace.Preserve;
  250.                     }
  251.                 }
  252.                 while (tempNav.MoveToParent());
  253.                 return XmlSpace.None;
  254.             }
  255.         }
  256.        
  257.         public override string XmlLang {
  258.             get { return this.nav.XmlLang; }
  259.         }
  260.        
  261.         public override bool HasValue {
  262.             get {
  263.                 if ((this.nodeType != XmlNodeType.Element) && (this.nodeType != XmlNodeType.Document) && (this.nodeType != XmlNodeType.EndElement) && (this.nodeType != XmlNodeType.None))
  264.                     return true;
  265.                 return false;
  266.             }
  267.         }
  268.        
  269.         public override string Value {
  270.             get {
  271.                 if ((this.nodeType != XmlNodeType.Element) && (this.nodeType != XmlNodeType.Document) && (this.nodeType != XmlNodeType.EndElement) && (this.nodeType != XmlNodeType.None))
  272.                     return this.nav.Value;
  273.                 return string.Empty;
  274.             }
  275.         }
  276.        
  277.         private XPathNavigator GetElemNav()
  278.         {
  279.             XPathNavigator tempNav;
  280.             switch (this.state) {
  281.                 case State.Content:
  282.                     return this.nav.Clone();
  283.                 case State.Attribute:
  284.                 case State.AttrVal:
  285.                     tempNav = this.nav.Clone();
  286.                     if (tempNav.MoveToParent())
  287.                         return tempNav;
  288.                     break;
  289.                 case State.InReadBinary:
  290.                     state = savedState;
  291.                     XPathNavigator nav = GetElemNav();
  292.                     state = State.InReadBinary;
  293.                     return nav;
  294.             }
  295.             return null;
  296.         }
  297.        
  298.         private XPathNavigator GetElemNav(out int depth)
  299.         {
  300.             XPathNavigator nav = null;
  301.             switch (this.state) {
  302.                 case State.Content:
  303.                     if (this.nodeType == XmlNodeType.Element)
  304.                         nav = this.nav.Clone();
  305.                     depth = this.depth;
  306.                     break;
  307.                 case State.Attribute:
  308.                     nav = this.nav.Clone();
  309.                     nav.MoveToParent();
  310.                     depth = this.depth - 1;
  311.                     break;
  312.                 case State.AttrVal:
  313.                     nav = this.nav.Clone();
  314.                     nav.MoveToParent();
  315.                     depth = this.depth - 2;
  316.                     break;
  317.                 case State.InReadBinary:
  318.                     state = savedState;
  319.                     nav = GetElemNav(out depth);
  320.                     state = State.InReadBinary;
  321.                     break;
  322.                 default:
  323.                     depth = this.depth;
  324.                     break;
  325.             }
  326.             return nav;
  327.         }
  328.        
  329.         private void MoveToAttr(XPathNavigator nav, int depth)
  330.         {
  331.             this.nav.MoveTo(nav);
  332.             this.depth = depth;
  333.             this.nodeType = XmlNodeType.Attribute;
  334.             this.state = State.Attribute;
  335.         }
  336.        
  337.         public override int AttributeCount {
  338.             get {
  339.                 if (this.attrCount < 0) {
  340.                     // attribute count works for element, regardless of where you are in start tag
  341.                     XPathNavigator tempNav = GetElemNav();
  342.                     int count = 0;
  343.                     if (null != tempNav) {
  344.                         if (tempNav.MoveToFirstNamespace(XPathNamespaceScope.Local)) {
  345.                             do {
  346.                                 count++;
  347.                             }
  348.                             while (tempNav.MoveToNextNamespace((XPathNamespaceScope.Local)));
  349.                             tempNav.MoveToParent();
  350.                         }
  351.                         if (tempNav.MoveToFirstAttribute()) {
  352.                             do {
  353.                                 count++;
  354.                             }
  355.                             while (tempNav.MoveToNextAttribute());
  356.                         }
  357.                     }
  358.                     this.attrCount = count;
  359.                 }
  360.                 return this.attrCount;
  361.             }
  362.         }
  363.        
  364.         public override string GetAttribute(string name)
  365.         {
  366.             // reader allows calling GetAttribute, even when positioned inside attributes
  367.             XPathNavigator nav = this.nav;
  368.             switch (nav.NodeType) {
  369.                 case XPathNodeType.Element:
  370.                     break;
  371.                 case XPathNodeType.Attribute:
  372.                     nav = nav.Clone();
  373.                     if (!nav.MoveToParent())
  374.                         return null;
  375.                     break;
  376.                 default:
  377.                     return null;
  378.             }
  379.             string prefix;
  380.             string localname;
  381.             ValidateNames.SplitQName(name, out prefix, out localname);
  382.             if (0 == prefix.Length) {
  383.                 if (localname == "xmlns")
  384.                     return nav.GetNamespace(string.Empty);
  385.                 if ((object)nav == (object)this.nav)
  386.                     nav = nav.Clone();
  387.                 if (nav.MoveToAttribute(localname, string.Empty))
  388.                     return nav.Value;
  389.             }
  390.             else {
  391.                 if (prefix == "xmlns")
  392.                     return nav.GetNamespace(localname);
  393.                 if ((object)nav == (object)this.nav)
  394.                     nav = nav.Clone();
  395.                 if (nav.MoveToFirstAttribute()) {
  396.                     do {
  397.                         if (nav.LocalName == localname && nav.Prefix == prefix)
  398.                             return nav.Value;
  399.                     }
  400.                     while (nav.MoveToNextAttribute());
  401.                 }
  402.             }
  403.             return null;
  404.         }
  405.        
  406.         public override string GetAttribute(string localName, string namespaceURI)
  407.         {
  408.             if (null == localName)
  409.                 throw new ArgumentNullException("localName");
  410.             // reader allows calling GetAttribute, even when positioned inside attributes
  411.             XPathNavigator nav = this.nav;
  412.             switch (nav.NodeType) {
  413.                 case XPathNodeType.Element:
  414.                     break;
  415.                 case XPathNodeType.Attribute:
  416.                     nav = nav.Clone();
  417.                     if (!nav.MoveToParent())
  418.                         return null;
  419.                     break;
  420.                 default:
  421.                     return null;
  422.             }
  423.             // are they really looking for a namespace-decl?
  424.             if (namespaceURI == XmlReservedNs.NsXmlNs) {
  425.                 if (localName == "xmlns")
  426.                     localName = string.Empty;
  427.                 return nav.GetNamespace(localName);
  428.             }
  429.             if (null == namespaceURI)
  430.                 namespaceURI = string.Empty;
  431.             // We need to clone the navigator and move the clone to the attribute to see whether the attribute exists,
  432.             // because XPathNavigator.GetAttribute return string.Empty for both when the the attribute is not there or when
  433.             // it has an empty value. XmlReader.GetAttribute must return null if the attribute does not exist.
  434.             if ((object)nav == (object)this.nav)
  435.                 nav = nav.Clone();
  436.             if (nav.MoveToAttribute(localName, namespaceURI)) {
  437.                 return nav.Value;
  438.             }
  439.             else {
  440.                 return null;
  441.             }
  442.         }
  443.        
  444.         private static string GetNamespaceByIndex(XPathNavigator nav, int index, out int count)
  445.         {
  446.             string thisValue = nav.Value;
  447.             string value = null;
  448.             if (nav.MoveToNextNamespace(XPathNamespaceScope.Local)) {
  449.                 value = GetNamespaceByIndex(nav, index, out count);
  450.             }
  451.             else {
  452.                 count = 0;
  453.             }
  454.             if (count == index) {
  455.                 Debug.Assert(value == null);
  456.                 value = thisValue;
  457.             }
  458.             count++;
  459.             return value;
  460.         }
  461.        
  462.         public override string GetAttribute(int index)
  463.         {
  464.             if (index < 0)
  465.                 goto Error;
  466.             XPathNavigator nav = GetElemNav();
  467.             if (null == nav)
  468.                 goto Error;
  469.             if (nav.MoveToFirstNamespace(XPathNamespaceScope.Local)) {
  470.                 // namespaces are returned in reverse order,
  471.                 // but we want to return them in the correct order,
  472.                 // so first count the namespaces
  473.                 int nsCount;
  474.                 string value = GetNamespaceByIndex(nav, index, out nsCount);
  475.                 if (null != value) {
  476.                     return value;
  477.                 }
  478.                 index -= nsCount;
  479.                 nav.MoveToParent();
  480.             }
  481.             if (nav.MoveToFirstAttribute()) {
  482.                 do {
  483.                     if (index == 0)
  484.                         return nav.Value;
  485.                     index--;
  486.                 }
  487.                 while (nav.MoveToNextAttribute());
  488.             }
  489.             Error:
  490.             // can't find it... error
  491.             throw new ArgumentOutOfRangeException("index");
  492.         }
  493.        
  494.        
  495.         public override bool MoveToAttribute(string localName, string namespaceName)
  496.         {
  497.             if (null == localName)
  498.                 throw new ArgumentNullException("localName");
  499.             int depth = this.depth;
  500.             XPathNavigator nav = GetElemNav(out depth);
  501.             if (null != nav) {
  502.                 if (namespaceName == XmlReservedNs.NsXmlNs) {
  503.                     if (localName == "xmlns")
  504.                         localName = string.Empty;
  505.                     if (nav.MoveToFirstNamespace(XPathNamespaceScope.Local)) {
  506.                         do {
  507.                             if (nav.LocalName == localName)
  508.                                 goto FoundMatch;
  509.                         }
  510.                         while (nav.MoveToNextNamespace(XPathNamespaceScope.Local));
  511.                     }
  512.                 }
  513.                 else {
  514.                     if (null == namespaceName)
  515.                         namespaceName = string.Empty;
  516.                     if (nav.MoveToAttribute(localName, namespaceName))
  517.                         goto FoundMatch;
  518.                 }
  519.             }
  520.             return false;
  521.             FoundMatch:
  522.            
  523.             if (state == State.InReadBinary) {
  524.                 readBinaryHelper.Finish();
  525.                 state = savedState;
  526.             }
  527.             MoveToAttr(nav, depth + 1);
  528.             return true;
  529.         }
  530.        
  531.         public override bool MoveToFirstAttribute()
  532.         {
  533.             int depth;
  534.             XPathNavigator nav = GetElemNav(out depth);
  535.             if (null != nav) {
  536.                 if (nav.MoveToFirstNamespace(XPathNamespaceScope.Local)) {
  537.                     // attributes are in reverse order
  538.                     while (nav.MoveToNextNamespace(XPathNamespaceScope.Local))
  539.                         ;
  540.                     goto FoundMatch;
  541.                 }
  542.                 if (nav.MoveToFirstAttribute()) {
  543.                     goto FoundMatch;
  544.                 }
  545.             }
  546.             return false;
  547.             FoundMatch:
  548.             if (state == State.InReadBinary) {
  549.                 readBinaryHelper.Finish();
  550.                 state = savedState;
  551.             }
  552.             MoveToAttr(nav, depth + 1);
  553.             return true;
  554.         }
  555.        
  556.         public override bool MoveToNextAttribute()
  557.         {
  558.             switch (this.state) {
  559.                 case State.Content:
  560.                     return MoveToFirstAttribute();
  561.                 case State.Attribute:
  562.                    
  563.                    
  564.                     {
  565.                         if (XPathNodeType.Attribute == this.nav.NodeType)
  566.                             return this.nav.MoveToNextAttribute();
  567.                        
  568.                         // otherwise it is on a namespace... namespace are in reverse order
  569.                         Debug.Assert(XPathNodeType.Namespace == this.nav.NodeType);
  570.                         XPathNavigator nav = this.nav.Clone();
  571.                         if (!nav.MoveToParent())
  572.                             return false;
  573.                         // shouldn't happen
  574.                         if (!nav.MoveToFirstNamespace(XPathNamespaceScope.Local))
  575.                             return false;
  576.                         // shouldn't happen
  577.                         if (nav.IsSamePosition(this.nav)) {
  578.                             // this was the last one... start walking attributes
  579.                             nav.MoveToParent();
  580.                             if (!nav.MoveToFirstAttribute())
  581.                                 return false;
  582.                             // otherwise we are there
  583.                             this.nav.MoveTo(nav);
  584.                             return true;
  585.                         }
  586.                         else {
  587.                             XPathNavigator prev = nav.Clone();
  588.                             for (;;) {
  589.                                 if (!nav.MoveToNextNamespace(XPathNamespaceScope.Local)) {
  590.                                     Debug.Fail("Couldn't find Namespace Node! Should not happen!");
  591.                                     return false;
  592.                                 }
  593.                                 if (nav.IsSamePosition(this.nav)) {
  594.                                     this.nav.MoveTo(prev);
  595.                                     return true;
  596.                                 }
  597.                                 prev.MoveTo(nav);
  598.                             }
  599.                             // found previous namespace position
  600.                         }
  601.                     }
  602.                     break;
  603.                 case State.AttrVal:
  604.                     depth--;
  605.                     this.state = State.Attribute;
  606.                     if (!MoveToNextAttribute()) {
  607.                         depth++;
  608.                         this.state = State.AttrVal;
  609.                         return false;
  610.                     }
  611.                     this.nodeType = XmlNodeType.Attribute;
  612.                     return true;
  613.                 case State.InReadBinary:
  614.                    
  615.                     state = savedState;
  616.                     if (!MoveToNextAttribute()) {
  617.                         state = State.InReadBinary;
  618.                         return false;
  619.                     }
  620.                     readBinaryHelper.Finish();
  621.                     return true;
  622.                 default:
  623.                    
  624.                     return false;
  625.             }
  626.         }
  627.        
  628.         public override bool MoveToAttribute(string name)
  629.         {
  630.             int depth;
  631.             XPathNavigator nav = GetElemNav(out depth);
  632.             if (null == nav)
  633.                 return false;
  634.            
  635.             string prefix;
  636.             string localname;
  637.             ValidateNames.SplitQName(name, out prefix, out localname);
  638.            
  639.             // watch for a namespace name
  640.             bool IsXmlnsNoPrefix = false;
  641.             if ((IsXmlnsNoPrefix = (0 == prefix.Length && localname == "xmlns")) || (prefix == "xmlns")) {
  642.                 if (IsXmlnsNoPrefix)
  643.                     localname = string.Empty;
  644.                 if (nav.MoveToFirstNamespace(XPathNamespaceScope.Local)) {
  645.                     do {
  646.                         if (nav.LocalName == localname)
  647.                             goto FoundMatch;
  648.                     }
  649.                     while (nav.MoveToNextNamespace(XPathNamespaceScope.Local));
  650.                 }
  651.             }
  652.             else if (0 == prefix.Length) {
  653.                 // the empty prefix always means empty namespaceUri for attributes
  654.                 if (nav.MoveToAttribute(localname, string.Empty))
  655.                     goto FoundMatch;
  656.             }
  657.             else {
  658.                 if (nav.MoveToFirstAttribute()) {
  659.                     do {
  660.                         if (nav.LocalName == localname && nav.Prefix == prefix)
  661.                             goto FoundMatch;
  662.                     }
  663.                     while (nav.MoveToNextAttribute());
  664.                 }
  665.             }
  666.             return false;
  667.             FoundMatch:
  668.            
  669.             if (state == State.InReadBinary) {
  670.                 readBinaryHelper.Finish();
  671.                 state = savedState;
  672.             }
  673.             MoveToAttr(nav, depth + 1);
  674.             return true;
  675.         }
  676.        
  677.         public override bool MoveToElement()
  678.         {
  679.             switch (this.state) {
  680.                 case State.Attribute:
  681.                 case State.AttrVal:
  682.                     if (!nav.MoveToParent())
  683.                         return false;
  684.                     this.depth--;
  685.                     if (this.state == State.AttrVal)
  686.                         this.depth--;
  687.                     this.state = State.Content;
  688.                     this.nodeType = XmlNodeType.Element;
  689.                     return true;
  690.                 case State.InReadBinary:
  691.                     state = savedState;
  692.                     if (!MoveToElement()) {
  693.                         state = State.InReadBinary;
  694.                         return false;
  695.                     }
  696.                     readBinaryHelper.Finish();
  697.                     break;
  698.             }
  699.             return false;
  700.         }
  701.        
  702.         public override bool EOF {
  703.             get { return this.state == State.EOF; }
  704.         }
  705.        
  706.         public override ReadState ReadState {
  707.             get {
  708.                 switch (this.state) {
  709.                     case State.Initial:
  710.                         return ReadState.Initial;
  711.                     case State.Content:
  712.                     case State.EndElement:
  713.                     case State.Attribute:
  714.                     case State.AttrVal:
  715.                     case State.InReadBinary:
  716.                         return ReadState.Interactive;
  717.                     case State.EOF:
  718.                         return ReadState.EndOfFile;
  719.                     case State.Closed:
  720.                         return ReadState.Closed;
  721.                     default:
  722.                         return ReadState.Error;
  723.                 }
  724.             }
  725.         }
  726.        
  727.         public override void ResolveEntity()
  728.         {
  729.             throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidOperation));
  730.         }
  731.        
  732.         public override bool ReadAttributeValue()
  733.         {
  734.             if (state == State.InReadBinary) {
  735.                 readBinaryHelper.Finish();
  736.                 state = savedState;
  737.             }
  738.             if (this.state == State.Attribute) {
  739.                 this.state = State.AttrVal;
  740.                 this.nodeType = XmlNodeType.Text;
  741.                 this.depth++;
  742.                 return true;
  743.             }
  744.             return false;
  745.         }
  746.        
  747.         public override bool CanReadBinaryContent {
  748.             get { return true; }
  749.         }
  750.        
  751.         public override int ReadContentAsBase64(byte[] buffer, int index, int count)
  752.         {
  753.             if (ReadState != ReadState.Interactive) {
  754.                 return 0;
  755.             }
  756.            
  757.             // init ReadContentAsBinaryHelper when called first time
  758.             if (state != State.InReadBinary) {
  759.                 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset(readBinaryHelper, this);
  760.                 savedState = state;
  761.             }
  762.            
  763.             // turn off InReadBinary state in order to have a normal Read() behavior when called from readBinaryHelper
  764.             state = savedState;
  765.            
  766.             // call to the helper
  767.             int readCount = readBinaryHelper.ReadContentAsBase64(buffer, index, count);
  768.            
  769.             // turn on InReadBinary state again and return
  770.             savedState = state;
  771.             state = State.InReadBinary;
  772.             return readCount;
  773.         }
  774.        
  775.         public override int ReadContentAsBinHex(byte[] buffer, int index, int count)
  776.         {
  777.             if (ReadState != ReadState.Interactive) {
  778.                 return 0;
  779.             }
  780.            
  781.             // init ReadContentAsBinaryHelper when called first time
  782.             if (state != State.InReadBinary) {
  783.                 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset(readBinaryHelper, this);
  784.                 savedState = state;
  785.             }
  786.            
  787.             // turn off InReadBinary state in order to have a normal Read() behavior when called from readBinaryHelper
  788.             state = savedState;
  789.            
  790.             // call to the helper
  791.             int readCount = readBinaryHelper.ReadContentAsBinHex(buffer, index, count);
  792.            
  793.             // turn on InReadBinary state again and return
  794.             savedState = state;
  795.             state = State.InReadBinary;
  796.             return readCount;
  797.         }
  798.        
  799.         public override int ReadElementContentAsBase64(byte[] buffer, int index, int count)
  800.         {
  801.             if (ReadState != ReadState.Interactive) {
  802.                 return 0;
  803.             }
  804.            
  805.             // init ReadContentAsBinaryHelper when called first time
  806.             if (state != State.InReadBinary) {
  807.                 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset(readBinaryHelper, this);
  808.                 savedState = state;
  809.             }
  810.            
  811.             // turn off InReadBinary state in order to have a normal Read() behavior when called from readBinaryHelper
  812.             state = savedState;
  813.            
  814.             // call to the helper
  815.             int readCount = readBinaryHelper.ReadElementContentAsBase64(buffer, index, count);
  816.            
  817.             // turn on InReadBinary state again and return
  818.             savedState = state;
  819.             state = State.InReadBinary;
  820.             return readCount;
  821.         }
  822.        
  823.         public override int ReadElementContentAsBinHex(byte[] buffer, int index, int count)
  824.         {
  825.             if (ReadState != ReadState.Interactive) {
  826.                 return 0;
  827.             }
  828.            
  829.             // init ReadContentAsBinaryHelper when called first time
  830.             if (state != State.InReadBinary) {
  831.                 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset(readBinaryHelper, this);
  832.                 savedState = state;
  833.             }
  834.            
  835.             // turn off InReadBinary state in order to have a normal Read() behavior when called from readBinaryHelper
  836.             state = savedState;
  837.            
  838.             // call to the helper
  839.             int readCount = readBinaryHelper.ReadElementContentAsBinHex(buffer, index, count);
  840.            
  841.             // turn on InReadBinary state again and return
  842.             savedState = state;
  843.             state = State.InReadBinary;
  844.             return readCount;
  845.         }
  846.        
  847.         public override string LookupNamespace(string prefix)
  848.         {
  849.             return this.nav.LookupNamespace(prefix);
  850.         }
  851.        
  852.         /// <summary>
  853.         /// Current depth in subtree.
  854.         /// </summary>
  855.         public override int Depth {
  856.             get { return this.depth; }
  857.         }
  858.        
  859.         /// <summary>
  860.         /// Move to the next reader state. Return false if that is ReaderState.Closed.
  861.         /// </summary>
  862.         public override bool Read()
  863.         {
  864.             this.attrCount = -1;
  865.             switch (this.state) {
  866.                 case State.Error:
  867.                 case State.Closed:
  868.                 case State.EOF:
  869.                     return false;
  870.                 case State.Initial:
  871.                    
  872.                     // Starting state depends on the navigator's item type
  873.                     this.nav = this.navToRead;
  874.                     this.state = State.Content;
  875.                     if (XPathNodeType.Root == this.nav.NodeType) {
  876.                         if (!nav.MoveToFirstChild()) {
  877.                             SetEOF();
  878.                             return false;
  879.                         }
  880.                         this.readEntireDocument = true;
  881.                     }
  882.                     else if (XPathNodeType.Attribute == this.nav.NodeType) {
  883.                         this.state = State.Attribute;
  884.                     }
  885.                     this.nodeType = ToXmlNodeType(this.nav.NodeType);
  886.                     break;
  887.                 case State.Content:
  888.                    
  889.                     if (this.nav.MoveToFirstChild()) {
  890.                         this.nodeType = ToXmlNodeType(this.nav.NodeType);
  891.                         this.depth++;
  892.                         this.state = State.Content;
  893.                     }
  894.                     else if (this.nodeType == XmlNodeType.Element && !this.nav.IsEmptyElement) {
  895.                         this.nodeType = XmlNodeType.EndElement;
  896.                         this.state = State.EndElement;
  897.                     }
  898.                     else
  899.                         goto case State.EndElement;
  900.                     break;
  901.                 case State.EndElement:
  902.                    
  903.                     if (0 == depth && !this.readEntireDocument) {
  904.                         SetEOF();
  905.                         return false;
  906.                     }
  907.                     else if (this.nav.MoveToNext()) {
  908.                         this.nodeType = ToXmlNodeType(this.nav.NodeType);
  909.                         this.state = State.Content;
  910.                     }
  911.                     else if (depth > 0 && this.nav.MoveToParent()) {
  912.                         Debug.Assert(this.nav.NodeType == XPathNodeType.Element, this.nav.NodeType.ToString() + " == XPathNodeType.Element");
  913.                         this.nodeType = XmlNodeType.EndElement;
  914.                         this.state = State.EndElement;
  915.                         depth--;
  916.                     }
  917.                     else {
  918.                         SetEOF();
  919.                         return false;
  920.                     }
  921.                     break;
  922.                 case State.Attribute:
  923.                 case State.AttrVal:
  924.                    
  925.                     if (!this.nav.MoveToParent()) {
  926.                         SetEOF();
  927.                         return false;
  928.                     }
  929.                     this.nodeType = ToXmlNodeType(this.nav.NodeType);
  930.                     this.depth--;
  931.                     if (state == State.AttrVal)
  932.                         this.depth--;
  933.                     goto case State.Content;
  934.                     break;
  935.                 case State.InReadBinary:
  936.                     state = savedState;
  937.                     readBinaryHelper.Finish();
  938.                     return Read();
  939.             }
  940.             return true;
  941.         }
  942.        
  943.        
  944.         /// <summary>
  945.         /// End reading by transitioning into the Closed state.
  946.         /// </summary>
  947.         public override void Close()
  948.         {
  949.             this.nav = XmlEmptyNavigator.Singleton;
  950.             this.nodeType = XmlNodeType.None;
  951.             this.state = State.Closed;
  952.             this.depth = 0;
  953.         }
  954.        
  955.         /// <summary>
  956.         /// set reader to EOF state
  957.         /// </summary>
  958.         private void SetEOF()
  959.         {
  960.             this.nav = XmlEmptyNavigator.Singleton;
  961.             this.nodeType = XmlNodeType.None;
  962.             this.state = State.EOF;
  963.             this.depth = 0;
  964.         }
  965.     }
  966.    
  967.     #if NAVREADER_SUPPORTSLINEINFO
  968.     internal class XPathNavigatorReaderWithLI : XPathNavigatorReader, System.Xml.IXmlLineInfo
  969.     {
  970.         internal XPathNavigatorReaderWithLI(XPathNavigator navToRead, IXmlLineInfo xli, IXmlSchemaInfo xsi) : base(navToRead, xli, xsi)
  971.         {
  972.         }
  973.        
  974.         //-----------------------------------------------
  975.         // IXmlLineInfo
  976.         //-----------------------------------------------
  977.        
  978.         public virtual bool HasLineInfo()
  979.         {
  980.             return IsReading ? this.lineInfo.HasLineInfo() : false;
  981.         }
  982.         public virtual int LineNumber {
  983.             get { return IsReading ? this.lineInfo.LineNumber : 0; }
  984.         }
  985.         public virtual int LinePosition {
  986.             get { return IsReading ? this.lineInfo.LinePosition : 0; }
  987.         }
  988.     }
  989.    
  990.     internal class XPathNavigatorReaderWithLIAndSI : XPathNavigatorReaderWithLI, System.Xml.IXmlLineInfo, System.Xml.Schema.IXmlSchemaInfo
  991.     {
  992.         internal XPathNavigatorReaderWithLIAndSI(XPathNavigator navToRead, IXmlLineInfo xli, IXmlSchemaInfo xsi) : base(navToRead, xli, xsi)
  993.         {
  994.         }
  995.        
  996.         //-----------------------------------------------
  997.         // IXmlSchemaInfo
  998.         //-----------------------------------------------
  999.        
  1000.         public virtual XmlSchemaValidity Validity {
  1001.             get { return IsReading ? this.schemaInfo.Validity : XmlSchemaValidity.NotKnown; }
  1002.         }
  1003.         public override bool IsDefault {
  1004.             get { return IsReading ? this.schemaInfo.IsDefault : false; }
  1005.         }
  1006.         public virtual bool IsNil {
  1007.             get { return IsReading ? this.schemaInfo.IsNil : false; }
  1008.         }
  1009.         public virtual XmlSchemaSimpleType MemberType {
  1010.             get { return IsReading ? this.schemaInfo.MemberType : null; }
  1011.         }
  1012.         public virtual XmlSchemaType SchemaType {
  1013.             get { return IsReading ? this.schemaInfo.SchemaType : null; }
  1014.         }
  1015.         public virtual XmlSchemaElement SchemaElement {
  1016.             get { return IsReading ? this.schemaInfo.SchemaElement : null; }
  1017.         }
  1018.         public virtual XmlSchemaAttribute SchemaAttribute {
  1019.             get { return IsReading ? this.schemaInfo.SchemaAttribute : null; }
  1020.         }
  1021.     }
  1022.     #endif
  1023.    
  1024.     internal class XPathNavigatorReaderWithSI : XPathNavigatorReader, System.Xml.Schema.IXmlSchemaInfo
  1025.     {
  1026.         internal XPathNavigatorReaderWithSI(XPathNavigator navToRead, IXmlLineInfo xli, IXmlSchemaInfo xsi) : base(navToRead, xli, xsi)
  1027.         {
  1028.         }
  1029.        
  1030.         //-----------------------------------------------
  1031.         // IXmlSchemaInfo
  1032.         //-----------------------------------------------
  1033.        
  1034.         public virtual XmlSchemaValidity Validity {
  1035.             get { return IsReading ? this.schemaInfo.Validity : XmlSchemaValidity.NotKnown; }
  1036.         }
  1037.         public override bool IsDefault {
  1038.             get { return IsReading ? this.schemaInfo.IsDefault : false; }
  1039.         }
  1040.         public virtual bool IsNil {
  1041.             get { return IsReading ? this.schemaInfo.IsNil : false; }
  1042.         }
  1043.         public virtual XmlSchemaSimpleType MemberType {
  1044.             get { return IsReading ? this.schemaInfo.MemberType : null; }
  1045.         }
  1046.         public virtual XmlSchemaType SchemaType {
  1047.             get { return IsReading ? this.schemaInfo.SchemaType : null; }
  1048.         }
  1049.         public virtual XmlSchemaElement SchemaElement {
  1050.             get { return IsReading ? this.schemaInfo.SchemaElement : null; }
  1051.         }
  1052.         public virtual XmlSchemaAttribute SchemaAttribute {
  1053.             get { return IsReading ? this.schemaInfo.SchemaAttribute : null; }
  1054.         }
  1055.     }
  1056.    
  1057.     /// <summary>
  1058.     /// The XmlEmptyNavigator exposes a document node with no children.
  1059.     /// Only one XmlEmptyNavigator exists per AppDomain (Singleton). That's why the constructor is private.
  1060.     /// Use the Singleton property to get the EmptyNavigator.
  1061.     /// </summary>
  1062.     internal class XmlEmptyNavigator : XPathNavigator
  1063.     {
  1064.         private static XmlEmptyNavigator singleton;
  1065.        
  1066.         private XmlEmptyNavigator()
  1067.         {
  1068.         }
  1069.        
  1070.         public static XmlEmptyNavigator Singleton {
  1071.             get {
  1072.                 if (XmlEmptyNavigator.singleton == null)
  1073.                     XmlEmptyNavigator.singleton = new XmlEmptyNavigator();
  1074.                 return XmlEmptyNavigator.singleton;
  1075.             }
  1076.         }
  1077.        
  1078.         //-----------------------------------------------
  1079.         // XmlReader
  1080.         //-----------------------------------------------
  1081.        
  1082.         public override XPathNodeType NodeType {
  1083.             get { return XPathNodeType.All; }
  1084.         }
  1085.        
  1086.         public override string NamespaceURI {
  1087.             get { return string.Empty; }
  1088.         }
  1089.        
  1090.         public override string LocalName {
  1091.             get { return string.Empty; }
  1092.         }
  1093.        
  1094.         public override string Name {
  1095.             get { return string.Empty; }
  1096.         }
  1097.        
  1098.         public override string Prefix {
  1099.             get { return string.Empty; }
  1100.         }
  1101.        
  1102.         public override string BaseURI {
  1103.             get { return string.Empty; }
  1104.         }
  1105.        
  1106.         public override string Value {
  1107.             get { return string.Empty; }
  1108.         }
  1109.        
  1110.         public override bool IsEmptyElement {
  1111.             get { return false; }
  1112.         }
  1113.        
  1114.         public override string XmlLang {
  1115.             get { return string.Empty; }
  1116.         }
  1117.        
  1118.         public override bool HasAttributes {
  1119.             get { return false; }
  1120.         }
  1121.        
  1122.         public override bool HasChildren {
  1123.             get { return false; }
  1124.         }
  1125.        
  1126.        
  1127.         //-----------------------------------------------
  1128.         // IXmlNamespaceResolver
  1129.         //-----------------------------------------------
  1130.        
  1131.         public override XmlNameTable NameTable {
  1132.             get { return new NameTable(); }
  1133.         }
  1134.        
  1135.         public override bool MoveToFirstChild()
  1136.         {
  1137.             return false;
  1138.         }
  1139.        
  1140.         public override void MoveToRoot()
  1141.         {
  1142.             //always on root
  1143.             return;
  1144.         }
  1145.        
  1146.         public override bool MoveToNext()
  1147.         {
  1148.             return false;
  1149.         }
  1150.        
  1151.         public override bool MoveToPrevious()
  1152.         {
  1153.             return false;
  1154.         }
  1155.        
  1156.         public override bool MoveToFirst()
  1157.         {
  1158.             return false;
  1159.         }
  1160.        
  1161.         public override bool MoveToFirstAttribute()
  1162.         {
  1163.             return false;
  1164.         }
  1165.        
  1166.         public override bool MoveToNextAttribute()
  1167.         {
  1168.             return false;
  1169.         }
  1170.        
  1171.         public override bool MoveToId(string id)
  1172.         {
  1173.             return false;
  1174.         }
  1175.        
  1176.         public override string GetAttribute(string localName, string namespaceName)
  1177.         {
  1178.             return null;
  1179.         }
  1180.        
  1181.         public override bool MoveToAttribute(string localName, string namespaceName)
  1182.         {
  1183.             return false;
  1184.         }
  1185.        
  1186.         public override string GetNamespace(string name)
  1187.         {
  1188.             return null;
  1189.         }
  1190.        
  1191.         public override bool MoveToNamespace(string prefix)
  1192.         {
  1193.             return false;
  1194.         }
  1195.        
  1196.        
  1197.         public override bool MoveToFirstNamespace(XPathNamespaceScope scope)
  1198.         {
  1199.             return false;
  1200.         }
  1201.        
  1202.         public override bool MoveToNextNamespace(XPathNamespaceScope scope)
  1203.         {
  1204.             return false;
  1205.         }
  1206.        
  1207.         public override bool MoveToParent()
  1208.         {
  1209.             return false;
  1210.         }
  1211.        
  1212.         public override bool MoveTo(XPathNavigator other)
  1213.         {
  1214.             // Only one instance of XmlEmptyNavigator exists on the system
  1215.             return (object)this == (object)other;
  1216.         }
  1217.        
  1218.         public override XmlNodeOrder ComparePosition(XPathNavigator other)
  1219.         {
  1220.             // Only one instance of XmlEmptyNavigator exists on the system
  1221.             return ((object)this == (object)other) ? XmlNodeOrder.Same : XmlNodeOrder.Unknown;
  1222.         }
  1223.        
  1224.         public override bool IsSamePosition(XPathNavigator other)
  1225.         {
  1226.             // Only one instance of XmlEmptyNavigator exists on the system
  1227.             return (object)this == (object)other;
  1228.         }
  1229.        
  1230.        
  1231.         //-----------------------------------------------
  1232.         // XPathNavigator2
  1233.         //-----------------------------------------------
  1234.         public override XPathNavigator Clone()
  1235.         {
  1236.             // Singleton, so clone just returns this
  1237.             return this;
  1238.         }
  1239.     }
  1240. }

Developer Fusion