2010-01-20 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mcs / class / System.XML / Mono.Xml.XPath / XPathEditableDocument.cs
1 //
2 // Mono.Xml.XPath.XPathEditableDocument
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // (C)2004 Novell Inc.
8 //
9 // Yet another implementation of editable XPathNavigator.
10 // (Even runnable under MS.NET 2.0)
11 //
12 // By rewriting XPathEditableDocument.CreateNavigator() as just to 
13 // create XmlDocumentNavigator, XmlDocumentEditableNavigator could be used 
14 // as to implement XmlDocument.CreateNavigator().
15 //
16
17 //
18 // Permission is hereby granted, free of charge, to any person obtaining
19 // a copy of this software and associated documentation files (the
20 // "Software"), to deal in the Software without restriction, including
21 // without limitation the rights to use, copy, modify, merge, publish,
22 // distribute, sublicense, and/or sell copies of the Software, and to
23 // permit persons to whom the Software is furnished to do so, subject to
24 // the following conditions:
25 // 
26 // The above copyright notice and this permission notice shall be
27 // included in all copies or substantial portions of the Software.
28 // 
29 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 //
37 #if NET_2_0
38
39 using System;
40 using System.Collections;
41 using System.ComponentModel;
42 using System.IO;
43 using System.Xml;
44 using System.Xml.Schema;
45 using System.Xml.XPath;
46 using System.Xml.Serialization;
47
48 namespace Mono.Xml.XPath
49 {
50         internal class XPathEditableDocument : IXPathNavigable
51         {
52                 XmlNode node;
53
54                 public XPathEditableDocument (XmlNode node)
55                 {
56                         this.node = node;
57                 }
58
59                 public XmlNode Node {
60                         get { return node; }
61                 }
62
63                 public XPathNavigator CreateNavigator ()
64                 {
65                         return new XmlDocumentEditableNavigator (this);
66                 }
67         }
68
69         internal delegate void XmlWriterClosedEventHandler (
70                 XmlWriter writer);
71
72         internal class XmlDocumentInsertionWriter : XmlWriter
73         {
74                 XmlNode parent;
75                 XmlNode current;
76                 XmlNode nextSibling;
77                 WriteState state;
78                 XmlAttribute attribute;
79
80                 public XmlDocumentInsertionWriter (XmlNode owner, XmlNode nextSibling)
81                 {
82                         this.parent = (XmlNode) owner;
83                         if (parent == null)
84                                 throw new InvalidOperationException ();
85                         switch (parent.NodeType) {
86                         case XmlNodeType.Document:
87                                 current = ((XmlDocument) parent).CreateDocumentFragment ();
88                                 break;
89                         case XmlNodeType.DocumentFragment:
90                         case XmlNodeType.Element:
91                                 current = parent.OwnerDocument.CreateDocumentFragment ();
92                                 break;
93                         default:
94                                 throw new InvalidOperationException (String.Format ("Insertion into {0} node is not allowed.", parent.NodeType));
95                         }
96                         this.nextSibling = nextSibling;
97                         state = WriteState.Content;
98                 }
99
100                 public override WriteState WriteState {
101                         get { return state; }
102                 }
103
104                 public override void Close ()
105                 {
106                         while (current.ParentNode != null)
107                                 current = current.ParentNode;
108
109                         parent.InsertBefore ((XmlDocumentFragment) current, nextSibling);
110                         if (Closed != null)
111                                 Closed (this);
112                 }
113
114                 internal event XmlWriterClosedEventHandler Closed;
115
116                 public override void Flush ()
117                 {
118                 }
119
120                 public override string LookupPrefix (string ns)
121                 {
122                         return current.GetPrefixOfNamespace (ns);
123                 }
124
125                 public override void WriteStartAttribute (string prefix, string name, string ns)
126                 {
127                         if (state != WriteState.Content)
128                                 throw new InvalidOperationException ("Current state is not inside element. Cannot start attribute.");
129                         if (prefix == null && ns != null && ns.Length > 0)
130                                 prefix = LookupPrefix (ns);
131                         attribute = current.OwnerDocument.CreateAttribute (prefix, name, ns);
132                         state = WriteState.Attribute;
133                 }
134
135                 public override void WriteProcessingInstruction (string name, string value)
136                 {
137                         XmlProcessingInstruction pi = current.OwnerDocument.CreateProcessingInstruction (name, value);
138                         current.AppendChild (pi);
139                 }
140
141                 public override void WriteComment (string text)
142                 {
143                         XmlComment comment = current.OwnerDocument.CreateComment (text);
144                         current.AppendChild (comment);
145                 }
146
147                 public override void WriteCData (string text)
148                 {
149                         XmlCDataSection cdata = current.OwnerDocument.CreateCDataSection (text);
150                         current.AppendChild (cdata);
151                 }
152
153                 public override void WriteStartElement (string prefix, string name, string ns)
154                 {
155                         if (prefix == null && ns != null && ns.Length > 0)
156                                 prefix = LookupPrefix (ns);
157                         XmlElement el = current.OwnerDocument.CreateElement (prefix, name, ns);
158                         current.AppendChild (el);
159                         current = el;
160                 }
161
162                 public override void WriteEndElement ()
163                 {
164                         current = current.ParentNode;
165                         if (current == null)
166                                 throw new InvalidOperationException ("No element is opened.");
167                 }
168
169                 public override void WriteFullEndElement ()
170                 {
171                         XmlElement el = current as XmlElement;
172                         if (el != null)
173                                 el.IsEmpty = false;
174                         WriteEndElement ();
175                 }
176
177                 public override void WriteDocType (string name, string pubid, string systemId, string intsubset)
178                 {
179                         throw new NotSupportedException ();
180                 }
181
182                 public override void WriteStartDocument ()
183                 {
184                         throw new NotSupportedException ();
185                 }
186
187                 public override void WriteStartDocument (bool standalone)
188                 {
189                         throw new NotSupportedException ();
190                 }
191
192                 public override void WriteEndDocument ()
193                 {
194                         throw new NotSupportedException ();
195                 }
196
197                 public override void WriteBase64 (byte [] data, int start, int length)
198                 {
199                         WriteString (Convert.ToBase64String (data, start, length));
200                 }
201
202                 public override void WriteRaw (char [] raw, int start, int length)
203                 {
204                         throw new NotSupportedException ();
205                 }
206
207                 public override void WriteRaw (string raw)
208                 {
209                         throw new NotSupportedException ();
210                 }
211
212                 public override void WriteSurrogateCharEntity (char msb, char lsb)
213                 {
214                         throw new NotSupportedException ();
215                 }
216
217                 public override void WriteCharEntity (char c)
218                 {
219                         throw new NotSupportedException ();
220                 }
221
222                 public override void WriteEntityRef (string entname)
223                 {
224                         if (state != WriteState.Attribute)
225                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot write attribute value.");
226                         attribute.AppendChild (attribute.OwnerDocument.CreateEntityReference (entname));
227                 }
228
229                 public override void WriteChars (char [] data, int start, int length)
230                 {
231                         WriteString (new string (data, start, length));
232                 }
233
234                 public override void WriteString (string text)
235                 {
236                         if (attribute != null)
237                                 attribute.Value += text;
238                         else {
239                                 XmlText t = current.OwnerDocument.CreateTextNode (text);
240                                 current.AppendChild (t);
241                         }
242                 }
243
244                 public override void WriteWhitespace (string text)
245                 {
246                         if (state != WriteState.Attribute)
247                                 current.AppendChild (current.OwnerDocument.CreateTextNode (text));
248                         else if (attribute.ChildNodes.Count == 0)
249                                 attribute.AppendChild (attribute.OwnerDocument.CreateWhitespace (text));
250                         else
251                                 attribute.Value += text;
252                 }
253
254                 public override void WriteEndAttribute ()
255                 {
256                         // when the writer is for AppendChild() and the root 
257                         // node is element, it allows to write attributes
258                         // (IMHO incorrectly: isn't it append "child" ???)
259                         XmlElement element = (current as XmlElement) ?? (nextSibling == null ? parent as XmlElement : null);
260                         if (state != WriteState.Attribute || element == null)
261                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot close attribute.");
262                         element.SetAttributeNode (attribute);
263                         attribute = null;
264                         state = WriteState.Content;
265                 }
266         }
267
268         internal class XmlDocumentAttributeWriter : XmlWriter
269         {
270                 XmlElement element;
271                 WriteState state;
272                 XmlAttribute attribute;
273
274                 public XmlDocumentAttributeWriter (XmlNode owner)
275                 {
276                         element = owner as XmlElement;
277                         if (element == null)
278                                 throw new ArgumentException ("To write attributes, current node must be an element.");
279                         state = WriteState.Content;
280                 }
281
282                 public override WriteState WriteState {
283                         get { return state; }
284                 }
285
286                 public override void Close ()
287                 {
288                 }
289
290                 public override void Flush ()
291                 {
292                 }
293
294                 public override string LookupPrefix (string ns)
295                 {
296                         return element.GetPrefixOfNamespace (ns);
297                 }
298
299                 public override void WriteStartAttribute (string prefix, string name, string ns)
300                 {
301                         if (state != WriteState.Content)
302                                 throw new InvalidOperationException ("Current state is not inside element. Cannot start attribute.");
303                         if (prefix == null && ns != null && ns.Length > 0)
304                                 prefix = LookupPrefix (ns);
305                         attribute = element.OwnerDocument.CreateAttribute (prefix, name, ns);
306                         state = WriteState.Attribute;
307                 }
308
309                 public override void WriteProcessingInstruction (string name, string value)
310                 {
311                         throw new NotSupportedException ();
312                 }
313
314                 public override void WriteComment (string text)
315                 {
316                         throw new NotSupportedException ();
317                 }
318
319                 public override void WriteCData (string text)
320                 {
321                         throw new NotSupportedException ();
322                 }
323
324                 public override void WriteStartElement (string prefix, string name, string ns)
325                 {
326                         throw new NotSupportedException ();
327                 }
328
329                 public override void WriteEndElement ()
330                 {
331                         throw new NotSupportedException ();
332                 }
333
334                 public override void WriteFullEndElement ()
335                 {
336                         throw new NotSupportedException ();
337                 }
338
339                 public override void WriteDocType (string name, string pubid, string systemId, string intsubset)
340                 {
341                         throw new NotSupportedException ();
342                 }
343
344                 public override void WriteStartDocument ()
345                 {
346                         throw new NotSupportedException ();
347                 }
348
349                 public override void WriteStartDocument (bool standalone)
350                 {
351                         throw new NotSupportedException ();
352                 }
353
354                 public override void WriteEndDocument ()
355                 {
356                         throw new NotSupportedException ();
357                 }
358
359                 public override void WriteBase64 (byte [] data, int start, int length)
360                 {
361                         throw new NotSupportedException ();
362                 }
363
364                 public override void WriteRaw (char [] raw, int start, int length)
365                 {
366                         throw new NotSupportedException ();
367                 }
368
369                 public override void WriteRaw (string raw)
370                 {
371                         throw new NotSupportedException ();
372                 }
373
374                 public override void WriteSurrogateCharEntity (char msb, char lsb)
375                 {
376                         throw new NotSupportedException ();
377                 }
378
379                 public override void WriteCharEntity (char c)
380                 {
381                         throw new NotSupportedException ();
382                 }
383
384                 public override void WriteEntityRef (string entname)
385                 {
386                         if (state != WriteState.Attribute)
387                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot write attribute value.");
388                         attribute.AppendChild (attribute.OwnerDocument.CreateEntityReference (entname));
389                 }
390
391                 public override void WriteChars (char [] data, int start, int length)
392                 {
393                         WriteString (new string (data, start, length));
394                 }
395
396                 public override void WriteString (string text)
397                 {
398                         if (state != WriteState.Attribute)
399                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot write attribute value.");
400                         attribute.Value += text;
401                 }
402
403                 public override void WriteWhitespace (string text)
404                 {
405                         if (state != WriteState.Attribute)
406                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot write attribute value.");
407                         if (attribute.ChildNodes.Count == 0)
408                                 attribute.AppendChild (attribute.OwnerDocument.CreateWhitespace (text));
409                         else
410                                 attribute.Value += text;
411                 }
412
413                 public override void WriteEndAttribute ()
414                 {
415                         if (state != WriteState.Attribute)
416                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot close attribute.");
417                         element.SetAttributeNode (attribute);
418                         attribute = null;
419                         state = WriteState.Content;
420                 }
421         }
422
423         internal class XmlDocumentEditableNavigator : XPathNavigator, IHasXmlNode
424         {
425                 static readonly bool isXmlDocumentNavigatorImpl;
426                 
427                 static XmlDocumentEditableNavigator ()
428                 {
429                         isXmlDocumentNavigatorImpl =
430                                 (typeof (XmlDocumentEditableNavigator).Assembly 
431                                 == typeof (XmlDocument).Assembly);
432                 }
433
434                 XPathEditableDocument document;
435                 XPathNavigator navigator;
436
437                 public XmlDocumentEditableNavigator (XPathEditableDocument doc)
438                 {
439                         document = doc;
440                         if (isXmlDocumentNavigatorImpl)
441                                 navigator = new XmlDocumentNavigator (doc.Node);
442                         else
443                                 navigator = doc.CreateNavigator ();
444                 }
445
446                 public XmlDocumentEditableNavigator (XmlDocumentEditableNavigator nav)
447                 {
448                         document = nav.document;
449                         navigator = nav.navigator.Clone ();
450                 }
451
452                 public override string BaseURI {
453                         get { return navigator.BaseURI; }
454                 }
455
456                 public override bool CanEdit {
457                         get { return true; }
458                 }
459
460                 public override bool IsEmptyElement {
461                         get { return navigator.IsEmptyElement; }
462                 }
463
464                 public override string LocalName {
465                         get { return navigator.LocalName; }
466                 }
467
468                 public override XmlNameTable NameTable {
469                         get { return navigator.NameTable; }
470                 }
471
472                 public override string Name {
473                         get { return navigator.Name; }
474                 }
475
476                 public override string NamespaceURI {
477                         get { return navigator.NamespaceURI; }
478                 }
479
480                 public override XPathNodeType NodeType {
481                         get { return navigator.NodeType; }
482                 }
483
484                 public override string Prefix {
485                         get { return navigator.Prefix; }
486                 }
487
488                 public override IXmlSchemaInfo SchemaInfo {
489                         get { return navigator.SchemaInfo; }
490                 }
491
492                 public override object UnderlyingObject {
493                         get { return navigator.UnderlyingObject; }
494                 }
495
496                 public override string Value {
497                         get { return navigator.Value; }
498                 }
499
500                 public override string XmlLang {
501                         get { return navigator.XmlLang; }
502                 }
503
504                 public override bool HasChildren {
505                         get { return navigator.HasChildren; }
506                 }
507
508                 public override bool HasAttributes {
509                         get { return navigator.HasAttributes; }
510                 }
511
512                 public override XPathNavigator Clone ()
513                 {
514                         return new XmlDocumentEditableNavigator (this);
515                 }
516
517                 public override XPathNavigator CreateNavigator ()
518                 {
519                         return navigator.Clone ();
520                 }
521
522                 public XmlNode GetNode ()
523                 {
524                         return ((IHasXmlNode) navigator).GetNode ();
525                 }
526
527                 public override bool IsSamePosition (XPathNavigator other)
528                 {
529                         XmlDocumentEditableNavigator nav = other as XmlDocumentEditableNavigator;
530                         if (nav != null)
531                                 return navigator.IsSamePosition (nav.navigator);
532                         else
533                                 return navigator.IsSamePosition (nav);
534                 }
535
536                 public override bool MoveTo (XPathNavigator other)
537                 {
538                         XmlDocumentEditableNavigator nav = other as XmlDocumentEditableNavigator;
539                         if (nav != null)
540                                 return navigator.MoveTo (nav.navigator);
541                         else
542                                 return navigator.MoveTo (nav);
543                 }
544
545                 public override bool MoveToFirstAttribute ()
546                 {
547                         return navigator.MoveToFirstAttribute ();
548                 }
549
550                 public override bool MoveToFirstChild ()
551                 {
552                         return navigator.MoveToFirstChild ();
553                 }
554
555                 public override bool MoveToFirstNamespace (XPathNamespaceScope scope)
556                 {
557                         return navigator.MoveToFirstNamespace (scope);
558                 }
559
560                 public override bool MoveToId (string id)
561                 {
562                         return navigator.MoveToId (id);
563                 }
564
565                 public override bool MoveToNext ()
566                 {
567                         return navigator.MoveToNext ();
568                 }
569
570                 public override bool MoveToNextAttribute ()
571                 {
572                         return navigator.MoveToNextAttribute ();
573                 }
574
575                 public override bool MoveToNextNamespace (XPathNamespaceScope scope)
576                 {
577                         return navigator.MoveToNextNamespace (scope);
578                 }
579
580                 public override bool MoveToParent ()
581                 {
582                         return navigator.MoveToParent ();
583                 }
584
585                 public override bool MoveToPrevious ()
586                 {
587                         return navigator.MoveToPrevious ();
588                 }
589
590                 public override XmlWriter AppendChild ()
591                 {
592                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
593                         if (n == null)
594                                 throw new InvalidOperationException ("Should not happen.");
595                         return new XmlDocumentInsertionWriter (n, null);
596                 }
597
598                 public override void DeleteRange (XPathNavigator lastSiblingToDelete)
599                 {
600                         if (lastSiblingToDelete == null)
601                                 throw new ArgumentNullException ();
602
603                         XmlNode start = ((IHasXmlNode) navigator).GetNode ();
604                         XmlNode end = null;
605                         if (lastSiblingToDelete is IHasXmlNode)
606                                 end = ((IHasXmlNode) lastSiblingToDelete).GetNode ();
607                         // After removal, it moves to parent node.
608                         if (!navigator.MoveToParent ())
609                                 throw new InvalidOperationException ("There is no parent to remove current node.");
610
611                         if (end == null || start.ParentNode != end.ParentNode)
612                                 throw new InvalidOperationException ("Argument XPathNavigator has different parent node.");
613
614                         XmlNode parent = start.ParentNode;
615                         XmlNode next;
616                         bool loop = true;
617                         for (XmlNode n = start; loop; n = next) {
618                                 loop = n != end;
619                                 next = n.NextSibling;
620                                 parent.RemoveChild (n);
621                         }
622                 }
623
624                 public override XmlWriter ReplaceRange (XPathNavigator nav)
625                 {
626                         if (nav == null)
627                                 throw new ArgumentNullException ();
628
629                         XmlNode start = ((IHasXmlNode) navigator).GetNode ();
630                         XmlNode end = null;
631                         if (nav is IHasXmlNode)
632                                 end = ((IHasXmlNode) nav).GetNode ();
633                         if (end == null || start.ParentNode != end.ParentNode)
634                                 throw new InvalidOperationException ("Argument XPathNavigator has different parent node.");
635
636                         XmlDocumentInsertionWriter w =
637                                 (XmlDocumentInsertionWriter) InsertBefore ();
638
639                         // local variables to anonymous delegate
640                         XPathNavigator prev = Clone ();
641                         if (!prev.MoveToPrevious ())
642                                 prev = null;
643                         XPathNavigator parentNav = Clone ();
644                         parentNav.MoveToParent ();
645
646                         w.Closed += delegate (XmlWriter writer) {
647                                 XmlNode parent = start.ParentNode;
648                                 XmlNode next;
649                                 bool loop = true;
650                                 for (XmlNode n = start; loop; n = next) {
651                                         loop = n != end;
652                                         next = n.NextSibling;
653                                         parent.RemoveChild (n);
654                                 }
655                                 if (prev != null) {
656                                         MoveTo (prev);
657                                         MoveToNext ();
658                                 } else {
659                                         MoveTo (parentNav);
660                                         MoveToFirstChild ();
661                                 }
662                         };
663
664                         return w;
665                 }
666
667                 public override XmlWriter InsertBefore ()
668                 {
669                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
670                         return new XmlDocumentInsertionWriter (n.ParentNode, n);
671                 }
672
673                 public override XmlWriter CreateAttributes ()
674                 {
675                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
676                         return new XmlDocumentAttributeWriter (n);
677                 }
678
679                 public override void DeleteSelf ()
680                 {
681                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
682                         XmlAttribute a = n as XmlAttribute;
683                         if (a != null) {
684                                 if (a.OwnerElement == null)
685                                         throw new InvalidOperationException ("This attribute node cannot be removed since it has no owner element.");
686                                 navigator.MoveToParent ();
687                                 a.OwnerElement.RemoveAttributeNode (a);
688                         } else {
689                                 if (n.ParentNode == null)
690                                         throw new InvalidOperationException ("This node cannot be removed since it has no parent.");
691                                 navigator.MoveToParent ();
692                                 n.ParentNode.RemoveChild (n);
693                         }
694                 }
695
696                 public override void ReplaceSelf (XmlReader reader)
697                 {
698                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
699                         XmlNode p = n.ParentNode;
700                         if (p == null)
701                                 throw new InvalidOperationException ("This node cannot be removed since it has no parent.");
702
703                         bool movenext = false;
704                         if (!MoveToPrevious ())
705                                 MoveToParent ();
706                         else
707                                 movenext = true;
708
709                         XmlDocument doc = p.NodeType == XmlNodeType.Document ?
710                                 p as XmlDocument : p.OwnerDocument;
711                         bool error = false;
712                         if (reader.ReadState == ReadState.Initial) {
713                                 reader.Read ();
714                                 if (reader.EOF)
715                                         error = true;
716                                 else
717                                         while (!reader.EOF)
718                                                 p.AppendChild (doc.ReadNode (reader));
719                         } else {
720                                 if (reader.EOF)
721                                         error = true;
722                                 else
723                                         p.AppendChild (doc.ReadNode (reader));
724                         }
725                         if (error)
726                                 throw new InvalidOperationException ("Content is required in argument XmlReader to replace current node.");
727
728                         p.RemoveChild (n);
729
730                         if (movenext)
731                                 MoveToNext ();
732                         else
733                                 MoveToFirstChild ();
734                 }
735
736                 public override void SetValue (string value)
737                 {
738                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
739                         while (n.FirstChild != null)
740                                 n.RemoveChild (n.FirstChild);
741                         n.InnerText = value;
742                 }
743
744                 public override void MoveToRoot ()
745                 {
746                         navigator.MoveToRoot ();
747                 }
748
749                 public override bool MoveToNamespace (string name)
750                 {
751                         return navigator.MoveToNamespace (name);
752                 }
753
754                 public override bool MoveToFirst ()
755                 {
756                         return navigator.MoveToFirst ();
757                 }
758
759                 public override bool MoveToAttribute (string localName, string namespaceURI)
760                 {
761                         return navigator.MoveToAttribute (localName, namespaceURI);
762                 }
763
764                 public override bool IsDescendant (XPathNavigator nav)
765                 {
766                         XmlDocumentEditableNavigator e = nav as XmlDocumentEditableNavigator;
767                         if (e != null)
768                                 return navigator.IsDescendant (e.navigator);
769                         else
770                                 return navigator.IsDescendant (nav);
771                 }
772
773                 public override string GetNamespace (string name)
774                 {
775                         return navigator.GetNamespace (name);
776                 }
777
778                 public override string GetAttribute (string localName, string namespaceURI)
779                 {
780                         return navigator.GetAttribute (localName, namespaceURI);
781                 }
782
783                 public override XmlNodeOrder ComparePosition (XPathNavigator nav)
784                 {
785                         XmlDocumentEditableNavigator e = nav as XmlDocumentEditableNavigator;
786                         if (e != null)
787                                 return navigator.ComparePosition (e.navigator);
788                         else
789                                 return navigator.ComparePosition (nav);
790                 }
791         }
792 }
793
794 #endif