3e2f3689373c50c1669decf5754c1e5bec80e53b
[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                         XmlReader reader = new XmlTextReader(new System.IO.StringReader(raw));
210                         WriteRaw(reader);
211                 }
212
213                 private void WriteRaw(XmlReader reader)
214                 {
215                         if (reader != null && reader.NodeType == XmlNodeType.Element)
216                         {
217                                 WriteStartElement (reader.Prefix, reader.LocalName, reader.NamespaceURI);
218                                 WriteAttributes (reader, true);
219                                 WriteRaw (reader.ReadSubtree ());
220                                 WriteEndElement ();
221
222                         }
223                 }
224
225                 public override void WriteSurrogateCharEntity (char msb, char lsb)
226                 {
227                         throw new NotSupportedException ();
228                 }
229
230                 public override void WriteCharEntity (char c)
231                 {
232                         throw new NotSupportedException ();
233                 }
234
235                 public override void WriteEntityRef (string entname)
236                 {
237                         if (state != WriteState.Attribute)
238                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot write attribute value.");
239                         attribute.AppendChild (attribute.OwnerDocument.CreateEntityReference (entname));
240                 }
241
242                 public override void WriteChars (char [] data, int start, int length)
243                 {
244                         WriteString (new string (data, start, length));
245                 }
246
247                 public override void WriteString (string text)
248                 {
249                         if (attribute != null)
250                                 attribute.Value += text;
251                         else {
252                                 XmlText t = current.OwnerDocument.CreateTextNode (text);
253                                 current.AppendChild (t);
254                         }
255                 }
256
257                 public override void WriteWhitespace (string text)
258                 {
259                         if (state != WriteState.Attribute)
260                                 current.AppendChild (current.OwnerDocument.CreateTextNode (text));
261                         else if (attribute.ChildNodes.Count == 0)
262                                 attribute.AppendChild (attribute.OwnerDocument.CreateWhitespace (text));
263                         else
264                                 attribute.Value += text;
265                 }
266
267                 public override void WriteEndAttribute ()
268                 {
269                         // when the writer is for AppendChild() and the root 
270                         // node is element, it allows to write attributes
271                         // (IMHO incorrectly: isn't it append "child" ???)
272                         XmlElement element = (current as XmlElement) ?? (nextSibling == null ? parent as XmlElement : null);
273                         if (state != WriteState.Attribute || element == null)
274                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot close attribute.");
275                         element.SetAttributeNode (attribute);
276                         attribute = null;
277                         state = WriteState.Content;
278                 }
279         }
280
281         internal class XmlDocumentAttributeWriter : XmlWriter
282         {
283                 XmlElement element;
284                 WriteState state;
285                 XmlAttribute attribute;
286
287                 public XmlDocumentAttributeWriter (XmlNode owner)
288                 {
289                         element = owner as XmlElement;
290                         if (element == null)
291                                 throw new ArgumentException ("To write attributes, current node must be an element.");
292                         state = WriteState.Content;
293                 }
294
295                 public override WriteState WriteState {
296                         get { return state; }
297                 }
298
299                 public override void Close ()
300                 {
301                 }
302
303                 public override void Flush ()
304                 {
305                 }
306
307                 public override string LookupPrefix (string ns)
308                 {
309                         return element.GetPrefixOfNamespace (ns);
310                 }
311
312                 public override void WriteStartAttribute (string prefix, string name, string ns)
313                 {
314                         if (state != WriteState.Content)
315                                 throw new InvalidOperationException ("Current state is not inside element. Cannot start attribute.");
316                         if (prefix == null && ns != null && ns.Length > 0)
317                                 prefix = LookupPrefix (ns);
318                         attribute = element.OwnerDocument.CreateAttribute (prefix, name, ns);
319                         state = WriteState.Attribute;
320                 }
321
322                 public override void WriteProcessingInstruction (string name, string value)
323                 {
324                         throw new NotSupportedException ();
325                 }
326
327                 public override void WriteComment (string text)
328                 {
329                         throw new NotSupportedException ();
330                 }
331
332                 public override void WriteCData (string text)
333                 {
334                         throw new NotSupportedException ();
335                 }
336
337                 public override void WriteStartElement (string prefix, string name, string ns)
338                 {
339                         throw new NotSupportedException ();
340                 }
341
342                 public override void WriteEndElement ()
343                 {
344                         throw new NotSupportedException ();
345                 }
346
347                 public override void WriteFullEndElement ()
348                 {
349                         throw new NotSupportedException ();
350                 }
351
352                 public override void WriteDocType (string name, string pubid, string systemId, string intsubset)
353                 {
354                         throw new NotSupportedException ();
355                 }
356
357                 public override void WriteStartDocument ()
358                 {
359                         throw new NotSupportedException ();
360                 }
361
362                 public override void WriteStartDocument (bool standalone)
363                 {
364                         throw new NotSupportedException ();
365                 }
366
367                 public override void WriteEndDocument ()
368                 {
369                         throw new NotSupportedException ();
370                 }
371
372                 public override void WriteBase64 (byte [] data, int start, int length)
373                 {
374                         throw new NotSupportedException ();
375                 }
376
377                 public override void WriteRaw (char [] raw, int start, int length)
378                 {
379                         throw new NotSupportedException ();
380                 }
381
382                 public override void WriteRaw (string raw)
383                 {
384                         throw new NotSupportedException ();
385                 }
386
387                 public override void WriteSurrogateCharEntity (char msb, char lsb)
388                 {
389                         throw new NotSupportedException ();
390                 }
391
392                 public override void WriteCharEntity (char c)
393                 {
394                         throw new NotSupportedException ();
395                 }
396
397                 public override void WriteEntityRef (string entname)
398                 {
399                         if (state != WriteState.Attribute)
400                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot write attribute value.");
401                         attribute.AppendChild (attribute.OwnerDocument.CreateEntityReference (entname));
402                 }
403
404                 public override void WriteChars (char [] data, int start, int length)
405                 {
406                         WriteString (new string (data, start, length));
407                 }
408
409                 public override void WriteString (string text)
410                 {
411                         if (state != WriteState.Attribute)
412                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot write attribute value.");
413                         attribute.Value += text;
414                 }
415
416                 public override void WriteWhitespace (string text)
417                 {
418                         if (state != WriteState.Attribute)
419                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot write attribute value.");
420                         if (attribute.ChildNodes.Count == 0)
421                                 attribute.AppendChild (attribute.OwnerDocument.CreateWhitespace (text));
422                         else
423                                 attribute.Value += text;
424                 }
425
426                 public override void WriteEndAttribute ()
427                 {
428                         if (state != WriteState.Attribute)
429                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot close attribute.");
430                         element.SetAttributeNode (attribute);
431                         attribute = null;
432                         state = WriteState.Content;
433                 }
434         }
435
436         internal class XmlDocumentEditableNavigator : XPathNavigator, IHasXmlNode
437         {
438                 static readonly bool isXmlDocumentNavigatorImpl;
439                 
440                 static XmlDocumentEditableNavigator ()
441                 {
442                         isXmlDocumentNavigatorImpl =
443                                 (typeof (XmlDocumentEditableNavigator).Assembly 
444                                 == typeof (XmlDocument).Assembly);
445                 }
446
447                 XPathEditableDocument document;
448                 XPathNavigator navigator;
449
450                 public XmlDocumentEditableNavigator (XPathEditableDocument doc)
451                 {
452                         document = doc;
453                         if (isXmlDocumentNavigatorImpl)
454                                 navigator = new XmlDocumentNavigator (doc.Node);
455                         else
456                                 navigator = doc.CreateNavigator ();
457                 }
458
459                 public XmlDocumentEditableNavigator (XmlDocumentEditableNavigator nav)
460                 {
461                         document = nav.document;
462                         navigator = nav.navigator.Clone ();
463                 }
464
465                 public override string BaseURI {
466                         get { return navigator.BaseURI; }
467                 }
468
469                 public override bool CanEdit {
470                         get { return true; }
471                 }
472
473                 public override bool IsEmptyElement {
474                         get { return navigator.IsEmptyElement; }
475                 }
476
477                 public override string LocalName {
478                         get { return navigator.LocalName; }
479                 }
480
481                 public override XmlNameTable NameTable {
482                         get { return navigator.NameTable; }
483                 }
484
485                 public override string Name {
486                         get { return navigator.Name; }
487                 }
488
489                 public override string NamespaceURI {
490                         get { return navigator.NamespaceURI; }
491                 }
492
493                 public override XPathNodeType NodeType {
494                         get { return navigator.NodeType; }
495                 }
496
497                 public override string Prefix {
498                         get { return navigator.Prefix; }
499                 }
500
501                 public override IXmlSchemaInfo SchemaInfo {
502                         get { return navigator.SchemaInfo; }
503                 }
504
505                 public override object UnderlyingObject {
506                         get { return navigator.UnderlyingObject; }
507                 }
508
509                 public override string Value {
510                         get { return navigator.Value; }
511                 }
512
513                 public override string XmlLang {
514                         get { return navigator.XmlLang; }
515                 }
516
517                 public override bool HasChildren {
518                         get { return navigator.HasChildren; }
519                 }
520
521                 public override bool HasAttributes {
522                         get { return navigator.HasAttributes; }
523                 }
524
525                 public override XPathNavigator Clone ()
526                 {
527                         return new XmlDocumentEditableNavigator (this);
528                 }
529
530                 public override XPathNavigator CreateNavigator ()
531                 {
532                         return navigator.Clone ();
533                 }
534
535                 public XmlNode GetNode ()
536                 {
537                         return ((IHasXmlNode) navigator).GetNode ();
538                 }
539
540                 public override bool IsSamePosition (XPathNavigator other)
541                 {
542                         XmlDocumentEditableNavigator nav = other as XmlDocumentEditableNavigator;
543                         if (nav != null)
544                                 return navigator.IsSamePosition (nav.navigator);
545                         else
546                                 return navigator.IsSamePosition (nav);
547                 }
548
549                 public override bool MoveTo (XPathNavigator other)
550                 {
551                         XmlDocumentEditableNavigator nav = other as XmlDocumentEditableNavigator;
552                         if (nav != null)
553                                 return navigator.MoveTo (nav.navigator);
554                         else
555                                 return navigator.MoveTo (nav);
556                 }
557
558                 public override bool MoveToFirstAttribute ()
559                 {
560                         return navigator.MoveToFirstAttribute ();
561                 }
562
563                 public override bool MoveToFirstChild ()
564                 {
565                         return navigator.MoveToFirstChild ();
566                 }
567
568                 public override bool MoveToFirstNamespace (XPathNamespaceScope scope)
569                 {
570                         return navigator.MoveToFirstNamespace (scope);
571                 }
572
573                 public override bool MoveToId (string id)
574                 {
575                         return navigator.MoveToId (id);
576                 }
577
578                 public override bool MoveToNext ()
579                 {
580                         return navigator.MoveToNext ();
581                 }
582
583                 public override bool MoveToNextAttribute ()
584                 {
585                         return navigator.MoveToNextAttribute ();
586                 }
587
588                 public override bool MoveToNextNamespace (XPathNamespaceScope scope)
589                 {
590                         return navigator.MoveToNextNamespace (scope);
591                 }
592
593                 public override bool MoveToParent ()
594                 {
595                         return navigator.MoveToParent ();
596                 }
597
598                 public override bool MoveToPrevious ()
599                 {
600                         return navigator.MoveToPrevious ();
601                 }
602
603                 public override XmlWriter AppendChild ()
604                 {
605                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
606                         if (n == null)
607                                 throw new InvalidOperationException ("Should not happen.");
608                         return new XmlDocumentInsertionWriter (n, null);
609                 }
610
611                 public override void DeleteRange (XPathNavigator lastSiblingToDelete)
612                 {
613                         if (lastSiblingToDelete == null)
614                                 throw new ArgumentNullException ();
615
616                         XmlNode start = ((IHasXmlNode) navigator).GetNode ();
617                         XmlNode end = null;
618                         if (lastSiblingToDelete is IHasXmlNode)
619                                 end = ((IHasXmlNode) lastSiblingToDelete).GetNode ();
620                         // After removal, it moves to parent node.
621                         if (!navigator.MoveToParent ())
622                                 throw new InvalidOperationException ("There is no parent to remove current node.");
623
624                         if (end == null || start.ParentNode != end.ParentNode)
625                                 throw new InvalidOperationException ("Argument XPathNavigator has different parent node.");
626
627                         XmlNode parent = start.ParentNode;
628                         XmlNode next;
629                         bool loop = true;
630                         for (XmlNode n = start; loop; n = next) {
631                                 loop = n != end;
632                                 next = n.NextSibling;
633                                 parent.RemoveChild (n);
634                         }
635                 }
636
637                 public override XmlWriter ReplaceRange (XPathNavigator nav)
638                 {
639                         if (nav == null)
640                                 throw new ArgumentNullException ();
641
642                         XmlNode start = ((IHasXmlNode) navigator).GetNode ();
643                         XmlNode end = null;
644                         if (nav is IHasXmlNode)
645                                 end = ((IHasXmlNode) nav).GetNode ();
646                         if (end == null || start.ParentNode != end.ParentNode)
647                                 throw new InvalidOperationException ("Argument XPathNavigator has different parent node.");
648
649                         XmlDocumentInsertionWriter w =
650                                 (XmlDocumentInsertionWriter) InsertBefore ();
651
652                         // local variables to anonymous delegate
653                         XPathNavigator prev = Clone ();
654                         if (!prev.MoveToPrevious ())
655                                 prev = null;
656                         XPathNavigator parentNav = Clone ();
657                         parentNav.MoveToParent ();
658
659                         w.Closed += delegate (XmlWriter writer) {
660                                 XmlNode parent = start.ParentNode;
661                                 XmlNode next;
662                                 bool loop = true;
663                                 for (XmlNode n = start; loop; n = next) {
664                                         loop = n != end;
665                                         next = n.NextSibling;
666                                         parent.RemoveChild (n);
667                                 }
668                                 if (prev != null) {
669                                         MoveTo (prev);
670                                         MoveToNext ();
671                                 } else {
672                                         MoveTo (parentNav);
673                                         MoveToFirstChild ();
674                                 }
675                         };
676
677                         return w;
678                 }
679
680                 public override XmlWriter InsertBefore ()
681                 {
682                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
683                         return new XmlDocumentInsertionWriter (n.ParentNode, n);
684                 }
685
686                 public override XmlWriter CreateAttributes ()
687                 {
688                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
689                         return new XmlDocumentAttributeWriter (n);
690                 }
691
692                 public override void DeleteSelf ()
693                 {
694                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
695                         XmlAttribute a = n as XmlAttribute;
696                         if (a != null) {
697                                 if (a.OwnerElement == null)
698                                         throw new InvalidOperationException ("This attribute node cannot be removed since it has no owner element.");
699                                 navigator.MoveToParent ();
700                                 a.OwnerElement.RemoveAttributeNode (a);
701                         } else {
702                                 if (n.ParentNode == null)
703                                         throw new InvalidOperationException ("This node cannot be removed since it has no parent.");
704                                 navigator.MoveToParent ();
705                                 n.ParentNode.RemoveChild (n);
706                         }
707                 }
708
709                 public override void ReplaceSelf (XmlReader reader)
710                 {
711                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
712                         XmlNode p = n.ParentNode;
713                         if (p == null)
714                                 throw new InvalidOperationException ("This node cannot be removed since it has no parent.");
715
716                         bool movenext = false;
717                         if (!MoveToPrevious ())
718                                 MoveToParent ();
719                         else
720                                 movenext = true;
721
722                         XmlDocument doc = p.NodeType == XmlNodeType.Document ?
723                                 p as XmlDocument : p.OwnerDocument;
724                         bool error = false;
725                         if (reader.ReadState == ReadState.Initial) {
726                                 reader.Read ();
727                                 if (reader.EOF)
728                                         error = true;
729                                 else
730                                         while (!reader.EOF)
731                                                 p.AppendChild (doc.ReadNode (reader));
732                         } else {
733                                 if (reader.EOF)
734                                         error = true;
735                                 else
736                                         p.AppendChild (doc.ReadNode (reader));
737                         }
738                         if (error)
739                                 throw new InvalidOperationException ("Content is required in argument XmlReader to replace current node.");
740
741                         p.RemoveChild (n);
742
743                         if (movenext)
744                                 MoveToNext ();
745                         else
746                                 MoveToFirstChild ();
747                 }
748
749                 public override void SetValue (string value)
750                 {
751                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
752                         while (n.FirstChild != null)
753                                 n.RemoveChild (n.FirstChild);
754                         n.InnerText = value;
755                 }
756
757                 public override void MoveToRoot ()
758                 {
759                         navigator.MoveToRoot ();
760                 }
761
762                 public override bool MoveToNamespace (string name)
763                 {
764                         return navigator.MoveToNamespace (name);
765                 }
766
767                 public override bool MoveToFirst ()
768                 {
769                         return navigator.MoveToFirst ();
770                 }
771
772                 public override bool MoveToAttribute (string localName, string namespaceURI)
773                 {
774                         return navigator.MoveToAttribute (localName, namespaceURI);
775                 }
776
777                 public override bool IsDescendant (XPathNavigator nav)
778                 {
779                         XmlDocumentEditableNavigator e = nav as XmlDocumentEditableNavigator;
780                         if (e != null)
781                                 return navigator.IsDescendant (e.navigator);
782                         else
783                                 return navigator.IsDescendant (nav);
784                 }
785
786                 public override string GetNamespace (string name)
787                 {
788                         return navigator.GetNamespace (name);
789                 }
790
791                 public override string GetAttribute (string localName, string namespaceURI)
792                 {
793                         return navigator.GetAttribute (localName, namespaceURI);
794                 }
795
796                 public override XmlNodeOrder ComparePosition (XPathNavigator nav)
797                 {
798                         XmlDocumentEditableNavigator e = nav as XmlDocumentEditableNavigator;
799                         if (e != null)
800                                 return navigator.ComparePosition (e.navigator);
801                         else
802                                 return navigator.ComparePosition (nav);
803                 }
804         }
805 }
806
807 #endif