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