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