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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlNodeReader.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Xml
  16. {
  17.     using System;
  18.     using System.Text;
  19.     using System.IO;
  20.     using System.Diagnostics;
  21.     using System.Collections;
  22.     using System.Collections.Generic;
  23.     using System.Xml.Schema;
  24.     using System.Globalization;
  25.    
  26.     internal class XmlNodeReaderNavigator
  27.     {
  28.         XmlNode curNode;
  29.         XmlNode elemNode;
  30.         XmlNode logNode;
  31.         int attrIndex;
  32.         int logAttrIndex;
  33.        
  34.         //presave these 2 variables since they shouldn't change.
  35.         XmlNameTable nameTable;
  36.         XmlDocument doc;
  37.        
  38.         int nAttrInd;
  39.         //used to identify virtual attributes of DocumentType node and XmlDeclaration node
  40.         const string strPublicID = "PUBLIC";
  41.         const string strSystemID = "SYSTEM";
  42.         const string strVersion = "version";
  43.         const string strStandalone = "standalone";
  44.         const string strEncoding = "encoding";
  45.        
  46.        
  47.         //caching variables for perf reasons
  48.         int nDeclarationAttrCount;
  49.         int nDocTypeAttrCount;
  50.        
  51.         //variables for roll back the moves
  52.         int nLogLevel;
  53.         int nLogAttrInd;
  54.         bool bLogOnAttrVal;
  55.         bool bCreatedOnAttribute;
  56.        
  57.         internal struct VirtualAttribute
  58.         {
  59.             internal string name;
  60.             internal string value;
  61.            
  62.             internal VirtualAttribute(string name, string value)
  63.             {
  64.                 this.name = name;
  65.                 this.value = value;
  66.             }
  67.         }
  68.        
  69.         internal VirtualAttribute[] decNodeAttributes = {new VirtualAttribute(null, null), new VirtualAttribute(null, null), new VirtualAttribute(null, null)};
  70.        
  71.         internal VirtualAttribute[] docTypeNodeAttributes = {new VirtualAttribute(null, null), new VirtualAttribute(null, null)};
  72.        
  73.         bool bOnAttrVal;
  74.        
  75.         public XmlNodeReaderNavigator(XmlNode node)
  76.         {
  77.             curNode = node;
  78.             logNode = node;
  79.             XmlNodeType nt = curNode.NodeType;
  80.             if (nt == XmlNodeType.Attribute) {
  81.                 elemNode = null;
  82.                 attrIndex = -1;
  83.                 bCreatedOnAttribute = true;
  84.             }
  85.             else {
  86.                 elemNode = node;
  87.                 attrIndex = -1;
  88.                 bCreatedOnAttribute = false;
  89.             }
  90.             //presave this for pref reason since it shouldn't change.
  91.             if (nt == XmlNodeType.Document)
  92.                 this.doc = (XmlDocument)curNode;
  93.             else
  94.                 this.doc = node.OwnerDocument;
  95.             this.nameTable = doc.NameTable;
  96.             this.nAttrInd = -1;
  97.             //initialize the caching variables
  98.             this.nDeclarationAttrCount = -1;
  99.             this.nDocTypeAttrCount = -1;
  100.             this.bOnAttrVal = false;
  101.             this.bLogOnAttrVal = false;
  102.         }
  103.        
  104.         public XmlNodeType NodeType {
  105.             get {
  106.                 XmlNodeType nt = curNode.NodeType;
  107.                 if (nAttrInd != -1) {
  108.                     Debug.Assert(nt == XmlNodeType.XmlDeclaration || nt == XmlNodeType.DocumentType);
  109.                     if (this.bOnAttrVal)
  110.                         return XmlNodeType.Text;
  111.                     else
  112.                         return XmlNodeType.Attribute;
  113.                 }
  114.                 return nt;
  115.             }
  116.         }
  117.        
  118.         public string NamespaceURI {
  119.             get { return curNode.NamespaceURI; }
  120.         }
  121.        
  122.         public string Name {
  123.             get {
  124.                 if (nAttrInd != -1) {
  125.                     Debug.Assert(curNode.NodeType == XmlNodeType.XmlDeclaration || curNode.NodeType == XmlNodeType.DocumentType);
  126.                     if (this.bOnAttrVal)
  127.                         return String.Empty;
  128.                     //Text node's name is String.Empty
  129.                     else {
  130.                         Debug.Assert(nAttrInd >= 0 && nAttrInd < AttributeCount);
  131.                         if (curNode.NodeType == XmlNodeType.XmlDeclaration)
  132.                             return decNodeAttributes[nAttrInd].name;
  133.                         else
  134.                             return docTypeNodeAttributes[nAttrInd].name;
  135.                     }
  136.                 }
  137.                 if (IsLocalNameEmpty(curNode.NodeType))
  138.                     return String.Empty;
  139.                 return curNode.Name;
  140.             }
  141.         }
  142.        
  143.         public string LocalName {
  144.             get {
  145.                 if (nAttrInd != -1)
  146.                     //for the nodes in this case, their LocalName should be the same as their name
  147.                     return Name;
  148.                 if (IsLocalNameEmpty(curNode.NodeType))
  149.                     return String.Empty;
  150.                 return curNode.LocalName;
  151.             }
  152.         }
  153.        
  154.         internal bool IsOnAttrVal {
  155.             get { return this.bOnAttrVal; }
  156.         }
  157.        
  158.         internal XmlNode OwnerElementNode {
  159.             get {
  160.                 if (this.bCreatedOnAttribute)
  161.                     return null;
  162.                 return this.elemNode;
  163.             }
  164.         }
  165.        
  166.         internal bool CreatedOnAttribute {
  167.             get { return this.bCreatedOnAttribute; }
  168.         }
  169.        
  170.         private bool IsLocalNameEmpty(XmlNodeType nt)
  171.         {
  172.             switch (nt) {
  173.                 case XmlNodeType.None:
  174.                 case XmlNodeType.Text:
  175.                 case XmlNodeType.CDATA:
  176.                 case XmlNodeType.Comment:
  177.                 case XmlNodeType.Document:
  178.                 case XmlNodeType.DocumentFragment:
  179.                 case XmlNodeType.Whitespace:
  180.                 case XmlNodeType.SignificantWhitespace:
  181.                 case XmlNodeType.EndElement:
  182.                 case XmlNodeType.EndEntity:
  183.                     return true;
  184.                 case XmlNodeType.Element:
  185.                 case XmlNodeType.Attribute:
  186.                 case XmlNodeType.EntityReference:
  187.                 case XmlNodeType.Entity:
  188.                 case XmlNodeType.ProcessingInstruction:
  189.                 case XmlNodeType.DocumentType:
  190.                 case XmlNodeType.Notation:
  191.                 case XmlNodeType.XmlDeclaration:
  192.                     return false;
  193.                 default:
  194.                     return true;
  195.             }
  196.         }
  197.        
  198.         public string Prefix {
  199.             get { return curNode.Prefix; }
  200.         }
  201.        
  202.         public bool HasValue {
  203.             //In DOM, DocumentType node and XmlDeclaration node doesn't value
  204.             //In XPathNavigator, XmlDeclaration node's value is its InnerText; DocumentType doesn't have value
  205.             //In XmlReader, DocumentType node's value is its InternalSubset which is never null ( at least String.Empty )
  206.             get {
  207.                 if (nAttrInd != -1) {
  208.                     //Pointing at the one of virtual attributes of Declaration or DocumentType nodes
  209.                     Debug.Assert(curNode.NodeType == XmlNodeType.XmlDeclaration || curNode.NodeType == XmlNodeType.DocumentType);
  210.                     Debug.Assert(nAttrInd >= 0 && nAttrInd < AttributeCount);
  211.                     return true;
  212.                 }
  213.                 if (curNode.Value != null || curNode.NodeType == XmlNodeType.DocumentType)
  214.                     return true;
  215.                 return false;
  216.             }
  217.         }
  218.        
  219.         public string Value {
  220.             //See comments in HasValue
  221.             get {
  222.                 string retValue = null;
  223.                 XmlNodeType nt = curNode.NodeType;
  224.                 if (nAttrInd != -1) {
  225.                     //Pointing at the one of virtual attributes of Declaration or DocumentType nodes
  226.                     Debug.Assert(nt == XmlNodeType.XmlDeclaration || nt == XmlNodeType.DocumentType);
  227.                     Debug.Assert(nAttrInd >= 0 && nAttrInd < AttributeCount);
  228.                     if (curNode.NodeType == XmlNodeType.XmlDeclaration)
  229.                         return decNodeAttributes[nAttrInd].value;
  230.                     else
  231.                         return docTypeNodeAttributes[nAttrInd].value;
  232.                 }
  233.                 if (nt == XmlNodeType.DocumentType)
  234.                     retValue = ((XmlDocumentType)curNode).InternalSubset;
  235.                 //in this case nav.Value will be null
  236.                 else if (nt == XmlNodeType.XmlDeclaration) {
  237.                     StringBuilder strb = new StringBuilder(String.Empty);
  238.                     if (nDeclarationAttrCount == -1)
  239.                         InitDecAttr();
  240.                     for (int i = 0; i < nDeclarationAttrCount; i++) {
  241.                         strb.Append(decNodeAttributes[i].name + "=\"" + decNodeAttributes[i].value + "\"");
  242.                         if (i != (nDeclarationAttrCount - 1))
  243.                             strb.Append(" ");
  244.                     }
  245.                     retValue = strb.ToString();
  246.                 }
  247.                 else
  248.                     retValue = curNode.Value;
  249.                 return (retValue == null) ? String.Empty : retValue;
  250.             }
  251.         }
  252.        
  253.         public string BaseURI {
  254.             get { return curNode.BaseURI; }
  255.         }
  256.        
  257.         public XmlSpace XmlSpace {
  258.             get { return curNode.XmlSpace; }
  259.         }
  260.        
  261.         public string XmlLang {
  262.             get { return curNode.XmlLang; }
  263.         }
  264.        
  265.         public bool IsEmptyElement {
  266.             get {
  267.                 if (curNode.NodeType == XmlNodeType.Element) {
  268.                     return ((XmlElement)curNode).IsEmpty;
  269.                 }
  270.                 return false;
  271.             }
  272.         }
  273.        
  274.         public bool IsDefault {
  275.             get {
  276.                 if (curNode.NodeType == XmlNodeType.Attribute) {
  277.                     return !((XmlAttribute)curNode).Specified;
  278.                 }
  279.                 return false;
  280.             }
  281.         }
  282.        
  283.         public IXmlSchemaInfo SchemaInfo {
  284.             get { return curNode.SchemaInfo; }
  285.         }
  286.        
  287.         public XmlNameTable NameTable {
  288.             get { return nameTable; }
  289.         }
  290.        
  291.         public int AttributeCount {
  292.             get {
  293.                 if (this.bCreatedOnAttribute)
  294.                     return 0;
  295.                 XmlNodeType nt = curNode.NodeType;
  296.                 if (nt == XmlNodeType.Element)
  297.                     return ((XmlElement)curNode).Attributes.Count;
  298.                 else if (nt == XmlNodeType.Attribute || (this.bOnAttrVal && nt != XmlNodeType.XmlDeclaration && nt != XmlNodeType.DocumentType))
  299.                     return elemNode.Attributes.Count;
  300.                 else if (nt == XmlNodeType.XmlDeclaration) {
  301.                     if (nDeclarationAttrCount != -1)
  302.                         return nDeclarationAttrCount;
  303.                     InitDecAttr();
  304.                     return nDeclarationAttrCount;
  305.                 }
  306.                 else if (nt == XmlNodeType.DocumentType) {
  307.                     if (nDocTypeAttrCount != -1)
  308.                         return nDocTypeAttrCount;
  309.                     InitDocTypeAttr();
  310.                     return nDocTypeAttrCount;
  311.                 }
  312.                 return 0;
  313.             }
  314.         }
  315.        
  316.         private void CheckIndexCondition(int attributeIndex)
  317.         {
  318.             if (attributeIndex < 0 || attributeIndex >= AttributeCount) {
  319.                 throw new ArgumentOutOfRangeException("attributeIndex");
  320.             }
  321.         }
  322.        
  323.         //8 functions below are the helper functions to deal with virtual attributes of XmlDeclaration nodes and DocumentType nodes.
  324.         private void InitDecAttr()
  325.         {
  326.             int i = 0;
  327.             string strTemp = doc.Version;
  328.             if (strTemp != null && strTemp.Length != 0) {
  329.                 decNodeAttributes[i].name = strVersion;
  330.                 decNodeAttributes[i].value = strTemp;
  331.                 i++;
  332.             }
  333.             strTemp = doc.Encoding;
  334.             if (strTemp != null && strTemp.Length != 0) {
  335.                 decNodeAttributes[i].name = strEncoding;
  336.                 decNodeAttributes[i].value = strTemp;
  337.                 i++;
  338.             }
  339.             strTemp = doc.Standalone;
  340.             if (strTemp != null && strTemp.Length != 0) {
  341.                 decNodeAttributes[i].name = strStandalone;
  342.                 decNodeAttributes[i].value = strTemp;
  343.                 i++;
  344.             }
  345.             nDeclarationAttrCount = i;
  346.         }
  347.        
  348.         public string GetDeclarationAttr(XmlDeclaration decl, string name)
  349.         {
  350.             //PreCondition: curNode is pointing at Declaration node or one of its virtual attributes
  351.             if (name == strVersion)
  352.                 return decl.Version;
  353.             if (name == strEncoding)
  354.                 return decl.Encoding;
  355.             if (name == strStandalone)
  356.                 return decl.Standalone;
  357.             return null;
  358.         }
  359.        
  360.         public string GetDeclarationAttr(int i)
  361.         {
  362.             if (nDeclarationAttrCount == -1)
  363.                 InitDecAttr();
  364.             return decNodeAttributes[i].value;
  365.         }
  366.        
  367.         public int GetDecAttrInd(string name)
  368.         {
  369.             if (nDeclarationAttrCount == -1)
  370.                 InitDecAttr();
  371.             for (int i = 0; i < nDeclarationAttrCount; i++) {
  372.                 if (decNodeAttributes[i].name == name)
  373.                     return i;
  374.             }
  375.             return -1;
  376.         }
  377.        
  378.         private void InitDocTypeAttr()
  379.         {
  380.             int i = 0;
  381.             XmlDocumentType docType = doc.DocumentType;
  382.             if (docType == null) {
  383.                 nDocTypeAttrCount = 0;
  384.                 return;
  385.             }
  386.             string strTemp = docType.PublicId;
  387.             if (strTemp != null) {
  388.                 docTypeNodeAttributes[i].name = strPublicID;
  389.                 docTypeNodeAttributes[i].value = strTemp;
  390.                 i++;
  391.             }
  392.             strTemp = docType.SystemId;
  393.             if (strTemp != null) {
  394.                 docTypeNodeAttributes[i].name = strSystemID;
  395.                 docTypeNodeAttributes[i].value = strTemp;
  396.                 i++;
  397.             }
  398.             nDocTypeAttrCount = i;
  399.         }
  400.        
  401.         public string GetDocumentTypeAttr(XmlDocumentType docType, string name)
  402.         {
  403.             //PreCondition: nav is pointing at DocumentType node or one of its virtual attributes
  404.             if (name == strPublicID)
  405.                 return docType.PublicId;
  406.             if (name == strSystemID)
  407.                 return docType.SystemId;
  408.             return null;
  409.         }
  410.        
  411.         public string GetDocumentTypeAttr(int i)
  412.         {
  413.             if (nDocTypeAttrCount == -1)
  414.                 InitDocTypeAttr();
  415.             return docTypeNodeAttributes[i].value;
  416.         }
  417.        
  418.         public int GetDocTypeAttrInd(string name)
  419.         {
  420.             if (nDocTypeAttrCount == -1)
  421.                 InitDocTypeAttr();
  422.             for (int i = 0; i < nDocTypeAttrCount; i++) {
  423.                 if (docTypeNodeAttributes[i].name == name)
  424.                     return i;
  425.             }
  426.             return -1;
  427.         }
  428.        
  429.         private string GetAttributeFromElement(XmlElement elem, string name)
  430.         {
  431.             XmlAttribute attr = elem.GetAttributeNode(name);
  432.             if (attr != null)
  433.                 return attr.Value;
  434.             return null;
  435.         }
  436.        
  437.         public string GetAttribute(string name)
  438.         {
  439.             if (this.bCreatedOnAttribute)
  440.                 return null;
  441.             switch (curNode.NodeType) {
  442.                 case XmlNodeType.Element:
  443.                     return GetAttributeFromElement((XmlElement)curNode, name);
  444.                 case XmlNodeType.Attribute:
  445.                     return GetAttributeFromElement((XmlElement)elemNode, name);
  446.                 case XmlNodeType.XmlDeclaration:
  447.                     return GetDeclarationAttr((XmlDeclaration)curNode, name);
  448.                 case XmlNodeType.DocumentType:
  449.                     return GetDocumentTypeAttr((XmlDocumentType)curNode, name);
  450.             }
  451.             return null;
  452.         }
  453.        
  454.         private string GetAttributeFromElement(XmlElement elem, string name, string ns)
  455.         {
  456.             XmlAttribute attr = elem.GetAttributeNode(name, ns);
  457.             if (attr != null)
  458.                 return attr.Value;
  459.             return null;
  460.         }
  461.         public string GetAttribute(string name, string ns)
  462.         {
  463.             if (this.bCreatedOnAttribute)
  464.                 return null;
  465.             switch (curNode.NodeType) {
  466.                 case XmlNodeType.Element:
  467.                     return GetAttributeFromElement((XmlElement)curNode, name, ns);
  468.                 case XmlNodeType.Attribute:
  469.                     return GetAttributeFromElement((XmlElement)elemNode, name, ns);
  470.                 case XmlNodeType.XmlDeclaration:
  471.                     return (ns.Length == 0) ? GetDeclarationAttr((XmlDeclaration)curNode, name) : null;
  472.                 case XmlNodeType.DocumentType:
  473.                     return (ns.Length == 0) ? GetDocumentTypeAttr((XmlDocumentType)curNode, name) : null;
  474.             }
  475.             return null;
  476.         }
  477.        
  478.         public string GetAttribute(int attributeIndex)
  479.         {
  480.             if (this.bCreatedOnAttribute)
  481.                 return null;
  482.             switch (curNode.NodeType) {
  483.                 case XmlNodeType.Element:
  484.                     CheckIndexCondition(attributeIndex);
  485.                     return ((XmlElement)curNode).Attributes[attributeIndex].Value;
  486.                 case XmlNodeType.Attribute:
  487.                     CheckIndexCondition(attributeIndex);
  488.                     return ((XmlElement)elemNode).Attributes[attributeIndex].Value;
  489.                 case XmlNodeType.XmlDeclaration:
  490.                    
  491.                     {
  492.                         CheckIndexCondition(attributeIndex);
  493.                         return GetDeclarationAttr(attributeIndex);
  494.                     }
  495.                     break;
  496.                 case XmlNodeType.DocumentType:
  497.                    
  498.                     {
  499.                         CheckIndexCondition(attributeIndex);
  500.                         return GetDocumentTypeAttr(attributeIndex);
  501.                     }
  502.                     break;
  503.             }
  504.             throw new ArgumentOutOfRangeException("attributeIndex");
  505.             //for other senario, AttributeCount is 0, i has to be out of range
  506.         }
  507.        
  508.         public void LogMove(int level)
  509.         {
  510.             logNode = curNode;
  511.             nLogLevel = level;
  512.             nLogAttrInd = nAttrInd;
  513.             logAttrIndex = attrIndex;
  514.             this.bLogOnAttrVal = this.bOnAttrVal;
  515.         }
  516.        
  517.         //The function has to be used in pair with ResetMove when the operation fails after LogMove() is
  518.         // called because it relies on the values of nOrigLevel, logNav and nOrigAttrInd to be acurate.
  519.         public void RollBackMove(ref int level)
  520.         {
  521.             curNode = logNode;
  522.             level = nLogLevel;
  523.             nAttrInd = nLogAttrInd;
  524.             attrIndex = logAttrIndex;
  525.             this.bOnAttrVal = this.bLogOnAttrVal;
  526.         }
  527.        
  528.         private bool IsOnDeclOrDocType {
  529.             get {
  530.                 XmlNodeType nt = curNode.NodeType;
  531.                 return (nt == XmlNodeType.XmlDeclaration || nt == XmlNodeType.DocumentType);
  532.             }
  533.         }
  534.        
  535.         public void ResetToAttribute(ref int level)
  536.         {
  537.             //the current cursor is pointing at one of the attribute children -- this could be caused by
  538.             // the calls to ReadAttributeValue(..)
  539.             if (this.bCreatedOnAttribute)
  540.                 return;
  541.             if (this.bOnAttrVal) {
  542.                 if (IsOnDeclOrDocType) {
  543.                     level -= 2;
  544.                 }
  545.                 else {
  546.                     while (curNode.NodeType != XmlNodeType.Attribute && ((curNode = curNode.ParentNode) != null))
  547.                         level--;
  548.                 }
  549.                 this.bOnAttrVal = false;
  550.             }
  551.         }
  552.        
  553.         public void ResetMove(ref int level, ref XmlNodeType nt)
  554.         {
  555.             LogMove(level);
  556.             if (this.bCreatedOnAttribute)
  557.                 return;
  558.             if (nAttrInd != -1) {
  559.                 Debug.Assert(IsOnDeclOrDocType);
  560.                 if (this.bOnAttrVal) {
  561.                     level--;
  562.                     this.bOnAttrVal = false;
  563.                 }
  564.                 nLogAttrInd = nAttrInd;
  565.                 level--;
  566.                 nAttrInd = -1;
  567.                 nt = curNode.NodeType;
  568.                 return;
  569.             }
  570.             if (this.bOnAttrVal && curNode.NodeType != XmlNodeType.Attribute)
  571.                 ResetToAttribute(ref level);
  572.             if (curNode.NodeType == XmlNodeType.Attribute) {
  573.                 curNode = ((XmlAttribute)curNode).OwnerElement;
  574.                 attrIndex = -1;
  575.                 level--;
  576.                 nt = XmlNodeType.Element;
  577.             }
  578.             if (curNode.NodeType == XmlNodeType.Element)
  579.                 elemNode = curNode;
  580.         }
  581.        
  582.         public bool MoveToAttribute(string name)
  583.         {
  584.             return MoveToAttribute(name, string.Empty);
  585.         }
  586.         private bool MoveToAttributeFromElement(XmlElement elem, string name, string ns)
  587.         {
  588.             XmlAttribute attr = null;
  589.             if (ns.Length == 0)
  590.                 attr = elem.GetAttributeNode(name);
  591.             else
  592.                 attr = elem.GetAttributeNode(name, ns);
  593.             if (attr != null) {
  594.                 this.bOnAttrVal = false;
  595.                 elemNode = elem;
  596.                 curNode = attr;
  597.                 attrIndex = elem.Attributes.FindNodeOffsetNS(attr);
  598.                 if (attrIndex != -1) {
  599.                     return true;
  600.                 }
  601.             }
  602.             return false;
  603.         }
  604.        
  605.         public bool MoveToAttribute(string name, string namespaceURI)
  606.         {
  607.             if (this.bCreatedOnAttribute)
  608.                 return false;
  609.             XmlNodeType nt = curNode.NodeType;
  610.             if (nt == XmlNodeType.Element)
  611.                 return MoveToAttributeFromElement((XmlElement)curNode, name, namespaceURI);
  612.             else if (nt == XmlNodeType.Attribute)
  613.                 return MoveToAttributeFromElement((XmlElement)elemNode, name, namespaceURI);
  614.             else if (nt == XmlNodeType.XmlDeclaration && namespaceURI.Length == 0) {
  615.                 if ((nAttrInd = GetDecAttrInd(name)) != -1) {
  616.                     this.bOnAttrVal = false;
  617.                     return true;
  618.                 }
  619.             }
  620.             else if (nt == XmlNodeType.DocumentType && namespaceURI.Length == 0) {
  621.                 if ((nAttrInd = GetDocTypeAttrInd(name)) != -1) {
  622.                     this.bOnAttrVal = false;
  623.                     return true;
  624.                 }
  625.             }
  626.             return false;
  627.         }
  628.        
  629.         public void MoveToAttribute(int attributeIndex)
  630.         {
  631.             if (this.bCreatedOnAttribute)
  632.                 return;
  633.             XmlAttribute attr = null;
  634.             switch (curNode.NodeType) {
  635.                 case XmlNodeType.Element:
  636.                     CheckIndexCondition(attributeIndex);
  637.                     attr = ((XmlElement)curNode).Attributes[attributeIndex];
  638.                     if (attr != null) {
  639.                         elemNode = curNode;
  640.                         curNode = (XmlNode)attr;
  641.                         attrIndex = attributeIndex;
  642.                     }
  643.                     break;
  644.                 case XmlNodeType.Attribute:
  645.                     CheckIndexCondition(attributeIndex);
  646.                     attr = ((XmlElement)elemNode).Attributes[attributeIndex];
  647.                     if (attr != null) {
  648.                         curNode = (XmlNode)attr;
  649.                         attrIndex = attributeIndex;
  650.                     }
  651.                     break;
  652.                 case XmlNodeType.XmlDeclaration:
  653.                 case XmlNodeType.DocumentType:
  654.                     CheckIndexCondition(attributeIndex);
  655.                     nAttrInd = attributeIndex;
  656.                     break;
  657.             }
  658.         }
  659.        
  660.         public bool MoveToNextAttribute(ref int level)
  661.         {
  662.             if (this.bCreatedOnAttribute)
  663.                 return false;
  664.             XmlNodeType nt = curNode.NodeType;
  665.             if (nt == XmlNodeType.Attribute) {
  666.                 if (attrIndex >= (elemNode.Attributes.Count - 1))
  667.                     return false;
  668.                 else {
  669.                     curNode = elemNode.Attributes[++attrIndex];
  670.                     return true;
  671.                 }
  672.             }
  673.             else if (nt == XmlNodeType.Element) {
  674.                 if (curNode.Attributes.Count > 0) {
  675.                     level++;
  676.                     elemNode = curNode;
  677.                     curNode = curNode.Attributes[0];
  678.                     attrIndex = 0;
  679.                     return true;
  680.                 }
  681.             }
  682.             else if (nt == XmlNodeType.XmlDeclaration) {
  683.                 if (nDeclarationAttrCount == -1)
  684.                     InitDecAttr();
  685.                 nAttrInd++;
  686.                 if (nAttrInd < nDeclarationAttrCount) {
  687.                     if (nAttrInd == 0)
  688.                         level++;
  689.                     this.bOnAttrVal = false;
  690.                     return true;
  691.                 }
  692.                 nAttrInd--;
  693.             }
  694.             else if (nt == XmlNodeType.DocumentType) {
  695.                 if (nDocTypeAttrCount == -1)
  696.                     InitDocTypeAttr();
  697.                 nAttrInd++;
  698.                 if (nAttrInd < nDocTypeAttrCount) {
  699.                     if (nAttrInd == 0)
  700.                         level++;
  701.                     this.bOnAttrVal = false;
  702.                     return true;
  703.                 }
  704.                 nAttrInd--;
  705.             }
  706.             return false;
  707.         }
  708.        
  709.         public bool MoveToParent()
  710.         {
  711.             XmlNode parent = curNode.ParentNode;
  712.             if (parent != null) {
  713.                 curNode = parent;
  714.                 if (!bOnAttrVal)
  715.                     attrIndex = 0;
  716.                 return true;
  717.             }
  718.             return false;
  719.         }
  720.        
  721.         public bool MoveToFirstChild()
  722.         {
  723.             XmlNode firstChild = curNode.FirstChild;
  724.             if (firstChild != null) {
  725.                 curNode = firstChild;
  726.                 if (!bOnAttrVal)
  727.                     attrIndex = -1;
  728.                 return true;
  729.             }
  730.             return false;
  731.         }
  732.        
  733.         private bool MoveToNextSibling(XmlNode node)
  734.         {
  735.             XmlNode nextSibling = node.NextSibling;
  736.             if (nextSibling != null) {
  737.                 curNode = nextSibling;
  738.                 if (!bOnAttrVal)
  739.                     attrIndex = -1;
  740.                 return true;
  741.             }
  742.             return false;
  743.         }
  744.        
  745.         public bool MoveToNext()
  746.         {
  747.             if (curNode.NodeType != XmlNodeType.Attribute)
  748.                 return MoveToNextSibling(curNode);
  749.             else
  750.                 return MoveToNextSibling(elemNode);
  751.         }
  752.        
  753.         public bool MoveToElement()
  754.         {
  755.             if (this.bCreatedOnAttribute)
  756.                 return false;
  757.             switch (curNode.NodeType) {
  758.                 case XmlNodeType.Attribute:
  759.                     if (elemNode != null) {
  760.                         curNode = elemNode;
  761.                         attrIndex = -1;
  762.                         return true;
  763.                     }
  764.                     break;
  765.                 case XmlNodeType.XmlDeclaration:
  766.                 case XmlNodeType.DocumentType:
  767.                    
  768.                     {
  769.                         if (nAttrInd != -1) {
  770.                             nAttrInd = -1;
  771.                             return true;
  772.                         }
  773.                         break;
  774.                     }
  775.                     break;
  776.             }
  777.             return false;
  778.         }
  779.        
  780.         public string LookupNamespace(string prefix)
  781.         {
  782.             if (this.bCreatedOnAttribute)
  783.                 return null;
  784.             if (prefix == "xmlns") {
  785.                 return nameTable.Add(XmlReservedNs.NsXmlNs);
  786.             }
  787.             if (prefix == "xml") {
  788.                 return nameTable.Add(XmlReservedNs.NsXml);
  789.             }
  790.            
  791.             // construct the name of the xmlns attribute
  792.             string attrName;
  793.             if (prefix == null)
  794.                 prefix = string.Empty;
  795.             if (prefix.Length == 0)
  796.                 attrName = "xmlns";
  797.             else
  798.                 attrName = "xmlns:" + prefix;
  799.            
  800.             // walk up the XmlNode parent chain, looking for the xmlns attribute
  801.             XmlNode node = curNode;
  802.             while (node != null) {
  803.                 if (node.NodeType == XmlNodeType.Element) {
  804.                     XmlElement elem = (XmlElement)node;
  805.                     if (elem.HasAttributes) {
  806.                         XmlAttribute attr = elem.GetAttributeNode(attrName);
  807.                         if (attr != null) {
  808.                             return nameTable.Add(attr.Value);
  809.                         }
  810.                     }
  811.                 }
  812.                 else if (node.NodeType == XmlNodeType.Attribute) {
  813.                     node = ((XmlAttribute)node).OwnerElement;
  814.                     continue;
  815.                 }
  816.                 node = node.ParentNode;
  817.             }
  818.             if (prefix.Length == 0) {
  819.                 return string.Empty;
  820.             }
  821.             return null;
  822.         }
  823.        
  824.         internal string DefaultLookupNamespace(string prefix)
  825.         {
  826.             if (!this.bCreatedOnAttribute) {
  827.                 if (prefix == "xmlns") {
  828.                     return nameTable.Add(XmlReservedNs.NsXmlNs);
  829.                 }
  830.                 if (prefix == "xml") {
  831.                     return nameTable.Add(XmlReservedNs.NsXml);
  832.                 }
  833.                 if (prefix == string.Empty) {
  834.                     return nameTable.Add(string.Empty);
  835.                 }
  836.             }
  837.             return null;
  838.         }
  839.        
  840.         internal string LookupPrefix(string namespaceName)
  841.         {
  842.             if (this.bCreatedOnAttribute || namespaceName == null) {
  843.                 return null;
  844.             }
  845.             if (namespaceName == XmlReservedNs.NsXmlNs) {
  846.                 return nameTable.Add("xmlns");
  847.             }
  848.             if (namespaceName == XmlReservedNs.NsXml) {
  849.                 return nameTable.Add("xml");
  850.             }
  851.             if (namespaceName == string.Empty) {
  852.                 return string.Empty;
  853.             }
  854.             // walk up the XmlNode parent chain, looking for the xmlns attribute with namespaceName value
  855.             XmlNode node = curNode;
  856.             while (node != null) {
  857.                 if (node.NodeType == XmlNodeType.Element) {
  858.                     XmlElement elem = (XmlElement)node;
  859.                     if (elem.HasAttributes) {
  860.                         XmlAttributeCollection attrs = elem.Attributes;
  861.                         for (int i = 0; i < attrs.Count; i++) {
  862.                             XmlAttribute a = attrs[i];
  863.                             if (a.Value == namespaceName) {
  864.                                 if (a.Prefix.Length == 0 && a.LocalName == "xmlns") {
  865.                                     if (LookupNamespace(string.Empty) == namespaceName) {
  866.                                         return string.Empty;
  867.                                     }
  868.                                 }
  869.                                 else if (a.Prefix == "xmlns") {
  870.                                     string pref = a.LocalName;
  871.                                     if (LookupNamespace(pref) == namespaceName) {
  872.                                         return nameTable.Add(pref);
  873.                                     }
  874.                                 }
  875.                             }
  876.                         }
  877.                     }
  878.                 }
  879.                 else if (node.NodeType == XmlNodeType.Attribute) {
  880.                     node = ((XmlAttribute)node).OwnerElement;
  881.                     continue;
  882.                 }
  883.                 node = node.ParentNode;
  884.             }
  885.             return null;
  886.         }
  887.        
  888.         internal IDictionary<string, string> GetNamespacesInScope(XmlNamespaceScope scope)
  889.         {
  890.             Dictionary<string, string> dict = new Dictionary<string, string>();
  891.             if (this.bCreatedOnAttribute)
  892.                 return dict;
  893.            
  894.             // walk up the XmlNode parent chain and add all namespace declarations to the dictionary
  895.             XmlNode node = curNode;
  896.             while (node != null) {
  897.                 if (node.NodeType == XmlNodeType.Element) {
  898.                     XmlElement elem = (XmlElement)node;
  899.                     if (elem.HasAttributes) {
  900.                         XmlAttributeCollection attrs = elem.Attributes;
  901.                         for (int i = 0; i < attrs.Count; i++) {
  902.                             XmlAttribute a = attrs[i];
  903.                             if (a.LocalName == "xmlns" && a.Prefix.Length == 0) {
  904.                                 if (!dict.ContainsKey(string.Empty)) {
  905.                                     dict.Add(nameTable.Add(string.Empty), nameTable.Add(a.Value));
  906.                                 }
  907.                             }
  908.                             else if (a.Prefix == "xmlns") {
  909.                                 string localName = a.LocalName;
  910.                                 if (!dict.ContainsKey(localName)) {
  911.                                     dict.Add(nameTable.Add(localName), nameTable.Add(a.Value));
  912.                                 }
  913.                             }
  914.                         }
  915.                     }
  916.                     if (scope == XmlNamespaceScope.Local) {
  917.                         break;
  918.                     }
  919.                 }
  920.                 else if (node.NodeType == XmlNodeType.Attribute) {
  921.                     node = ((XmlAttribute)node).OwnerElement;
  922.                     continue;
  923.                 }
  924.                 node = node.ParentNode;
  925.             }
  926.             ;
  927.            
  928.             if (scope != XmlNamespaceScope.Local) {
  929.                 if (dict.ContainsKey(string.Empty) && dict[string.Empty] == string.Empty) {
  930.                     dict.Remove(string.Empty);
  931.                 }
  932.                 if (scope == XmlNamespaceScope.All) {
  933.                     dict.Add(nameTable.Add("xml"), nameTable.Add(XmlReservedNs.NsXml));
  934.                 }
  935.             }
  936.             return dict;
  937.         }
  938.        
  939.         public bool ReadAttributeValue(ref int level, ref bool bResolveEntity, ref XmlNodeType nt)
  940.         {
  941.             if (nAttrInd != -1) {
  942.                 Debug.Assert(curNode.NodeType == XmlNodeType.XmlDeclaration || curNode.NodeType == XmlNodeType.DocumentType);
  943.                 if (!this.bOnAttrVal) {
  944.                     this.bOnAttrVal = true;
  945.                     level++;
  946.                     nt = XmlNodeType.Text;
  947.                     return true;
  948.                 }
  949.                 return false;
  950.             }
  951.             if (curNode.NodeType == XmlNodeType.Attribute) {
  952.                 XmlNode firstChild = curNode.FirstChild;
  953.                 if (firstChild != null) {
  954.                     curNode = firstChild;
  955.                     nt = curNode.NodeType;
  956.                     level++;
  957.                     this.bOnAttrVal = true;
  958.                     return true;
  959.                 }
  960.             }
  961.             else if (this.bOnAttrVal) {
  962.                 XmlNode nextSibling = null;
  963.                 if (curNode.NodeType == XmlNodeType.EntityReference && bResolveEntity) {
  964.                     //going down to ent ref node
  965.                     curNode = curNode.FirstChild;
  966.                     nt = curNode.NodeType;
  967.                     Debug.Assert(curNode != null);
  968.                     level++;
  969.                     bResolveEntity = false;
  970.                     return true;
  971.                 }
  972.                 else
  973.                     nextSibling = curNode.NextSibling;
  974.                 if (nextSibling == null) {
  975.                     XmlNode parentNode = curNode.ParentNode;
  976.                     //Check if its parent is entity ref node is sufficient, because in this senario, ent ref node can't have more than 1 level of children that are not other ent ref nodes
  977.                     if (parentNode != null && parentNode.NodeType == XmlNodeType.EntityReference) {
  978.                         //come back from ent ref node
  979.                         curNode = parentNode;
  980.                         nt = XmlNodeType.EndEntity;
  981.                         level--;
  982.                         return true;
  983.                     }
  984.                 }
  985.                 if (nextSibling != null) {
  986.                     curNode = nextSibling;
  987.                     nt = curNode.NodeType;
  988.                     return true;
  989.                 }
  990.                 else
  991.                     return false;
  992.             }
  993.             return false;
  994.         }
  995.        
  996.     }
  997.    
  998.     // Represents a reader that provides fast, non-cached forward only stream access
  999.     // to XML data in an XmlDocument or a specific XmlNode within an XmlDocument.
  1000.     public class XmlNodeReader : XmlReader, IXmlNamespaceResolver
  1001.     {
  1002.         XmlNodeReaderNavigator readerNav;
  1003.        
  1004.         XmlNodeType nodeType;
  1005.         // nodeType of the node that the reader is currently positioned on
  1006.         int curDepth;
  1007.         // depth of attrNav ( also functions as reader's depth )
  1008.         ReadState readState;
  1009.         // current reader's state
  1010.         bool fEOF;
  1011.         // flag to show if reaches the end of file
  1012.         //mark to the state that EntityReference node is supposed to be resolved
  1013.         bool bResolveEntity;
  1014.         bool bStartFromDocument;
  1015.        
  1016.         bool bInReadBinary;
  1017.         ReadContentAsBinaryHelper readBinaryHelper;
  1018.        
  1019.        
  1020.         // Creates an instance of the XmlNodeReader class using the specified XmlNode.
  1021.         public XmlNodeReader(XmlNode node)
  1022.         {
  1023.             Init(node);
  1024.         }
  1025.        
  1026.         private void Init(XmlNode node)
  1027.         {
  1028.             readerNav = new XmlNodeReaderNavigator(node);
  1029.             this.curDepth = 0;
  1030.            
  1031.             readState = ReadState.Initial;
  1032.             fEOF = false;
  1033.             nodeType = XmlNodeType.None;
  1034.             bResolveEntity = false;
  1035.             bStartFromDocument = false;
  1036.         }
  1037.        
  1038.         //function returns if the reader currently in valid reading states
  1039.         internal bool IsInReadingStates()
  1040.         {
  1041.             return (readState == ReadState.Interactive);
  1042.             // || readState == ReadState.EndOfFile
  1043.         }
  1044.        
  1045.         //
  1046.         // Node Properties
  1047.         //
  1048.        
  1049.         // Gets the type of the current node.
  1050.         public override XmlNodeType NodeType {
  1051.             get { return (IsInReadingStates()) ? nodeType : XmlNodeType.None; }
  1052.         }
  1053.        
  1054.         // Gets the name of
  1055.         // the current node, including the namespace prefix.
  1056.         public override string Name {
  1057.             get {
  1058.                 if (!IsInReadingStates())
  1059.                     return String.Empty;
  1060.                 return readerNav.Name;
  1061.             }
  1062.         }
  1063.        
  1064.         // Gets the name of the current node without the namespace prefix.
  1065.         public override string LocalName {
  1066.             get {
  1067.                 if (!IsInReadingStates())
  1068.                     return String.Empty;
  1069.                 return readerNav.LocalName;
  1070.             }
  1071.         }
  1072.        
  1073.         // Gets the namespace URN (as defined in the W3C Namespace Specification)
  1074.         // of the current namespace scope.
  1075.         public override string NamespaceURI {
  1076.             get {
  1077.                 if (!IsInReadingStates())
  1078.                     return String.Empty;
  1079.                 return readerNav.NamespaceURI;
  1080.             }
  1081.         }
  1082.        
  1083.         // Gets the namespace prefix associated with the current node.
  1084.         public override string Prefix {
  1085.             get {
  1086.                 if (!IsInReadingStates())
  1087.                     return String.Empty;
  1088.                 return readerNav.Prefix;
  1089.             }
  1090.         }
  1091.        
  1092.         // Gets a value indicating whether
  1093.         // XmlNodeReader.Value has a value to return.
  1094.         public override bool HasValue {
  1095.             get {
  1096.                 if (!IsInReadingStates())
  1097.                     return false;
  1098.                 return readerNav.HasValue;
  1099.             }
  1100.         }
  1101.        
  1102.         // Gets the text value of the current node.
  1103.         public override string Value {
  1104.             get {
  1105.                 if (!IsInReadingStates())
  1106.                     return String.Empty;
  1107.                 return readerNav.Value;
  1108.             }
  1109.         }
  1110.        
  1111.         // Gets the depth of the
  1112.         // current node in the XML element stack.
  1113.         public override int Depth {
  1114.             get { return curDepth; }
  1115.         }
  1116.        
  1117.         // Gets the base URI of the current node.
  1118.         public override string BaseURI {
  1119.             get { return readerNav.BaseURI; }
  1120.         }
  1121.        
  1122.         public override bool CanResolveEntity {
  1123.             get { return true; }
  1124.         }
  1125.        
  1126.         // Gets a value indicating whether the current
  1127.         // node is an empty element (for example, <MyElement/>.
  1128.         public override bool IsEmptyElement {
  1129.             get {
  1130.                 if (!IsInReadingStates())
  1131.                     return false;
  1132.                 return readerNav.IsEmptyElement;
  1133.             }
  1134.         }
  1135.        
  1136.         // Gets a value indicating whether the current node is an
  1137.         // attribute that was generated from the default value defined
  1138.         // in the DTD or schema.
  1139.         public override bool IsDefault {
  1140.             get {
  1141.                 if (!IsInReadingStates())
  1142.                     return false;
  1143.                 return readerNav.IsDefault;
  1144.             }
  1145.         }
  1146.        
  1147.         // Gets the current xml:space scope.
  1148.         public override XmlSpace XmlSpace {
  1149.             get {
  1150.                 if (!IsInReadingStates())
  1151.                     return XmlSpace.None;
  1152.                 return readerNav.XmlSpace;
  1153.             }
  1154.         }
  1155.        
  1156.         // Gets the current xml:lang scope.
  1157.         public override string XmlLang {
  1158.             // Assume everything is in Unicode
  1159.             get {
  1160.                 if (!IsInReadingStates())
  1161.                     return String.Empty;
  1162.                 return readerNav.XmlLang;
  1163.             }
  1164.         }
  1165.        
  1166.         public override IXmlSchemaInfo SchemaInfo {
  1167.             get {
  1168.                 if (!IsInReadingStates()) {
  1169.                     return null;
  1170.                 }
  1171.                 return readerNav.SchemaInfo;
  1172.             }
  1173.         }
  1174.        
  1175.         //
  1176.         // Attribute Accessors
  1177.         //
  1178.        
  1179.         // Gets the number of attributes on the current node.
  1180.         public override int AttributeCount {
  1181.             get {
  1182.                 if (!IsInReadingStates() || nodeType == XmlNodeType.EndElement)
  1183.                     return 0;
  1184.                 return readerNav.AttributeCount;
  1185.             }
  1186.         }
  1187.        
  1188.         // Gets the value of the attribute with the specified name.
  1189.         public override string GetAttribute(string name)
  1190.         {
  1191.             //if not on Attribute, only element node could have attributes
  1192.             if (!IsInReadingStates())
  1193.                 return null;
  1194.             return readerNav.GetAttribute(name);
  1195.         }
  1196.        
  1197.         // Gets the value of the attribute with the specified name and namespace.
  1198.         public override string GetAttribute(string name, string namespaceURI)
  1199.         {
  1200.             //if not on Attribute, only element node could have attributes
  1201.             if (!IsInReadingStates())
  1202.                 return null;
  1203.             string ns = (namespaceURI == null) ? String.Empty : namespaceURI;
  1204.             return readerNav.GetAttribute(name, ns);
  1205.         }
  1206.        
  1207.         // Gets the value of the attribute with the specified index.
  1208.         public override string GetAttribute(int attributeIndex)
  1209.         {
  1210.             if (!IsInReadingStates())
  1211.                 throw new ArgumentOutOfRangeException("attributeIndex");
  1212.             //CheckIndexCondition( i );
  1213.             //Debug.Assert( nav.NodeType == XmlNodeType.Element );
  1214.             return readerNav.GetAttribute(attributeIndex);
  1215.         }
  1216.        
  1217.         // Moves to the attribute with the specified name.
  1218.         public override bool MoveToAttribute(string name)
  1219.         {
  1220.             if (!IsInReadingStates())
  1221.                 return false;
  1222.             readerNav.ResetMove(ref curDepth, ref nodeType);
  1223.             if (readerNav.MoveToAttribute(name)) {
  1224.                 //, ref curDepth ) ) {
  1225.                 curDepth++;
  1226.                 nodeType = readerNav.NodeType;
  1227.                 if (bInReadBinary) {
  1228.                     FinishReadBinary();
  1229.                 }
  1230.                 return true;
  1231.             }
  1232.             readerNav.RollBackMove(ref curDepth);
  1233.             return false;
  1234.         }
  1235.        
  1236.         // Moves to the attribute with the specified name and namespace.
  1237.         public override bool MoveToAttribute(string name, string namespaceURI)
  1238.         {
  1239.             if (!IsInReadingStates())
  1240.                 return false;
  1241.             readerNav.ResetMove(ref curDepth, ref nodeType);
  1242.             string ns = (namespaceURI == null) ? String.Empty : namespaceURI;
  1243.             if (readerNav.MoveToAttribute(name, ns)) {
  1244.                 //, ref curDepth ) ) {
  1245.                 curDepth++;
  1246.                 nodeType = readerNav.NodeType;
  1247.                 if (bInReadBinary) {
  1248.                     FinishReadBinary();
  1249.                 }
  1250.                 return true;
  1251.             }
  1252.             readerNav.RollBackMove(ref curDepth);
  1253.             return false;
  1254.         }
  1255.        
  1256.         // Moves to the attribute with the specified index.
  1257.         public override void MoveToAttribute(int attributeIndex)
  1258.         {
  1259.             if (!IsInReadingStates())
  1260.                 throw new ArgumentOutOfRangeException("attributeIndex");
  1261.             readerNav.ResetMove(ref curDepth, ref nodeType);
  1262.             try {
  1263.                 if (AttributeCount > 0) {
  1264.                     readerNav.MoveToAttribute(attributeIndex);
  1265.                     if (bInReadBinary) {
  1266.                         FinishReadBinary();
  1267.                     }
  1268.                 }
  1269.                 else
  1270.                     throw new ArgumentOutOfRangeException("attributeIndex");
  1271.             }
  1272.             catch {
  1273.                 readerNav.RollBackMove(ref curDepth);
  1274.                 throw;
  1275.             }
  1276.             curDepth++;
  1277.             nodeType = readerNav.NodeType;
  1278.         }
  1279.        
  1280.         // Moves to the first attribute.
  1281.         public override bool MoveToFirstAttribute()
  1282.         {
  1283.             if (!IsInReadingStates())
  1284.                 return false;
  1285.             readerNav.ResetMove(ref curDepth, ref nodeType);
  1286.             if (AttributeCount > 0) {
  1287.                 readerNav.MoveToAttribute(0);
  1288.                 curDepth++;
  1289.                 nodeType = readerNav.NodeType;
  1290.                 if (bInReadBinary) {
  1291.                     FinishReadBinary();
  1292.                 }
  1293.                 return true;
  1294.             }
  1295.             readerNav.RollBackMove(ref curDepth);
  1296.             return false;
  1297.         }
  1298.        
  1299.         // Moves to the next attribute.
  1300.         public override bool MoveToNextAttribute()
  1301.         {
  1302.             if (!IsInReadingStates() || nodeType == XmlNodeType.EndElement)
  1303.                 return false;
  1304.             readerNav.LogMove(curDepth);
  1305.             readerNav.ResetToAttribute(ref curDepth);
  1306.             if (readerNav.MoveToNextAttribute(ref curDepth)) {
  1307.                 nodeType = readerNav.NodeType;
  1308.                 if (bInReadBinary) {
  1309.                     FinishReadBinary();
  1310.                 }
  1311.                 return true;
  1312.             }
  1313.             readerNav.RollBackMove(ref curDepth);
  1314.             return false;
  1315.         }
  1316.        
  1317.         // Moves to the element that contains the current attribute node.
  1318.         public override bool MoveToElement()
  1319.         {
  1320.             if (!IsInReadingStates())
  1321.                 return false;
  1322.             readerNav.LogMove(curDepth);
  1323.             readerNav.ResetToAttribute(ref curDepth);
  1324.             if (readerNav.MoveToElement()) {
  1325.                 curDepth--;
  1326.                 nodeType = readerNav.NodeType;
  1327.                 if (bInReadBinary) {
  1328.                     FinishReadBinary();
  1329.                 }
  1330.                 return true;
  1331.             }
  1332.             readerNav.RollBackMove(ref curDepth);
  1333.             return false;
  1334.         }
  1335.        
  1336.         //
  1337.         // Moving through the Stream
  1338.         //
  1339.        
  1340.         // Reads the next node from the stream.
  1341.         public override bool Read()
  1342.         {
  1343.             return Read(false);
  1344.         }
  1345.         private bool Read(bool fSkipChildren)
  1346.         {
  1347.             if (fEOF)
  1348.                 return false;
  1349.            
  1350.             if (readState == ReadState.Initial) {
  1351.                 // if nav is pointing at the document node, start with its children
  1352.                 // otherwise,start with the node.
  1353.                 if ((readerNav.NodeType == XmlNodeType.Document) || (readerNav.NodeType == XmlNodeType.DocumentFragment)) {
  1354.                     bStartFromDocument = true;
  1355.                     if (!ReadNextNode(fSkipChildren)) {
  1356.                         readState = ReadState.Error;
  1357.                         return false;
  1358.                     }
  1359.                 }
  1360.                 ReSetReadingMarks();
  1361.                 readState = ReadState.Interactive;
  1362.                 nodeType = readerNav.NodeType;
  1363.                 //_depth = 0;
  1364.                 curDepth = 0;
  1365.                 return true;
  1366.             }
  1367.            
  1368.             if (bInReadBinary) {
  1369.                 FinishReadBinary();
  1370.             }
  1371.            
  1372.             bool bRead = false;
  1373.             if ((readerNav.CreatedOnAttribute))
  1374.                 return false;
  1375.             ReSetReadingMarks();
  1376.             bRead = ReadNextNode(fSkipChildren);
  1377.             if (bRead) {
  1378.                 return true;
  1379.             }
  1380.             else {
  1381.                 if (readState == ReadState.Initial || readState == ReadState.Interactive)
  1382.                     readState = ReadState.Error;
  1383.                 if (readState == ReadState.EndOfFile)
  1384.                     nodeType = XmlNodeType.None;
  1385.                 return false;
  1386.             }
  1387.         }
  1388.        
  1389.         private bool ReadNextNode(bool fSkipChildren)
  1390.         {
  1391.             if (readState != ReadState.Interactive && readState != ReadState.Initial) {
  1392.                 nodeType = XmlNodeType.None;
  1393.                 return false;
  1394.             }
  1395.            
  1396.             bool bDrillDown = !fSkipChildren;
  1397.             XmlNodeType nt = readerNav.NodeType;
  1398.             //only goes down when nav.NodeType is of element or of document at the initial state, other nav.NodeType will not be parsed down
  1399.             //if nav.NodeType is of EntityReference, ResolveEntity() could be called to get the content parsed;
  1400.             bDrillDown = bDrillDown && (nodeType != XmlNodeType.EndElement) && (nodeType != XmlNodeType.EndEntity) && (nt == XmlNodeType.Element || (nt == XmlNodeType.EntityReference && bResolveEntity) || (((readerNav.NodeType == XmlNodeType.Document) || (readerNav.NodeType == XmlNodeType.DocumentFragment)) && readState == ReadState.Initial));
  1401.             //first see if there are children of current node, so to move down
  1402.             if (bDrillDown) {
  1403.                 if (readerNav.MoveToFirstChild()) {
  1404.                     nodeType = readerNav.NodeType;
  1405.                     curDepth++;
  1406.                     if (bResolveEntity)
  1407.                         bResolveEntity = false;
  1408.                     return true;
  1409.                 }
  1410.                 else if (readerNav.NodeType == XmlNodeType.Element && !readerNav.IsEmptyElement) {
  1411.                     nodeType = XmlNodeType.EndElement;
  1412.                     return true;
  1413.                 }
  1414.                 //entity reference node shall always have at least one child ( at least a text node with empty string )
  1415.                 Debug.Assert(readerNav.NodeType != XmlNodeType.EntityReference);
  1416.                 // if fails to move to it 1st Child, try to move to next below
  1417.                 return ReadForward(fSkipChildren);
  1418.             }
  1419.             else {
  1420.                 if (readerNav.NodeType == XmlNodeType.EntityReference && bResolveEntity) {
  1421.                     //The only way to get to here is because Skip() is called directly after ResolveEntity()
  1422.                     // in this case, user wants to skip the first Child of EntityRef node and fSkipChildren is true
  1423.                     // We want to pointing to the first child node.
  1424.                     readerNav.MoveToFirstChild();
  1425.                     //it has to succeeded
  1426.                     nodeType = readerNav.NodeType;
  1427.                     curDepth++;
  1428.                     bResolveEntity = false;
  1429.                     return true;
  1430.                 }
  1431.             }
  1432.             return ReadForward(fSkipChildren);
  1433.             //has to get the next node by moving forward
  1434.         }
  1435.        
  1436.         private void SetEndOfFile()
  1437.         {
  1438.             fEOF = true;
  1439.             readState = ReadState.EndOfFile;
  1440.             nodeType = XmlNodeType.None;
  1441.         }
  1442.        
  1443.         private bool ReadAtZeroLevel(bool fSkipChildren)
  1444.         {
  1445.             Debug.Assert(curDepth == 0);
  1446.             if (!fSkipChildren && nodeType != XmlNodeType.EndElement && readerNav.NodeType == XmlNodeType.Element && !readerNav.IsEmptyElement) {
  1447.                 nodeType = XmlNodeType.EndElement;
  1448.                 return true;
  1449.             }
  1450.             else {
  1451.                 SetEndOfFile();
  1452.                 return false;
  1453.             }
  1454.         }
  1455.        
  1456.         private bool ReadForward(bool fSkipChildren)
  1457.         {
  1458.             if (readState == ReadState.Error)
  1459.                 return false;
  1460.            
  1461.             if (!bStartFromDocument && curDepth == 0) {
  1462.                 //already on top most node and we shouldn't move to next
  1463.                 return ReadAtZeroLevel(fSkipChildren);
  1464.             }
  1465.             //else either we are not on top level or we are starting from the document at the very beginning in which case
  1466.             // we will need to read all the "top" most nodes
  1467.             if (readerNav.MoveToNext()) {
  1468.                 nodeType = readerNav.NodeType;
  1469.                 return true;
  1470.             }
  1471.             else {
  1472.                 //need to check its parent
  1473.                 if (curDepth == 0)
  1474.                     return ReadAtZeroLevel(fSkipChildren);
  1475.                 if (readerNav.MoveToParent()) {
  1476.                     if (readerNav.NodeType == XmlNodeType.Element) {
  1477.                         curDepth--;
  1478.                         nodeType = XmlNodeType.EndElement;
  1479.                         return true;
  1480.                     }
  1481.                     else if (readerNav.NodeType == XmlNodeType.EntityReference) {
  1482.                         //coming back from entity reference node -- must be getting down through call ResolveEntity()
  1483.                         curDepth--;
  1484.                         nodeType = XmlNodeType.EndEntity;
  1485.                         return true;
  1486.                     }
  1487.                     return true;
  1488.                 }
  1489.             }
  1490.             return false;
  1491.         }
  1492.        
  1493.         //the function reset the marks used for ReadChars() and MoveToAttribute(...), ReadAttributeValue(...)
  1494.         private void ReSetReadingMarks()
  1495.         {
  1496.             //_attrValInd = -1;
  1497.             readerNav.ResetMove(ref curDepth, ref nodeType);
  1498.             //attrNav.MoveTo( nav );
  1499.             //curDepth = _depth;
  1500.         }
  1501.        
  1502.         // Gets a value indicating whether the reader is positioned at the
  1503.         // end of the stream.
  1504.         public override bool EOF {
  1505.             get { return (readState != ReadState.Closed) && fEOF; }
  1506.         }
  1507.        
  1508.         // Closes the stream, changes the XmlNodeReader.ReadState
  1509.         // to Closed, and sets all the properties back to zero.
  1510.         public override void Close()
  1511.         {
  1512.             readState = ReadState.Closed;
  1513.         }
  1514.        
  1515.         // Gets the read state of the stream.
  1516.         public override ReadState ReadState {
  1517.             get { return readState; }
  1518.         }
  1519.        
  1520.         // Skips to the end tag of the current element.
  1521.         public override void Skip()
  1522.         {
  1523.             Read(true);
  1524.         }
  1525.        
  1526.         // Reads the contents of an element as a string.
  1527.         public override string ReadString()
  1528.         {
  1529.             if ((this.NodeType == XmlNodeType.EntityReference) && bResolveEntity) {
  1530.                 if (!this.Read()) {
  1531.                     throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidOperation));
  1532.                 }
  1533.             }
  1534.             return base.ReadString();
  1535.         }
  1536.        
  1537.         //
  1538.         // Partial Content Read Methods
  1539.         //
  1540.        
  1541.         // Gets a value indicating whether the current node
  1542.         // has any attributes.
  1543.         public override bool HasAttributes {
  1544.             get { return (AttributeCount > 0); }
  1545.         }
  1546.        
  1547.         //
  1548.         // Nametable and Namespace Helpers
  1549.         //
  1550.        
  1551.         // Gets the XmlNameTable associated with this implementation.
  1552.         public override XmlNameTable NameTable {
  1553.             get { return readerNav.NameTable; }
  1554.         }
  1555.        
  1556.         // Resolves a namespace prefix in the current element's scope.
  1557.         public override string LookupNamespace(string prefix)
  1558.         {
  1559.             if (!IsInReadingStates())
  1560.                 return null;
  1561.             string ns = readerNav.LookupNamespace(prefix);
  1562.             if (ns != null && ns.Length == 0) {
  1563.                 return null;
  1564.             }
  1565.             return ns;
  1566.         }
  1567.        
  1568.         // Resolves the entity reference for nodes of NodeType EntityReference.
  1569.         public override void ResolveEntity()
  1570.         {
  1571.             if (!IsInReadingStates() || (nodeType != XmlNodeType.EntityReference))
  1572.                 throw new InvalidOperationException(Res.GetString(Res.Xnr_ResolveEntity));
  1573.             bResolveEntity = true;
  1574.             ;
  1575.         }
  1576.        
  1577.         // Parses the attribute value into one or more Text and/or
  1578.         // EntityReference node types.
  1579.         public override bool ReadAttributeValue()
  1580.         {
  1581.             if (!IsInReadingStates())
  1582.                 return false;
  1583.             if (readerNav.ReadAttributeValue(ref curDepth, ref bResolveEntity, ref nodeType)) {
  1584.                 bInReadBinary = false;
  1585.                 return true;
  1586.             }
  1587.             return false;
  1588.         }
  1589.        
  1590.         public override bool CanReadBinaryContent {
  1591.             get { return true; }
  1592.         }
  1593.        
  1594.         public override int ReadContentAsBase64(byte[] buffer, int index, int count)
  1595.         {
  1596.             if (readState != ReadState.Interactive) {
  1597.                 return 0;
  1598.             }
  1599.            
  1600.             // init ReadContentAsBinaryHelper when called first time
  1601.             if (!bInReadBinary) {
  1602.                 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset(readBinaryHelper, this);
  1603.             }
  1604.            
  1605.             // turn off bInReadBinary in order to have a normal Read() behavior when called from readBinaryHelper
  1606.             bInReadBinary = false;
  1607.            
  1608.             // call to the helper
  1609.             int readCount = readBinaryHelper.ReadContentAsBase64(buffer, index, count);
  1610.            
  1611.             // turn on bInReadBinary in again and return
  1612.             bInReadBinary = true;
  1613.             return readCount;
  1614.         }
  1615.        
  1616.         public override int ReadContentAsBinHex(byte[] buffer, int index, int count)
  1617.         {
  1618.             if (readState != ReadState.Interactive) {
  1619.                 return 0;
  1620.             }
  1621.            
  1622.             // init ReadContentAsBinaryHelper when called first time
  1623.             if (!bInReadBinary) {
  1624.                 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset(readBinaryHelper, this);
  1625.             }
  1626.            
  1627.             // turn off bInReadBinary in order to have a normal Read() behavior when called from readBinaryHelper
  1628.             bInReadBinary = false;
  1629.            
  1630.             // call to the helper
  1631.             int readCount = readBinaryHelper.ReadContentAsBinHex(buffer, index, count);
  1632.            
  1633.             // turn on bInReadBinary in again and return
  1634.             bInReadBinary = true;
  1635.             return readCount;
  1636.         }
  1637.        
  1638.         public override int ReadElementContentAsBase64(byte[] buffer, int index, int count)
  1639.         {
  1640.             if (readState != ReadState.Interactive) {
  1641.                 return 0;
  1642.             }
  1643.            
  1644.             // init ReadContentAsBinaryHelper when called first time
  1645.             if (!bInReadBinary) {
  1646.                 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset(readBinaryHelper, this);
  1647.             }
  1648.            
  1649.             // turn off bInReadBinary in order to have a normal Read() behavior when called from readBinaryHelper
  1650.             bInReadBinary = false;
  1651.            
  1652.             // call to the helper
  1653.             int readCount = readBinaryHelper.ReadElementContentAsBase64(buffer, index, count);
  1654.            
  1655.             // turn on bInReadBinary in again and return
  1656.             bInReadBinary = true;
  1657.             return readCount;
  1658.         }
  1659.        
  1660.         public override int ReadElementContentAsBinHex(byte[] buffer, int index, int count)
  1661.         {
  1662.             if (readState != ReadState.Interactive) {
  1663.                 return 0;
  1664.             }
  1665.            
  1666.             // init ReadContentAsBinaryHelper when called first time
  1667.             if (!bInReadBinary) {
  1668.                 readBinaryHelper = ReadContentAsBinaryHelper.CreateOrReset(readBinaryHelper, this);
  1669.             }
  1670.            
  1671.             // turn off bInReadBinary in order to have a normal Read() behavior when called from readBinaryHelper
  1672.             bInReadBinary = false;
  1673.            
  1674.             // call to the helper
  1675.             int readCount = readBinaryHelper.ReadElementContentAsBinHex(buffer, index, count);
  1676.            
  1677.             // turn on bInReadBinary in again and return
  1678.             bInReadBinary = true;
  1679.             return readCount;
  1680.         }
  1681.        
  1682.         void FinishReadBinary()
  1683.         {
  1684.             bInReadBinary = false;
  1685.             readBinaryHelper.Finish();
  1686.         }
  1687.        
  1688.         //
  1689.         // IXmlNamespaceResolver
  1690.         //
  1691.         IDictionary<string, string> IXmlNamespaceResolver.GetNamespacesInScope(XmlNamespaceScope scope)
  1692.         {
  1693.             return readerNav.GetNamespacesInScope(scope);
  1694.         }
  1695.        
  1696.         string IXmlNamespaceResolver.LookupPrefix(string namespaceName)
  1697.         {
  1698.             return readerNav.LookupPrefix(namespaceName);
  1699.         }
  1700.        
  1701.         string IXmlNamespaceResolver.LookupNamespace(string prefix)
  1702.         {
  1703.             if (!IsInReadingStates()) {
  1704.                 return readerNav.DefaultLookupNamespace(prefix);
  1705.             }
  1706.             return readerNav.LookupNamespace(prefix);
  1707.         }
  1708.     }
  1709. }

Developer Fusion