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