2003-01-27 Ville Palo <vi64pa@koti.soon.fi>
[mono.git] / mcs / class / System.Data / System.Xml / XmlDataDocument.cs
1 //
2 // mcs/class/System.Data/System.Xml/XmlDataDocument.cs
3 //
4 // Purpose: Provides a W3C XML DOM Document to interact with
5 //          relational data in a DataSet
6 //
7 // class: XmlDataDocument
8 // assembly: System.Data.dll
9 // namespace: System.Xml
10 //
11 // Author:
12 //     Daniel Morgan <danmorg@sc.rr.com>
13 //     Ville Palo <vi64pa@koti.soon.fi>
14 //
15 // (c)copyright 2002 Daniel Morgan
16 // (c)copyright 2003 Ville Palo
17 //
18 // XmlDataDocument is included within the Mono Class Library.
19 //
20
21 using System;
22 using System.Data;
23 using System.IO;
24 using System.Text;
25 using System.Xml.XPath;
26 using System.Collections;
27 using System.Globalization;
28 using System.ComponentModel;
29
30 namespace System.Xml {
31
32         public class XmlDataDocument : XmlDocument {
33
34                 #region Fields
35
36                 private DataSet dataSet;
37                 private bool isReadOnly = false;
38
39                 private int dataRowID = 1;
40                 private ArrayList dataRowIDList = new ArrayList ();
41
42                 // this is needed for inserting new row to datatable via xml
43                 private Hashtable TempTable = new Hashtable ();
44
45                 #endregion // Fields
46
47                 #region Constructors
48
49                 public XmlDataDocument() {
50
51                         dataSet = new DataSet();
52                         dataSet.Tables.CollectionChanged += new CollectionChangeEventHandler (OnDataTableChanged);
53                         
54                         this.NodeChanged += new XmlNodeChangedEventHandler (OnNodeChanged);
55                         this.NodeChanging += new XmlNodeChangedEventHandler (OnNodeChanging);
56                         this.NodeInserting += new XmlNodeChangedEventHandler (OnNodeInserting);
57                         this.NodeRemoved += new XmlNodeChangedEventHandler (OnNodeRemoved);
58                         this.NodeInserted += new XmlNodeChangedEventHandler (OnNodeInserted);
59                         DataSet.EnforceConstraints = false;
60                 }
61
62                 public XmlDataDocument(DataSet dataset) {
63
64                         this.dataSet = dataset;
65
66                         // Read DataSet in as document if there is data in tables
67                         bool HaveRows = false;
68                         foreach (DataTable T in dataSet.Tables) {
69
70                                 if (T.Rows.Count > 0) {
71                                         HaveRows = true;
72                                         break;
73                                 }
74                         }
75
76                         if (HaveRows) {
77
78                                 XmlReader xmlReader = new XmlTextReader (new StringReader (dataSet.GetXml ()));
79
80                                 // Load DataSet's xml-data
81                                 base.Load (xmlReader);
82                                 xmlReader.Close ();
83                         }
84
85                         foreach (DataTable Table in DataSet.Tables) {
86                                 
87                                 foreach (DataRow Row in Table.Rows) {
88                                         Row.XmlRowID = dataRowID;
89                                         dataRowIDList.Add (dataRowID);
90                                         dataRowID++;
91                                 }
92                         }
93                                                 
94                         this.NodeChanged += new XmlNodeChangedEventHandler (OnNodeChanged);
95                         this.NodeChanging += new XmlNodeChangedEventHandler (OnNodeChanging);
96                         this.NodeInserting += new XmlNodeChangedEventHandler (OnNodeInserting);
97                         this.NodeRemoved += new XmlNodeChangedEventHandler (OnNodeRemoved);
98                         this.NodeInserted += new XmlNodeChangedEventHandler (OnNodeInserted);
99
100                         foreach (DataTable Table in dataSet.Tables) {
101                                 Table.ColumnChanged += new DataColumnChangeEventHandler (OnDataTableColumnChanged);
102                                 Table.RowDeleted += new DataRowChangeEventHandler (OnDataTableRowDeleted);
103                                 Table.RowChanged += new DataRowChangeEventHandler (OnDataTableRowChanged);
104                         }
105                 }
106
107                 // bool clone. If we are cloning XmlDataDocument then clone should be true.
108                 private XmlDataDocument (DataSet dataset, bool clone)
109                 {
110                         this.dataSet = dataset;
111
112                         foreach (DataTable Table in DataSet.Tables) {
113                                 
114                                 foreach (DataRow Row in Table.Rows) {
115                                         Row.XmlRowID = dataRowID;
116                                         dataRowIDList.Add (dataRowID);
117                                         dataRowID++;
118                                 }
119                         }
120                                                 
121                         this.NodeChanged += new XmlNodeChangedEventHandler (OnNodeChanged);
122                         this.NodeChanging += new XmlNodeChangedEventHandler (OnNodeChanging);           
123                         this.NodeInserting += new XmlNodeChangedEventHandler (OnNodeInserting);
124                         this.NodeRemoved += new XmlNodeChangedEventHandler (OnNodeRemoved);
125                         this.NodeInserted += new XmlNodeChangedEventHandler (OnNodeInserted);
126
127                         foreach (DataTable Table in dataSet.Tables) {
128                                 Table.ColumnChanged += new DataColumnChangeEventHandler (OnDataTableColumnChanged);
129                                 Table.RowDeleted += new DataRowChangeEventHandler (OnDataTableRowDeleted);
130                                 Table.RowChanged += new DataRowChangeEventHandler (OnDataTableRowChanged);
131                         }
132                 }
133
134                 #endregion // Constructors
135
136                 #region Public Properties
137
138                 public override string BaseURI {
139                         [MonoTODO]
140                         get {
141                                 // TODO: why are we overriding?
142                                 return base.BaseURI;
143                         }
144                 }
145
146                 public DataSet DataSet {
147                         get {
148                                 return dataSet;
149                         }
150                 }
151
152                 // override inheritted method from XmlDocument
153                 public override string InnerXml {
154                         [MonoTODO("override???")]
155                         get {
156                                 return base.InnerXml;
157                         }
158                                  
159                         [MonoTODO]
160                         set {
161                                 base.InnerXml = value;
162                         }
163                 }
164
165                 public override bool IsReadOnly {
166                         [MonoTODO("override???")]
167                         get {
168                                 return isReadOnly;
169                         }
170
171                 }
172
173                 // Item indexer
174                 public override XmlElement this[string name] {
175                         [MonoTODO("override???")]
176                         get {
177                                 return base [name];
178                         }
179                 }
180
181                 // Item indexer
182                 public override XmlElement this[string localname, string ns] {
183                         [MonoTODO("override???")]
184                         get {
185                                 return base [localname, ns];
186                         }
187                 }
188
189                 public override string LocalName {
190                         [MonoTODO("override???")]
191                         get {
192                                 return base.LocalName;
193                         }
194                 }
195
196                 public override string Name {
197                         [MonoTODO("override??")]
198                         get {
199                                 return base.Name;
200                         }
201                 }
202
203                 public override XmlDocument OwnerDocument {
204                         get {
205                                 return null;
206                         }
207                 }
208
209                 #endregion // Public Properties
210
211                 #region Public Methods
212
213                 [MonoTODO]
214                 public override XmlNode CloneNode(bool deep) 
215                 {
216                         XmlDataDocument Document;
217                         if (deep)
218                                 Document = new XmlDataDocument (DataSet.Copy (), true);
219                         else
220                                 Document = new XmlDataDocument (DataSet.Clone (), true);
221
222                         RemoveXmlDocumentListeners ();
223
224                         Document.PreserveWhitespace = PreserveWhitespace;
225                         if (deep) {
226                                 foreach(XmlNode n in ChildNodes)
227                                         Document.AppendChild (Document.ImportNode (n, deep));
228                         }
229
230                         AddXmlDocumentListeners ();
231
232                         return Document;                        
233                 }
234
235                 #region overloaded CreateElement methods
236
237                 [MonoTODO ("why this is override?")]
238                 public override XmlElement CreateElement(string prefix,
239                                 string localName, string namespaceURI) 
240                 {
241                         if ((localName == null) || (localName == String.Empty))
242                                 throw new ArgumentException ("The local name for elements or attributes cannot be null" +
243                                                              "or an empty string.");
244                         string pref = prefix != null ? prefix : String.Empty;
245                         return base.CreateElement (pref, localName, namespaceURI != null ? namespaceURI : String.Empty);
246                 }
247
248                 #endregion // overloaded CreateElement Methods
249                         
250                 // will not be supported
251                 public override XmlEntityReference CreateEntityReference(string name) 
252                 {
253                         throw new NotSupportedException();
254                 }
255                 
256                 // will not be supported
257                 public override XmlElement GetElementById(string elemId) 
258                 {
259                         throw new NotSupportedException();
260                 }
261
262                 // get the XmlElement associated with the DataRow
263                 [MonoTODO ("Exceptions")]
264                 public XmlElement GetElementFromRow(DataRow r) 
265                 {
266                         if (r.XmlRowID == 0) // datarow was not in xmldatadocument
267                                 throw new Exception ();
268
269                         int elementRow = dataRowIDList.IndexOf (r.XmlRowID);
270                         
271                         return (XmlElement)GetElementsByTagName (r.Table.TableName) [elementRow];
272                 }
273
274                 // get the DataRow associated with the XmlElement
275                 [MonoTODO ("Exceptions")]
276                 public DataRow GetRowFromElement(XmlElement e)
277                 {
278                         XmlElement node = e;
279                         if (node == null)
280                                 return null;
281
282                         XPathNavigator nodeNavigator = node.CreateNavigator ();
283                         int c  = GetElementsByTagName (node.Name).Count;
284                         
285                         if (c == 0)
286                                 return null;
287
288                         XmlNodeList nodeList = GetElementsByTagName (node.Name);
289
290                         int i = 0;
291                         bool isSame = false;
292
293                         while (i < c && !isSame) {
294
295                                 XPathNavigator docNavigator = nodeList [i].CreateNavigator ();
296                                 isSame = docNavigator.IsSamePosition (nodeNavigator);
297                                 docNavigator = nodeList [i].CreateNavigator ();
298                                 if (!isSame)
299                                         i++;
300                         }
301
302                         if (!isSame)
303                                 return null;
304
305                         if (i >= dataRowIDList.Count)
306                                 return null;
307
308                         // now we know rownum                   
309                         int xmlrowid = (int)dataRowIDList [i];
310                         if (xmlrowid <= 0)
311                                 return null;
312
313                         DataTable dt = DataSet.Tables [node.Name];
314                         DataRow row = null;
315
316                         if (dt == null)
317                                 return null;
318
319                         foreach (DataRow r in dt.Rows) {
320                                 if (xmlrowid == r.XmlRowID) {
321                                         row = r;
322                                 }
323                         }
324
325                         return row;                     
326                 }
327
328                 #region overload Load methods
329
330                 public override void Load(Stream inStream) {
331                         Load (new XmlTextReader (inStream));
332                 }
333
334                 public override void Load(string filename) {
335                         Load (new XmlTextReader (filename));
336                 }
337
338                 public override void Load(TextReader txtReader) {
339                         Load (new XmlTextReader (txtReader));
340                 }
341
342                 public override void Load(XmlReader reader) {
343
344                         bool OldEC = DataSet.EnforceConstraints;
345                         DataSet.EnforceConstraints = false;
346
347                         dataSet.Tables.CollectionChanged -= new CollectionChangeEventHandler (OnDataTableChanged);
348
349                         // For reading xml to XmlDocument
350                         XmlTextReader textReader = new XmlTextReader (
351                                 reader.BaseURI);
352                         
353                         // dont listen these events
354                         RemoveXmlDocumentListeners ();
355                         DataTable dt = null;
356
357
358                         if (reader.NodeType != XmlNodeType.Element)
359                                 reader.MoveToContent ();
360
361                         // read to next element
362                         while (reader.Read () && reader.NodeType != XmlNodeType.Element);
363
364                         do {
365                                 // Find right table from tablecollection
366                                 if (DataSet.Tables.Contains (reader.LocalName)) {
367
368                                         dt = DataSet.Tables [reader.LocalName];
369
370                                         // Make sure event handlers are not added twice
371                                         dt.ColumnChanged -= new DataColumnChangeEventHandler (OnDataTableColumnChanged);
372                                         dt.ColumnChanged += new DataColumnChangeEventHandler (OnDataTableColumnChanged);
373
374                                         dt.RowDeleted -= new DataRowChangeEventHandler (OnDataTableRowDeleted);
375                                         dt.RowDeleted += new DataRowChangeEventHandler (OnDataTableRowDeleted);
376                                         
377                                         dt.RowChanged -= new DataRowChangeEventHandler (OnDataTableRowChanged);
378                                         dt.RowChanged += new DataRowChangeEventHandler (OnDataTableRowChanged);
379                                 }
380                                 else
381                                         continue;
382
383                                 // Read rows to table
384                                 DataRow tempRow = dt.NewRow ();
385                                 while ((reader.NodeType != XmlNodeType.EndElement ||
386                                         reader.Name != dt.TableName) && reader.Read()) {
387                                         
388                                         switch (reader.NodeType) {
389                                                 
390                                         case XmlNodeType.Element:
391                                                 // Add column to DataRow
392                                                 LoadRow (reader, ref tempRow);
393                                                 break;
394                                         default:
395                                                 break;
396                                         }                       
397                                 }
398
399                                 // Every row must have unique id.
400                                 tempRow.XmlRowID = dataRowID;
401                                 dataRowIDList.Add (dataRowID);
402                                 dt.Rows.Add (tempRow);
403                                 dataRowID++;                                    
404                                 
405                                 
406                         } while (reader.Read ());
407
408                         base.Load (textReader);
409                         textReader.Close ();
410
411                         DataSet.EnforceConstraints = OldEC;
412                         AddXmlDocumentListeners ();
413                         dataSet.Tables.CollectionChanged += new CollectionChangeEventHandler (OnDataTableChanged);
414                 }
415                 
416                 #endregion // overloaded Load methods
417
418                 [MonoTODO]
419                 public override void WriteContentTo(XmlWriter xw) {
420                         base.WriteContentTo (xw);
421                 }
422
423                 [MonoTODO]
424                 public override void WriteTo(XmlWriter w) {
425                         base.WriteTo (w);
426                 }
427
428                 #endregion // Public Methods
429
430                 #region Protected Methods
431
432                 //FIXME: when internal protected bug is fixed uncomment this
433                 //[MonoTODO]
434                 //protected internal override XPathNavigator CreateNavigator(XmlNode node) {
435                 //      throw new NotImplementedException();
436                 //}
437
438                 #endregion // Protected Methods
439                 
440                 #region XmlDocument event handlers
441
442                 private void OnNodeChanging (object sender, XmlNodeChangedEventArgs args)
443                 {
444                         if (DataSet.EnforceConstraints) 
445                                 throw new InvalidOperationException (Locale.GetText ("Please set DataSet.EnforceConstraints == false " +
446                                                                                      "before trying to edit XmlDataDocument using " +
447                                                                                      "XML operations."));                       
448                 }
449
450                 // Invoked when XmlNode is changed colum is changed
451                 [MonoTODO]
452                 private void OnNodeChanged (object sender, XmlNodeChangedEventArgs args)
453                 {
454
455                         if (args.Node == null)
456                                 return;
457
458                         DataRow row = GetRowFromElement ((XmlElement)args.Node.ParentNode.ParentNode);
459
460                         if (row == null)
461                                 return;
462
463                         if (!row.Table.Columns.Contains (args.Node.ParentNode.Name))
464                                 return;
465
466                         row.Table.ColumnChanged -= new DataColumnChangeEventHandler (OnDataTableColumnChanged);
467
468                         if (row [args.Node.ParentNode.Name].ToString () != args.Node.InnerText)         
469                                 row [args.Node.ParentNode.Name] = args.Node.InnerText;          
470
471                         row.Table.ColumnChanged += new DataColumnChangeEventHandler (OnDataTableColumnChanged);
472                 }
473
474                 // Invoked when XmlNode is removed
475                 [MonoTODO]
476                 private void OnNodeRemoved (object sender, XmlNodeChangedEventArgs args)
477                 {
478                         if (args.OldParent == null)
479                                 return;
480
481                         if (!(args.OldParent is XmlElement))
482                                 return;
483                         
484                         DataRow row = GetRowFromElement ((XmlElement)args.OldParent);
485                         
486                         if (row == null)
487                                 return ;
488
489                         // Dont trig event again
490                         row.Table.ColumnChanged -= new DataColumnChangeEventHandler (OnDataTableColumnChanged);
491                         row [args.Node.Name] = null;
492                         row.Table.ColumnChanged += new DataColumnChangeEventHandler (OnDataTableColumnChanged);
493                 }
494
495                 private void OnNodeInserting (object sender, XmlNodeChangedEventArgs args) 
496                 {
497                         if (DataSet.EnforceConstraints) 
498                                 throw new InvalidOperationException (Locale.GetText ("Please set DataSet.EnforceConstraints == false " +
499                                                                                      "before trying to edit XmlDataDocument using " +
500                                                                                      "XML operations."));
501                         
502                 }
503                 
504                 private void OnNodeInserted (object sender, XmlNodeChangedEventArgs args)
505                 {
506
507                         // this is table element 
508                         if (DataSet.Tables.Contains (args.NewParent.Name)) {
509
510                                 Hashtable ht = null;
511                                 if (TempTable.ContainsKey (args.NewParent.Name)) {
512
513                                         // if TempTable contains table name, get it and remove it from hashtable
514                                         // so we can later add it :)
515                                         ht = TempTable [args.NewParent.Name] as Hashtable;
516                                         TempTable.Remove (args.NewParent.Name);
517                                 }
518                                 else 
519                                         ht = new Hashtable ();
520
521                                 ht.Add (args.Node.Name, args.Node.InnerText);                           
522                                 TempTable.Add (args.NewParent.Name, ht);
523                         } 
524                         else if (DataSet.Tables.Contains (args.Node.Name)) {
525                                 
526                                 // if nodes name is same as some table in the list is is time to 
527                                 // add row to datatable
528
529                                 DataTable dt = DataSet.Tables [args.Node.Name];
530                                 dt.RowChanged -= new DataRowChangeEventHandler (OnDataTableRowChanged);
531
532                                 DataRow row = dt.NewRow ();
533                                 Hashtable ht = TempTable [args.Node.Name] as Hashtable;
534                                 
535                                 IDictionaryEnumerator enumerator = ht.GetEnumerator ();
536                                 while (enumerator.MoveNext ()) {
537                                         if (dt.Columns.Contains (enumerator.Key.ToString ()))
538                                                 row [enumerator.Key.ToString ()] = enumerator.Value.ToString ();
539                                 }
540                                 
541                                 DataSet.Tables [args.Node.Name].Rows.Add (row);
542                                 dt.RowChanged += new DataRowChangeEventHandler (OnDataTableRowChanged);
543                         } 
544
545                 }
546
547                 #endregion // DataSet event handlers
548
549                 #region DataSet event handlers
550
551                 // If DataTable is added or removed from DataSet
552                 private void OnDataTableChanged (object sender, CollectionChangeEventArgs eventArgs)
553                 {
554                         DataTable Table = (DataTable)eventArgs.Element;
555                         if (eventArgs.Action == CollectionChangeAction.Add) {
556                                 Table.ColumnChanged += new DataColumnChangeEventHandler (OnDataTableColumnChanged);
557                                 Table.RowDeleted += new DataRowChangeEventHandler (OnDataTableRowDeleted);
558                                 Table.RowChanged += new DataRowChangeEventHandler (OnDataTableRowChanged);
559                         }
560                 }
561
562                 // If column has changed 
563                 [MonoTODO]                      
564                 private void OnDataTableColumnChanged(object sender, 
565                                                              DataColumnChangeEventArgs eventArgs)
566                 {
567                         RemoveXmlDocumentListeners ();
568
569                         // row is not yet in datatable
570                         if (eventArgs.Row.XmlRowID == 0)
571                                 return;
572
573                         // TODO: Here should be some kind of error checking.
574                         GetElementsByTagName (eventArgs.Column.ColumnName) [dataRowIDList.IndexOf (
575                                 eventArgs.Row.XmlRowID)].InnerText = eventArgs.ProposedValue.ToString ();
576                         
577                         AddXmlDocumentListeners ();
578                 }
579         
580                 [MonoTODO]
581                 private void OnDataTableRowDeleted(object sender,
582                                                           DataRowChangeEventArgs eventArgs)
583                 {
584
585                         DataRow deletedRow = null;
586                         deletedRow = eventArgs.Row;
587
588                         if (eventArgs.Row.XmlRowID == 0)
589                                 return;
590                         
591                         int rowIndex = dataRowIDList.IndexOf (eventArgs.Row.XmlRowID);
592                         if (rowIndex == -1 || eventArgs.Row.XmlRowID == 0 || 
593                             rowIndex > GetElementsByTagName (deletedRow.Table.TableName).Count - 1)
594                                 return;
595                         
596                         // Remove element from xmldocument and row indexlist
597                         // FIXME: this is one way to do this, but i hope someday i find out much better way.
598                         XmlNode p = GetElementsByTagName (deletedRow.Table.TableName) [rowIndex].ParentNode;
599                         if (p != null) {
600                                 p.RemoveChild (GetElementsByTagName (deletedRow.Table.TableName) [rowIndex]);
601                                 dataRowIDList.RemoveAt (rowIndex);
602                         }
603                 }
604                 
605                 [MonoTODO]
606                 private void OnDataTableRowChanged(object sender, DataRowChangeEventArgs eventArgs)
607                 {
608                         switch (eventArgs.Action) {
609
610                                 case DataRowAction.Delete:
611                                         OnDataTableRowDeleted (sender, eventArgs);
612                                         break;
613
614                                 case DataRowAction.Add:
615                                         OnDataTableRowAdded (eventArgs);
616                                         break;
617
618                                 case DataRowAction.Rollback:
619                                         OnDataTableRowRollback (eventArgs);
620                                         break;
621                                 default:
622                                         break;
623                         } 
624                 }
625
626                 // Added
627                 [MonoTODO]
628                 private void OnDataTableRowAdded (DataRowChangeEventArgs args)
629                 {
630                         RemoveXmlDocumentListeners ();
631
632                         // If XmlRowID is != 0 then it is already added
633                         if (args.Row.XmlRowID != 0)
634                                 return;
635                         
636                         // Create row element. Row's name same as TableName                                     
637                         DataRow row = args.Row;
638                         row.XmlRowID = dataRowID;
639                         dataRowIDList.Add (dataRowID);
640                         dataRowID++;
641
642                         if (DocumentElement == null)
643                                 this.AppendChild (CreateElement (DataSet.DataSetName));
644
645                         XmlElement element = CreateElement (args.Row.Table.TableName);
646                         DocumentElement.AppendChild (element);
647
648                         XmlElement rowElement = null;
649
650                         for (int i = 0; i < row.Table.Columns.Count; i++) {
651
652                                 rowElement = CreateElement (row.Table.Columns [i].ColumnName);
653                                 rowElement.InnerText = (string)row [i];
654                                 element.AppendChild (rowElement);
655                         }
656                         
657                         AddXmlDocumentListeners ();
658                 }
659
660                 // Rollback
661                 [MonoTODO]
662                 private void OnDataTableRowRollback (DataRowChangeEventArgs args)
663                 {
664                         RemoveXmlDocumentListeners ();
665
666                         DataRow row = args.Row;                 
667                         int rowid = dataRowIDList.IndexOf (row.XmlRowID);
668
669                         // find right element in xmldocument
670                         if (rowid == 0 || rowid >= GetElementsByTagName (row.Table.TableName).Count)
671                                 return;
672
673                         XmlNode node = GetElementsByTagName (row.Table.TableName) [rowid];
674                         
675                         int rowValue = 0;
676                         for (int i = 0; i < node.ChildNodes.Count; i++) {
677                                 
678                                 XmlNode child = node.ChildNodes [i];
679                                 if (child.NodeType != XmlNodeType.Whitespace) {
680                                         child.InnerText = (string)row [rowValue++];
681                                 }
682                         }
683
684                         AddXmlDocumentListeners ();
685                 }
686
687                 #endregion // DataSet event handlers
688
689                 #region Private methods
690
691                 [MonoTODO]
692                 private void LoadRow (XmlReader reader, ref DataRow row)
693                 {                       
694                         // dt.Rows.Add (LoadRow (reader, dt.NewRow ()));
695                         // This method returns DataRow filled by values
696                         // from xmldocument
697                         string rowname = reader.Name;
698                         string column = "";
699                         
700                         if (reader.NodeType == XmlNodeType.Element)
701                                 column = reader.Name;
702                         
703                         reader.Read ();
704                         
705                         if (reader.NodeType == XmlNodeType.Text) {
706                                 
707                                 string val = reader.Value;
708                                 if (row.Table.Columns.Contains (column))
709                                         row [column] = val;
710                         }
711                 }
712                 
713                 private void RemoveXmlDocumentListeners ()
714                 {
715                         this.NodeInserting -= new XmlNodeChangedEventHandler (OnNodeInserting);
716                         this.NodeInserted -= new XmlNodeChangedEventHandler (OnNodeInserted);
717                         this.NodeChanged -= new XmlNodeChangedEventHandler (OnNodeChanged);
718                         this.NodeChanging -= new XmlNodeChangedEventHandler (OnNodeChanging);
719                 }
720
721                 private void AddXmlDocumentListeners ()
722                 {
723                         this.NodeInserting += new XmlNodeChangedEventHandler (OnNodeInserting);
724                         this.NodeInserted += new XmlNodeChangedEventHandler (OnNodeInserted);
725                         this.NodeChanged += new XmlNodeChangedEventHandler (OnNodeChanged);
726                         this.NodeChanging += new XmlNodeChangedEventHandler (OnNodeChanging);
727                 }
728                 #endregion // Private methods
729         }
730 }
731