2005-05-05 Atsushi Enomoto <atsushi@ximian.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                 /*
53                 public static void Main ()
54                 {
55                         try {
56 #if true
57                                 XmlDocument doc = new XmlDocument ();
58                                 XPathEditableDocument pd = new XPathEditableDocument (doc);
59                                 XPathNavigator nav = pd.CreateNavigator ();
60                                 IChangeTracking xp = pd;
61 #else
62                                 XPathDocument doc = new XPathDocument ();
63                                 XPathNavigator nav = doc.CreateNavigator ();
64                                 IChangeTracking xp = doc;
65 #endif
66                                 doc.LoadXml ("<root/>");
67                                 nav.MoveToFirstChild (); // root
68                                 XmlWriter w = nav.AppendChild ();
69                                 Console.WriteLine (((IChangeTracking) xp).IsChanged);
70                                 w.WriteElementString ("foo", "foo_text");
71                                 w.WriteElementString ("bar", "bar_text");
72                                 w.WriteStartElement ("hoge");
73                                 w.WriteAttributeString ("fuga", "fugafuga");
74                                 w.WriteAttributeString ("unya", "unyaunya");
75                                 w.WriteFullEndElement ();
76                                 w.Close ();
77
78                                 w = nav.CreateAttributes ();
79                                 w.WriteStartAttribute ("namara");
80                                 w.WriteString ("mokera");
81                                 w.WriteEndAttribute ();
82                                 w.WriteAttributeString ("beccho", "giccho");
83                                 w.Close ();
84
85                                 nav.MoveToRoot ();
86                                 nav.MoveToFirstChild ();
87                                 nav.MoveToFirstChild ();
88                                 nav.DeleteSelf (); // delete foo
89                                 Console.WriteLine (nav.Name);
90                                 nav.MoveToNext ();
91                                 Console.WriteLine (nav.Name);
92                                 Console.WriteLine (nav.MoveToFirstAttribute ());
93                                 nav.DeleteSelf (); // delete fuga
94
95                                 doc.Save (Console.Out);
96                         } catch (Exception ex) {
97                                 Console.WriteLine (ex);
98                         }
99                 }
100                 */
101
102                 XmlNode node;
103
104                 ArrayList changes = new ArrayList ();
105
106                 public XPathEditableDocument (XmlNode node)
107                 {
108                         this.node = node;
109                 }
110
111                 public virtual bool CanEdit {
112                         get { return true; }
113                 }
114
115                 public XmlNode Node {
116                         get { return node; }
117                 }
118
119                 public XPathNavigator CreateNavigator ()
120                 {
121                         return new XmlDocumentEditableNavigator (this);
122                 }
123
124                 public XmlWriter CreateWriter ()
125                 {
126                         return CreateNavigator ().AppendChild ();
127                 }
128
129                 public bool HasChanges ()
130                 {
131                         return IsChanged;
132                 }
133
134                 #region IRevertibleChangeTracking/IChangeTracking
135                 public bool IsChanged {
136                         get { return changes.Count != 0; }
137                 }
138
139                 public void AcceptChanges ()
140                 {
141                         changes.Clear ();
142                 }
143
144                 public void RejectChanges ()
145                 {
146                         for (int i = changes.Count - 1; i >= 0; i--) {
147                                 Insertion ins = changes [i] as Insertion;
148                                 if (ins != null) {
149                                         ins.ParentNode.RemoveChild (ins.InsertedNode);
150                                         continue;
151                                 }
152                                 
153                                 Removal rem = changes [i] as Removal;
154                                 if (rem != null) {
155                                         if (rem.RemovedNode.NodeType == XmlNodeType.Attribute) {
156                                                 XmlElement el = (XmlElement) rem.OwnerNode;
157                                                 el.SetAttributeNode ((XmlAttribute) rem.RemovedNode);
158                                         }
159                                         else
160                                                 rem.OwnerNode.InsertBefore (rem.RemovedNode, rem.NextSibling);
161                                         continue;
162                                 }
163                                 AttributeUpdate au = changes [i] as AttributeUpdate;
164                                 if (au != null) {
165                                         if (au.OldAttribute != null)
166                                                 au.Element.SetAttributeNode (au.OldAttribute);
167                                         else
168                                                 au.Element.RemoveAttributeNode (au.NewAttribute);
169                                         continue;
170                                 }
171                         }
172                         changes.Clear ();
173                 }
174                 #endregion
175
176                 #region IXmlSerializable
177                 public void WriteXml (XmlWriter writer)
178                 {
179                         throw new NotImplementedException ();
180                 }
181
182                 public void ReadXml (XmlReader reader)
183                 {
184                         throw new NotImplementedException ();
185                 }
186
187                 public XmlSchema GetSchema ()
188                 {
189                         throw new NotImplementedException ();
190                 }
191                 #endregion
192
193                 internal bool DeleteNode (XmlNode node)
194                 {
195                         Removal rem = new Removal ();
196                         if (node.NodeType == XmlNodeType.Attribute) {
197                                 XmlAttribute attr = node as XmlAttribute;
198                                 rem.OwnerNode = attr.OwnerElement;
199                                 rem.RemovedNode = node;
200                                 attr.OwnerElement.RemoveAttributeNode (attr);
201                                 return false;
202                         } else {
203                                 rem.OwnerNode = node.ParentNode;
204                                 rem.NextSibling = node.NextSibling;
205                                 rem.RemovedNode = node;
206                                 node.ParentNode.RemoveChild (node);
207                                 return rem.NextSibling != null;
208                         }
209                 }
210
211                 internal XmlWriter CreateInsertionWriter (XmlNode owner, XmlNode previousSibling)
212                 {
213                         return new XmlDocumentInsertionWriter (owner, previousSibling, this);
214                 }
215
216                 internal XmlWriter CreateAttributesWriter (XmlNode owner)
217                 {
218                         return new XmlDocumentAttributeWriter (owner, this);
219                 }
220
221                 internal void AttributeUpdate (XmlElement element, XmlAttribute oldAttr, XmlAttribute newAttr)
222                 {
223                         AttributeUpdate au = new AttributeUpdate ();
224                         au.Element = element;
225                         au.OldAttribute = oldAttr;
226                         au.NewAttribute = newAttr;
227                         changes.Add (au);
228                 }
229                 
230                 internal void AppendChild (XmlNode parent, XmlNode child)
231                 {
232                         Insertion ins = new Insertion ();
233                         ins.ParentNode = parent;
234                         ins.InsertedNode = child;
235                         changes.Add (ins);
236                 }
237         }
238
239         internal class XmlDocumentInsertionWriter : XmlWriter
240         {
241                 XmlNode current;
242                 XmlNode previousSibling;
243                 XPathEditableDocument document;
244                 Stack nodeStack = new Stack ();
245
246                 public XmlDocumentInsertionWriter (XmlNode owner, XmlNode previousSibling, XPathEditableDocument doc)
247                 {
248                         this.current = (XmlNode) owner;
249                         if (current == null)
250                                 throw new InvalidOperationException ();
251                         this.previousSibling = previousSibling;
252                         this.document = doc;
253                         state = WriteState.Content;
254                 }
255
256                 WriteState state;
257                 XmlAttribute attribute;
258
259                 public override WriteState WriteState {
260                         get { return state; }
261                 }
262
263                 public override void Close ()
264                 {
265                 }
266
267                 public override void Flush ()
268                 {
269                 }
270
271                 public override string LookupPrefix (string ns)
272                 {
273                         return current.GetPrefixOfNamespace (ns);
274                 }
275
276                 public override void WriteStartAttribute (string prefix, string name, string ns)
277                 {
278                         if (state != WriteState.Content)
279                                 throw new InvalidOperationException ("Current state is not inside element. Cannot start attribute.");
280                         attribute = current.OwnerDocument.CreateAttribute (prefix, name, ns);
281                         state = WriteState.Attribute;
282                 }
283
284                 public override void WriteProcessingInstruction (string name, string value)
285                 {
286                         XmlProcessingInstruction pi = current.OwnerDocument.CreateProcessingInstruction (name, value);
287                         current.AppendChild (pi);
288                         document.AppendChild (current, pi);
289                 }
290
291                 public override void WriteComment (string text)
292                 {
293                         XmlComment comment = current.OwnerDocument.CreateComment (text);
294                         current.AppendChild (comment);
295                         document.AppendChild (current, comment);
296                 }
297
298                 public override void WriteCData (string text)
299                 {
300                         XmlCDataSection cdata = current.OwnerDocument.CreateCDataSection (text);
301                         current.AppendChild (cdata);
302                         document.AppendChild (current, cdata);
303                 }
304
305                 public override void WriteStartElement (string prefix, string name, string ns)
306                 {
307                         XmlDocument doc = current.OwnerDocument;
308                         if (doc == null)
309                                 doc = current as XmlDocument;
310                         if (doc == null)
311                                 throw new SystemException ("Should not happen.");
312                         XmlElement el = doc.CreateElement (prefix, name, ns);
313                         current.AppendChild (el);
314                         document.AppendChild (current, el);
315                         nodeStack.Push (current);
316                         current = el;
317                 }
318
319                 public override void WriteEndElement ()
320                 {
321                         if (nodeStack.Count == 0)
322                                 throw new InvalidOperationException ("No element is opened.");
323                         current = nodeStack.Pop () as XmlNode;
324                 }
325
326                 public override void WriteFullEndElement ()
327                 {
328                         WriteEndElement ();
329                         XmlElement el = current as XmlElement;
330                         if (el != null)
331                                 el.IsEmpty = false;
332                 }
333
334                 public override void WriteDocType (string name, string pubid, string systemId, string intsubset)
335                 {
336                         throw new NotSupportedException ();
337                 }
338
339                 public override void WriteStartDocument ()
340                 {
341                         throw new NotSupportedException ();
342                 }
343
344                 public override void WriteStartDocument (bool standalone)
345                 {
346                         throw new NotSupportedException ();
347                 }
348
349                 public override void WriteEndDocument ()
350                 {
351                         throw new NotSupportedException ();
352                 }
353
354                 public override void WriteBase64 (byte [] data, int start, int length)
355                 {
356                         WriteString (Convert.ToBase64String (data, start, length));
357                 }
358
359                 public override void WriteRaw (char [] raw, int start, int length)
360                 {
361                         throw new NotSupportedException ();
362                 }
363
364                 public override void WriteRaw (string raw)
365                 {
366                         throw new NotSupportedException ();
367                 }
368
369                 public override void WriteSurrogateCharEntity (char msb, char lsb)
370                 {
371                         throw new NotSupportedException ();
372                 }
373
374                 public override void WriteCharEntity (char c)
375                 {
376                         throw new NotSupportedException ();
377                 }
378
379                 public override void WriteEntityRef (string entname)
380                 {
381                         if (state != WriteState.Attribute)
382                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot write attribute value.");
383                         attribute.AppendChild (attribute.OwnerDocument.CreateEntityReference (entname));
384                 }
385
386                 public override void WriteChars (char [] data, int start, int length)
387                 {
388                         WriteString (new string (data, start, length));
389                 }
390
391                 public override void WriteString (string text)
392                 {
393                         if (attribute != null)
394                                 attribute.Value += text;
395                         else {
396                                 XmlText t = current.OwnerDocument.CreateTextNode (text);
397                                 current.AppendChild (t);
398                                 document.AppendChild (current, t);
399                         }
400                 }
401
402                 public override void WriteWhitespace (string text)
403                 {
404                         if (state != WriteState.Attribute)
405                                 current.AppendChild (current.OwnerDocument.CreateTextNode (text));
406                         else if (attribute.ChildNodes.Count == 0)
407                                 attribute.AppendChild (attribute.OwnerDocument.CreateWhitespace (text));
408                         else
409                                 attribute.Value += text;
410                 }
411
412                 public override void WriteEndAttribute ()
413                 {
414                         XmlElement element = current as XmlElement;
415                         if (state != WriteState.Attribute || element == null)
416                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot close attribute.");
417                         document.AttributeUpdate (element, element.SetAttributeNode (attribute), attribute);
418                         attribute = null;
419                         state = WriteState.Content;
420                 }
421         }
422
423         internal class XmlDocumentAttributeWriter : XmlWriter
424         {
425                 XmlElement element;
426                 XPathEditableDocument document;
427
428                 public XmlDocumentAttributeWriter (XmlNode owner, XPathEditableDocument doc)
429                 {
430                         element = owner as XmlElement;
431                         if (element == null)
432                                 throw new ArgumentException ("To write attributes, current node must be an element.");
433                         state = WriteState.Content;
434                         document = doc;
435                 }
436
437                 WriteState state;
438                 XmlAttribute attribute;
439
440                 public override WriteState WriteState {
441                         get { return state; }
442                 }
443
444                 public override void Close ()
445                 {
446                 }
447
448                 public override void Flush ()
449                 {
450                 }
451
452                 public override string LookupPrefix (string ns)
453                 {
454                         return element.GetPrefixOfNamespace (ns);
455                 }
456
457                 public override void WriteStartAttribute (string prefix, string name, string ns)
458                 {
459                         if (state != WriteState.Content)
460                                 throw new InvalidOperationException ("Current state is not inside element. Cannot start attribute.");
461                         attribute = element.OwnerDocument.CreateAttribute (prefix, name, ns);
462                         state = WriteState.Attribute;
463                 }
464
465                 public override void WriteProcessingInstruction (string name, string value)
466                 {
467                         throw new NotSupportedException ();
468                 }
469
470                 public override void WriteComment (string text)
471                 {
472                         throw new NotSupportedException ();
473                 }
474
475                 public override void WriteCData (string text)
476                 {
477                         throw new NotSupportedException ();
478                 }
479
480                 public override void WriteStartElement (string prefix, string name, string ns)
481                 {
482                         throw new NotSupportedException ();
483                 }
484
485                 public override void WriteEndElement ()
486                 {
487                         throw new NotSupportedException ();
488                 }
489
490                 public override void WriteFullEndElement ()
491                 {
492                         throw new NotSupportedException ();
493                 }
494
495                 public override void WriteDocType (string name, string pubid, string systemId, string intsubset)
496                 {
497                         throw new NotSupportedException ();
498                 }
499
500                 public override void WriteStartDocument ()
501                 {
502                         throw new NotSupportedException ();
503                 }
504
505                 public override void WriteStartDocument (bool standalone)
506                 {
507                         throw new NotSupportedException ();
508                 }
509
510                 public override void WriteEndDocument ()
511                 {
512                         throw new NotSupportedException ();
513                 }
514
515                 public override void WriteBase64 (byte [] data, int start, int length)
516                 {
517                         throw new NotSupportedException ();
518                 }
519
520                 public override void WriteRaw (char [] raw, int start, int length)
521                 {
522                         throw new NotSupportedException ();
523                 }
524
525                 public override void WriteRaw (string raw)
526                 {
527                         throw new NotSupportedException ();
528                 }
529
530                 public override void WriteSurrogateCharEntity (char msb, char lsb)
531                 {
532                         throw new NotSupportedException ();
533                 }
534
535                 public override void WriteCharEntity (char c)
536                 {
537                         throw new NotSupportedException ();
538                 }
539
540                 public override void WriteEntityRef (string entname)
541                 {
542                         if (state != WriteState.Attribute)
543                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot write attribute value.");
544                         attribute.AppendChild (attribute.OwnerDocument.CreateEntityReference (entname));
545                 }
546
547                 public override void WriteChars (char [] data, int start, int length)
548                 {
549                         WriteString (new string (data, start, length));
550                 }
551
552                 public override void WriteString (string text)
553                 {
554                         if (state != WriteState.Attribute)
555                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot write attribute value.");
556                         attribute.Value += text;
557                 }
558
559                 public override void WriteWhitespace (string text)
560                 {
561                         if (state != WriteState.Attribute)
562                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot write attribute value.");
563                         if (attribute.ChildNodes.Count == 0)
564                                 attribute.AppendChild (attribute.OwnerDocument.CreateWhitespace (text));
565                         else
566                                 attribute.Value += text;
567                 }
568
569                 public override void WriteEndAttribute ()
570                 {
571                         if (state != WriteState.Attribute)
572                                 throw new InvalidOperationException ("Current state is not inside attribute. Cannot close attribute.");
573                         document.AttributeUpdate (element, element.SetAttributeNode (attribute), attribute);
574                         attribute = null;
575                         state = WriteState.Content;
576                 }
577         }
578
579         internal class Insertion
580         {
581                 // AppendChild : last child / true
582                 // InsertBefore : current node / false
583                 // InsertAfter : current node / true
584                 // PrependChild : first child / false
585                 public XmlNode ParentNode;
586                 public XmlNode InsertedNode;
587                 public bool Afterward;
588         }
589
590         internal class Removal
591         {
592                 public XmlNode OwnerNode;
593                 public XmlNode NextSibling;
594                 public XmlNode RemovedNode;
595         }
596
597         internal class AttributeUpdate
598         {
599                 public XmlElement Element;
600                 public XmlAttribute NewAttribute;
601                 public XmlAttribute OldAttribute;
602         }
603
604         internal class XmlDocumentEditableNavigator : XPathNavigator, IHasXmlNode
605         {
606                 static readonly bool isXmlDocumentNavigatorImpl;
607                 
608                 static XmlDocumentEditableNavigator ()
609                 {
610                         isXmlDocumentNavigatorImpl =
611                                 (typeof (XmlDocumentEditableNavigator).Assembly 
612                                 == typeof (XmlDocument).Assembly);
613                 }
614
615                 XPathEditableDocument document;
616                 XPathNavigator navigator;
617
618                 public XmlDocumentEditableNavigator (XPathEditableDocument doc)
619                 {
620                         document = doc;
621                         if (isXmlDocumentNavigatorImpl)
622                                 navigator = new XmlDocumentNavigator (doc.Node);
623                         else
624                                 navigator = doc.CreateNavigator ();
625                 }
626
627                 public XmlDocumentEditableNavigator (XmlDocumentEditableNavigator nav)
628                 {
629                         document = nav.document;
630                         navigator = nav.navigator.Clone ();
631                 }
632
633                 public override string BaseURI {
634                         get { return navigator.BaseURI; }
635                 }
636
637                 public override bool IsEmptyElement {
638                         get { return navigator.IsEmptyElement; }
639                 }
640
641                 public override string LocalName {
642                         get { return navigator.LocalName; }
643                 }
644
645                 public override XmlNameTable NameTable {
646                         get { return navigator.NameTable; }
647                 }
648
649                 public override string Name {
650                         get { return navigator.Name; }
651                 }
652
653                 public override string NamespaceURI {
654                         get { return navigator.NamespaceURI; }
655                 }
656
657                 public override XPathNodeType NodeType {
658                         get { return navigator.NodeType; }
659                 }
660
661                 public override string Prefix {
662                         get { return navigator.Prefix; }
663                 }
664
665                 public override string Value {
666                         get { return navigator.Value; }
667                 }
668
669                 public override XPathNavigator Clone ()
670                 {
671                         return new XmlDocumentEditableNavigator (this);
672                 }
673
674                 public override XPathNavigator CreateNavigator ()
675                 {
676                         return navigator.Clone ();
677                 }
678
679                 public XmlNode GetNode ()
680                 {
681                         return ((IHasXmlNode) navigator).GetNode ();
682                 }
683
684                 public override bool IsSamePosition (XPathNavigator other)
685                 {
686                         XmlDocumentEditableNavigator nav = other as XmlDocumentEditableNavigator;
687                         if (nav != null)
688                                 return navigator.IsSamePosition (nav.navigator);
689                         else
690                                 return navigator.IsSamePosition (nav);
691                 }
692
693                 public override bool MoveTo (XPathNavigator other)
694                 {
695                         XmlDocumentEditableNavigator nav = other as XmlDocumentEditableNavigator;
696                         if (nav != null)
697                                 return navigator.MoveTo (nav.navigator);
698                         else
699                                 return navigator.MoveTo (nav);
700                 }
701
702                 public override bool MoveToFirstAttribute ()
703                 {
704                         return navigator.MoveToFirstAttribute ();
705                 }
706
707                 public override bool MoveToFirstChild ()
708                 {
709                         return navigator.MoveToFirstChild ();
710                 }
711
712                 public override bool MoveToFirstNamespace (XPathNamespaceScope scope)
713                 {
714                         return navigator.MoveToFirstNamespace (scope);
715                 }
716
717                 public override bool MoveToId (string id)
718                 {
719                         return navigator.MoveToId (id);
720                 }
721
722                 public override bool MoveToNext ()
723                 {
724                         return navigator.MoveToNext ();
725                 }
726
727                 public override bool MoveToNextAttribute ()
728                 {
729                         return navigator.MoveToNextAttribute ();
730                 }
731
732                 public override bool MoveToNextNamespace (XPathNamespaceScope scope)
733                 {
734                         return navigator.MoveToNextNamespace (scope);
735                 }
736
737                 public override bool MoveToParent ()
738                 {
739                         return navigator.MoveToParent ();
740                 }
741
742                 public override bool MoveToPrevious ()
743                 {
744                         return navigator.MoveToPrevious ();
745                 }
746
747                 public override XmlWriter AppendChild ()
748                 {
749                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
750                         if (n == null)
751                                 throw new InvalidOperationException ("Should not happen.");
752                         return document.CreateInsertionWriter (n, null);
753                 }
754
755                 public override XmlWriter InsertBefore ()
756                 {
757                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
758                         return document.CreateInsertionWriter (n.ParentNode, n.PreviousSibling);
759                 }
760
761                 public override XmlWriter CreateAttributes ()
762                 {
763                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
764                         return document.CreateInsertionWriter (n, null);
765                 }
766
767                 public override void DeleteSelf ()
768                 {
769                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
770                         if (!navigator.MoveToNext ())
771                                 navigator.MoveToParent ();
772                         document.DeleteNode (n);
773                 }
774
775                 public override void SetValue (string value)
776                 {
777                         XmlNode n = ((IHasXmlNode) navigator).GetNode ();
778                         foreach (XmlNode c in n.ChildNodes)
779                                 document.DeleteNode (c);
780                         XmlWriter w = document.CreateInsertionWriter (n, null);
781                         w.WriteValue (value);
782                         w.Close ();
783                 }
784         }
785 }
786
787 #endif