* Mono.Posix.dll.sources: Rename Mono.Posix to Mono.Unix.
[mono.git] / mcs / class / System.XML / Mono.Xml.XPath / XPathNavigatorReader.cs
1 //\r
2 // XPathNavigatorReader.cs\r
3 //\r
4 // Author:\r
5 //      Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>\r
6 //\r
7 // 2003 Atsushi Enomoto. No rights reserved.\r
8 // Copyright (C) 2004 Novell Inc.\r
9 \r
10 //\r
11 // Permission is hereby granted, free of charge, to any person obtaining\r
12 // a copy of this software and associated documentation files (the\r
13 // "Software"), to deal in the Software without restriction, including\r
14 // without limitation the rights to use, copy, modify, merge, publish,\r
15 // distribute, sublicense, and/or sell copies of the Software, and to\r
16 // permit persons to whom the Software is furnished to do so, subject to\r
17 // the following conditions:\r
18 // \r
19 // The above copyright notice and this permission notice shall be\r
20 // included in all copies or substantial portions of the Software.\r
21 // \r
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
29 //\r
30 #if NET_2_0\r
31 \r
32 using System;\r
33 using System.Text;\r
34 using System.Xml;\r
35 using System.Xml.Schema;\r
36 using System.Xml.XPath;\r
37 \r
38 namespace Mono.Xml.XPath\r
39 {\r
40 \r
41         internal class XPathNavigatorReader : XmlReader\r
42         {\r
43                 public XPathNavigatorReader (XPathNavigator nav)\r
44                 {\r
45                         // It seems that this class have only to support linked\r
46                         // node as its parameter\r
47                         switch (nav.NodeType) {\r
48                         case XPathNodeType.Attribute:\r
49                         case XPathNodeType.Namespace:\r
50                                 throw new InvalidOperationException (String.Format ("NodeType {0} is not supported to read as a subtree of an XPathNavigator.", nav.NodeType));\r
51                         }\r
52                         root = nav.Clone ();\r
53                         current = nav.Clone ();\r
54                 }\r
55 \r
56                 XPathNavigator root;\r
57                 XPathNavigator current;\r
58                 bool started;\r
59                 bool closed;\r
60                 bool endElement;\r
61                 bool attributeValueConsumed;\r
62                 StringBuilder readStringBuffer = new StringBuilder ();\r
63                 StringBuilder innerXmlBuilder = new StringBuilder ();\r
64 \r
65                 int depth = 0;\r
66                 int attributeCount = 0;\r
67                 bool eof;\r
68                 bool nextIsEOF;\r
69 \r
70                 #region Properties\r
71                 public override XmlNodeType NodeType \r
72                 {\r
73                         get {\r
74                                 if (ReadState != ReadState.Interactive)\r
75                                         return XmlNodeType.None;\r
76                                 if (endElement)\r
77                                         return XmlNodeType.EndElement;\r
78                                 if (attributeValueConsumed)\r
79                                         // Is there any way to get other kind of nodes than Text?\r
80                                         return XmlNodeType.Text;\r
81 \r
82                                 switch (current.NodeType) {\r
83                                 case XPathNodeType.Namespace:\r
84                                 case XPathNodeType.Attribute:\r
85                                         return XmlNodeType.Attribute;\r
86                                 case XPathNodeType.Comment:\r
87                                         return XmlNodeType.Comment;\r
88                                 case XPathNodeType.Element:\r
89                                         return XmlNodeType.Element;\r
90                                 case XPathNodeType.ProcessingInstruction:\r
91                                         return XmlNodeType.ProcessingInstruction;\r
92                                 case XPathNodeType.Root:\r
93                                         // It is actually Document, but in XmlReader there is no such situation to return Document.\r
94                                         return XmlNodeType.None;\r
95                                 case XPathNodeType.SignificantWhitespace:\r
96                                         return XmlNodeType.SignificantWhitespace;\r
97                                 case XPathNodeType.Text:\r
98                                         return XmlNodeType.Text;\r
99                                 case XPathNodeType.Whitespace:\r
100                                         return XmlNodeType.Whitespace;\r
101                                 default:\r
102                                         throw new InvalidOperationException (String.Format ("Current XPathNavigator status is {0} which is not acceptable to XmlReader.", current.NodeType));\r
103                                 }\r
104                         }\r
105                 }\r
106 \r
107                 public override string Name {\r
108                         get {\r
109                                 if (eof)\r
110                                         return String.Empty;\r
111                                 else if (current.NodeType == XPathNodeType.Namespace)\r
112                                         return current.Name == String.Empty ? "xmlns" : "xmlns:" + current.Name;\r
113                                 else\r
114                                         return current.Name;\r
115                         }\r
116                 }\r
117 \r
118                 public override string LocalName {\r
119                         get {\r
120                                 if (eof)\r
121                                         return String.Empty;\r
122                                 else if (current.NodeType == XPathNodeType.Namespace && current.LocalName == String.Empty)\r
123                                         return "xmlns";\r
124                                 else\r
125                                         return current.LocalName;\r
126                         }\r
127                 }\r
128 \r
129                 public override string NamespaceURI {\r
130                         get {\r
131                                 if (eof)\r
132                                         return String.Empty;\r
133                                 else if (current.NodeType == XPathNodeType.Namespace)\r
134                                         return XmlNamespaceManager.XmlnsXmlns;\r
135                                 else\r
136                                         return current.NamespaceURI;\r
137                         }\r
138                 }\r
139 \r
140                 public override string Prefix {\r
141                         get {\r
142                                 if (eof)\r
143                                         return String.Empty;\r
144                                 else if (current.NodeType == XPathNodeType.Namespace && current.LocalName != String.Empty)\r
145                                         return "xmlns";\r
146                                 else\r
147                                         return current.Prefix;\r
148                         }\r
149                 }\r
150 \r
151                 public override bool HasValue {\r
152                         get {\r
153                                 switch (current.NodeType) {\r
154                                 case XPathNodeType.Namespace:\r
155                                 case XPathNodeType.Attribute:\r
156                                 case XPathNodeType.Comment:\r
157                                 case XPathNodeType.ProcessingInstruction:\r
158                                 case XPathNodeType.SignificantWhitespace:\r
159                                 case XPathNodeType.Text:\r
160                                 case XPathNodeType.Whitespace:\r
161                                         return true;\r
162                                 }\r
163                                 return false;\r
164                         }\r
165                 }\r
166 \r
167                 public override int Depth {\r
168                         get {\r
169                                 switch (ReadState) {\r
170                                 case ReadState.EndOfFile:\r
171                                 case ReadState.Initial:\r
172                                 case ReadState.Closed:\r
173                                         return 0;\r
174                                 }\r
175                                 return depth;\r
176                         }\r
177                 }\r
178 \r
179                 public override string Value {\r
180                         get {\r
181                                 switch (current.NodeType) {\r
182                                 case XPathNodeType.Namespace:\r
183                                 case XPathNodeType.Attribute:\r
184                                 case XPathNodeType.Comment:\r
185                                 case XPathNodeType.ProcessingInstruction:\r
186                                 case XPathNodeType.SignificantWhitespace:\r
187                                 case XPathNodeType.Text:\r
188                                 case XPathNodeType.Whitespace:\r
189                                         return current.Value;\r
190                                 case XPathNodeType.Element:\r
191                                 case XPathNodeType.Root:\r
192                                         return String.Empty;\r
193                                 default:\r
194                                         throw new InvalidOperationException ("Current XPathNavigator status is {0} which is not acceptable to XmlReader.");\r
195                                 }\r
196                         }\r
197                 }\r
198 \r
199                 public override string BaseURI {\r
200                         get { return current.BaseURI; }\r
201                 }\r
202 \r
203                 public override bool IsEmptyElement {\r
204                         get { return current.IsEmptyElement; }\r
205                 }\r
206 \r
207                 public override bool IsDefault {\r
208                         get {\r
209                                 IXmlSchemaInfo si = current as IXmlSchemaInfo;\r
210                                 return si != null && si.IsDefault;\r
211                         }\r
212                 }\r
213 \r
214                 // It makes no sense.\r
215                 public override char QuoteChar {\r
216                         get { return '\"'; }\r
217                 }\r
218 \r
219                 public override string XmlLang {\r
220                         get { return current.XmlLang; }\r
221                 }\r
222 \r
223                 // It is meaningless.\r
224                 public override XmlSpace XmlSpace {\r
225                         get { return XmlSpace.None; }\r
226                 }\r
227 \r
228                 public override int AttributeCount {\r
229                         get { return attributeCount; }\r
230                 }\r
231 \r
232                 private int GetAttributeCount ()\r
233                 {\r
234                         int count = 0;\r
235                         if (current.MoveToFirstAttribute ()) {\r
236                                 do {\r
237                                         count++;\r
238                                 } while (current.MoveToNextAttribute ());\r
239                                 current.MoveToParent ();\r
240                         }\r
241                         if (current.MoveToFirstNamespace (XPathNamespaceScope.Local)) {\r
242                                 do {\r
243                                         count++;\r
244                                 } while (current.MoveToNextNamespace (XPathNamespaceScope.Local));\r
245                                 current.MoveToParent ();\r
246                         }\r
247                         return count;\r
248                 }\r
249                 \r
250                 private bool MoveToAttributeNavigator (int i)\r
251                 {\r
252                         switch (current.NodeType) {\r
253                         case XPathNodeType.Namespace:\r
254                         case XPathNodeType.Attribute:\r
255                                 this.MoveToElement ();\r
256                                 goto case XPathNodeType.Element;\r
257                         case XPathNodeType.Element:\r
258                                 int count = 0;\r
259                                 if (MoveToFirstAttribute ()) {\r
260                                         if (i == 0)\r
261                                                 return true;\r
262                                 }\r
263                                 for (count++; this.MoveToNextAttribute (); count++) {\r
264                                         if (count == i)\r
265                                                 return true;\r
266                                 }\r
267                                 break;\r
268                         }\r
269                         return false;\r
270                 }\r
271 \r
272                 public override string this [int i] {\r
273                         get {\r
274                                 XPathNavigator backup = current.Clone ();\r
275                                 try {\r
276                                         if (MoveToAttributeNavigator (i))\r
277                                                 return Value;\r
278                                         else\r
279                                                 throw new ArgumentOutOfRangeException ();\r
280                                 } finally {\r
281                                         current.MoveTo (backup);\r
282                                 }\r
283                         }\r
284                 }\r
285 \r
286                 private void SplitName (string name, out string localName, out string ns)\r
287                 {\r
288                         localName = name;\r
289                         ns = String.Empty;\r
290                         int colon = name.IndexOf (':');\r
291                         if (colon > 0) {\r
292                                 localName = name.Substring (colon + 1, name.Length - colon - 1);\r
293                                 ns = this.LookupNamespace (name.Substring (0, colon));\r
294                         }\r
295                 }\r
296 \r
297                 public override string this [string name] {\r
298                         get {\r
299                                 string localName;\r
300                                 string ns;\r
301                                 SplitName (name, out localName, out ns);\r
302                                 return this [localName, ns];\r
303                         }\r
304                 }\r
305 \r
306                 public override string this [string localName, string namespaceURI] {\r
307                         get {\r
308                                 string v = current.GetAttribute (localName, namespaceURI);\r
309                                 if (v != String.Empty)\r
310                                         return v;\r
311                                 XPathNavigator tmp = current.Clone ();\r
312                                 return tmp.MoveToAttribute (localName, namespaceURI) ? String.Empty : null;\r
313                         }\r
314                 }\r
315 \r
316                 public override bool EOF {\r
317                         get { return ReadState == ReadState.EndOfFile; }\r
318                 }\r
319 \r
320                 public override ReadState ReadState {\r
321                         get {\r
322                                 if (eof)\r
323                                         return ReadState.EndOfFile;\r
324                                 if (closed)\r
325                                         return ReadState.Closed;\r
326                                 else if (!started)\r
327                                         return ReadState.Initial;\r
328                                 return ReadState.Interactive;\r
329                         }\r
330                 }\r
331 \r
332                 public override XmlNameTable NameTable {\r
333                         get { return current.NameTable; }\r
334                 }\r
335                 #endregion\r
336 \r
337                 #region Methods\r
338 \r
339                 public override string GetAttribute (string name)\r
340                 {\r
341                         string localName;\r
342                         string ns;\r
343                         SplitName (name, out localName, out ns);\r
344                         return this [localName, ns];\r
345                 }\r
346 \r
347                 public override string GetAttribute (string localName, string namespaceURI)\r
348                 {\r
349                         return this [localName, namespaceURI];\r
350                 }\r
351 \r
352                 public override string GetAttribute (int i)\r
353                 {\r
354                         return this [i];\r
355                 }\r
356 \r
357                 private bool CheckAttributeMove (bool b)\r
358                 {\r
359                         if (b)\r
360                                 attributeValueConsumed = false;\r
361                         return b;\r
362                 }\r
363 \r
364                 public override bool MoveToAttribute (string name)\r
365                 {\r
366                         string localName;\r
367                         string ns;\r
368                         SplitName (name, out localName, out ns);\r
369                         return CheckAttributeMove (MoveToAttribute (localName, ns));\r
370                 }\r
371 \r
372                 public override bool MoveToAttribute (string localName, string namespaceURI)\r
373                 {\r
374                         XPathNavigator backup = null;\r
375                         switch (current.NodeType) {\r
376                         case XPathNodeType.Attribute:\r
377                                 backup = current.Clone ();\r
378                                 this.MoveToElement ();\r
379                                 goto case XPathNodeType.Element;\r
380                         case XPathNodeType.Element:\r
381                                 while (MoveToNextAttribute ())\r
382                                         if (current.LocalName == localName && current.NamespaceURI == namespaceURI) {\r
383                                                 attributeValueConsumed = false;\r
384                                                 return true;\r
385                                         }\r
386                                 break;\r
387                         }\r
388                         if (backup != null)\r
389                                 current = backup;\r
390                         return false;\r
391                 }\r
392 \r
393                 public override void MoveToAttribute (int i)\r
394                 {\r
395                         if (!MoveToAttributeNavigator (i))\r
396                                 throw new ArgumentOutOfRangeException ();\r
397                 }\r
398 \r
399                 public override bool MoveToFirstAttribute ()\r
400                 {\r
401                         bool b = CheckAttributeMove (current.MoveToFirstNamespace (XPathNamespaceScope.Local));\r
402                         if (b)\r
403                                 return true;\r
404                         return CheckAttributeMove (current.MoveToFirstAttribute ());\r
405                 }\r
406 \r
407                 public override bool MoveToNextAttribute ()\r
408                 {\r
409                         if (current.NodeType == XPathNodeType.Namespace) {\r
410                                 bool b = CheckAttributeMove (current.MoveToNextNamespace (XPathNamespaceScope.Local));\r
411                                 if (b)\r
412                                         return true;\r
413                                 current.MoveToParent ();\r
414                                 b = CheckAttributeMove (current.MoveToFirstAttribute ());\r
415                                 if (b)\r
416                                         return true;\r
417                         }\r
418                         return CheckAttributeMove (current.MoveToNextAttribute ());\r
419                 }\r
420 \r
421                 public override bool MoveToElement ()\r
422                 {\r
423                         if (current.NodeType == XPathNodeType.Attribute ||\r
424                                 current.NodeType == XPathNodeType.Namespace) {\r
425                                 attributeValueConsumed = false;\r
426                                 return current.MoveToParent ();\r
427                         }\r
428                         return false;\r
429                 }\r
430 \r
431                 public override void Close ()\r
432                 {\r
433                         closed = true;\r
434                         eof = true;\r
435                 }\r
436 \r
437                 public override bool Read ()\r
438                 {\r
439                         switch (ReadState) {\r
440                         case ReadState.EndOfFile:\r
441                         case ReadState.Closed:\r
442                         case ReadState.Error:\r
443                                 return false;\r
444                         case ReadState.Initial:\r
445                                 started = true;\r
446                                 switch (current.NodeType) {\r
447                                 case XPathNodeType.Root:\r
448                                         // recurse, but as Interactive\r
449                                         return Read ();\r
450                                 case XPathNodeType.Element:\r
451                                         if (current.IsEmptyElement)\r
452                                                 nextIsEOF = true;\r
453                                         attributeCount = GetAttributeCount ();\r
454                                         return true;\r
455                                 default:\r
456                                         nextIsEOF = true;\r
457                                         return true;\r
458                                 }\r
459                                 break;\r
460                         }\r
461 \r
462                         if (nextIsEOF) {\r
463                                 nextIsEOF = false;\r
464                                 eof = true;\r
465                                 return false;\r
466                         }\r
467 \r
468                         MoveToElement ();\r
469 \r
470                         if (endElement || !current.MoveToFirstChild ()) {\r
471                                 if (current.IsSamePosition (root)) {    // It should happen only when the root node was empty.\r
472                                         eof = true;\r
473                                         return false;\r
474                                 }\r
475                                 if (!current.MoveToNext ()) {\r
476                                         current.MoveToParent ();\r
477                                         depth--;\r
478                                         endElement = (current.NodeType == XPathNodeType.Element);\r
479                                         if (current.IsSamePosition (root)) {\r
480                                                 if (current.NodeType == XPathNodeType.Element)\r
481                                                         nextIsEOF = true;\r
482                                                 else {\r
483                                                         endElement = false;\r
484                                                         eof = true;\r
485                                                         return false;\r
486                                                 }\r
487                                         }\r
488                                 } else\r
489                                         endElement = false;\r
490                         }\r
491                         else if (!endElement)\r
492                                 depth++;\r
493                         attributeCount = GetAttributeCount ();\r
494                         return true;\r
495                 }\r
496 \r
497                 public override string ReadString ()\r
498                 {\r
499                         readStringBuffer.Length = 0;\r
500 \r
501                         switch (NodeType) {\r
502                         default:\r
503                                 return String.Empty;\r
504                         case XmlNodeType.Element:\r
505                                 if (IsEmptyElement)\r
506                                         return String.Empty;\r
507                                 do {\r
508                                         Read ();\r
509                                         switch (NodeType) {\r
510                                         case XmlNodeType.Text:\r
511                                         case XmlNodeType.CDATA:\r
512                                         case XmlNodeType.Whitespace:\r
513                                         case XmlNodeType.SignificantWhitespace:\r
514                                                 readStringBuffer.Append (Value);\r
515                                                 continue;\r
516                                         }\r
517                                         break;\r
518                                 } while (true);\r
519                                 break;\r
520                         case XmlNodeType.Text:\r
521                         case XmlNodeType.CDATA:\r
522                         case XmlNodeType.Whitespace:\r
523                         case XmlNodeType.SignificantWhitespace:\r
524                                 do {\r
525                                         switch (NodeType) {\r
526                                         case XmlNodeType.Text:\r
527                                         case XmlNodeType.CDATA:\r
528                                         case XmlNodeType.Whitespace:\r
529                                         case XmlNodeType.SignificantWhitespace:\r
530                                                 readStringBuffer.Append (Value);\r
531                                                 Read ();\r
532                                                 continue;\r
533                                         }\r
534                                         break;\r
535                                 } while (true);\r
536                                 break;\r
537                         }\r
538                         string ret = readStringBuffer.ToString ();\r
539                         readStringBuffer.Length = 0;\r
540                         return ret;\r
541                 }\r
542 \r
543 #if NET_1_1\r
544 #else\r
545                 public override string ReadInnerXml ()\r
546                 {\r
547                         if (ReadState != ReadState.Interactive)\r
548                                 return String.Empty;\r
549 \r
550                         switch (NodeType) {\r
551                         case XmlNodeType.Attribute:\r
552                                 return Value;\r
553                         case XmlNodeType.Element:\r
554                                 if (IsEmptyElement)\r
555                                         return String.Empty;\r
556 \r
557                                 int startDepth = Depth;\r
558 \r
559                                 innerXmlBuilder.Length = 0;\r
560                                 bool loop = true;\r
561                                 do {\r
562                                         Read ();\r
563                                         if (NodeType ==XmlNodeType.None)\r
564                                                 throw new InvalidOperationException ("unexpected end of xml.");\r
565                                         else if (NodeType == XmlNodeType.EndElement && Depth == startDepth) {\r
566                                                 loop = false;\r
567                                                 Read ();\r
568                                         }\r
569                                         else\r
570                                                 innerXmlBuilder.Append (GetCurrentTagMarkup ());\r
571                                 } while (loop);\r
572                                 string xml = innerXmlBuilder.ToString ();\r
573                                 innerXmlBuilder.Length = 0;\r
574                                 return xml;\r
575                         case XmlNodeType.None:\r
576                                 // MS document is incorrect. Seems not to progress.\r
577                                 return String.Empty;\r
578                         default:\r
579                                 Read ();\r
580                                 return String.Empty;\r
581                         }\r
582                 }\r
583                 \r
584                 StringBuilder atts = new StringBuilder ();\r
585                 private string GetCurrentTagMarkup ()\r
586                 {\r
587                         switch (NodeType) {\r
588                         case XmlNodeType.CDATA:\r
589                                 return String.Format ("<![CDATA[{0}]]>", Value.Replace ("]]>", "]]&gt;"));\r
590                         case XmlNodeType.Text:\r
591                                 return Value.Replace ("<", "&lt;");\r
592                         case XmlNodeType.Comment:\r
593                                 return String.Format ("<!--{0}-->", Value);\r
594                         case XmlNodeType.SignificantWhitespace:\r
595                         case XmlNodeType.Whitespace:\r
596                                 return Value;\r
597                         case XmlNodeType.EndElement:\r
598                                 return String.Format ("</{0}>", Name);\r
599                         }\r
600 \r
601                         bool isEmpty = IsEmptyElement;\r
602                         string name = Name;\r
603                         atts.Length = 0;\r
604                         XPathNavigator temp = current.Clone ();\r
605                         while (temp.MoveToNextAttribute ())\r
606                                 atts.AppendFormat (" {0}='{1}'", temp.Name, temp.Value.Replace ("'", "&apos;"));\r
607                         if (!IsEmptyElement)\r
608                                 return String.Format ("<{0}{1}>", name, atts);\r
609                         else\r
610                                 return String.Format ("<{0}{1} />", name, atts);\r
611                 }\r
612 \r
613                 // Arranged copy of XmlTextReader.ReadOuterXml()\r
614                 public override string ReadOuterXml ()\r
615                 {\r
616                         if (ReadState != ReadState.Interactive)\r
617                                 return String.Empty;\r
618 \r
619                         switch (NodeType) {\r
620                         case XmlNodeType.Attribute:\r
621                                 // strictly incompatible with MS... (it holds spaces attribute between name, value and "=" char (very trivial).\r
622                                 return String.Format ("{0}={1}{2}{1}", Name, QuoteChar, ReadInnerXml ());\r
623                         case XmlNodeType.Element:\r
624                                 bool isEmpty = IsEmptyElement;\r
625                                 string name = Name;\r
626                                 StringBuilder atts = new StringBuilder ();\r
627                                 XPathNavigator temp = current.Clone ();\r
628                                 while (temp.MoveToNextAttribute ())\r
629                                         atts.AppendFormat (" {0}='{1}'", temp.Name, temp.Value.Replace ("'", "&apos;"));\r
630 \r
631                                 if (!isEmpty)\r
632                                         return String.Format ("{0}{1}</{2}>", GetCurrentTagMarkup (), atts, ReadInnerXml (), name);\r
633                                 else\r
634                                         return String.Format ("{0}", GetCurrentTagMarkup ());\r
635                         case XmlNodeType.None:\r
636                                 // MS document is incorrect. Seems not to progress.\r
637                                 return String.Empty;\r
638                         default:\r
639                                 Read ();\r
640                                 return String.Empty;\r
641                         }\r
642                 }\r
643 #endif\r
644 \r
645                 public override string LookupNamespace (string prefix)\r
646                 {\r
647                         XPathNavigator backup = current.Clone ();\r
648                         try {\r
649                                 this.MoveToElement ();\r
650                                 if (current.MoveToFirstNamespace ()) {\r
651                                         do {\r
652                                                 if (current.LocalName == prefix)\r
653                                                         return current.Value;\r
654                                         } while (current.MoveToNextNamespace ());\r
655                                 }\r
656                                 return null;\r
657                         } finally {\r
658                                 current = backup;\r
659                         }\r
660                 }\r
661 \r
662                 // It does not support entity resolution.\r
663                 public override void ResolveEntity ()\r
664                 {\r
665                         throw new InvalidOperationException ();\r
666                 }\r
667 \r
668                 public override bool ReadAttributeValue () {\r
669                         if (NodeType != XmlNodeType.Attribute)\r
670                                 return false;\r
671                         if (attributeValueConsumed)\r
672                                 return false;\r
673                         attributeValueConsumed = true;\r
674                         return true;\r
675                 }\r
676                 #endregion\r
677         }\r
678 }\r
679 \r
680 #endif\r