2004-12-01 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml.XPath / XPathDocument.cs
1 //
2 // System.Xml.XPath.XPathDocument
3 //
4 // Authors:
5 //   Tim Coleman (tim@timcoleman.com)
6 //   Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
7 //
8 // (C) Copyright 2002 Tim Coleman
9 // (C) 2003 Atsushi Enomoto
10 //
11
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 // 
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 // 
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 //
32 using System;
33 using System.Collections;
34 using System.ComponentModel;
35 using System.IO;
36 using System.Text;
37 using System.Xml;
38 using System.Xml.Schema;
39 using System.Xml.Serialization;
40 using Mono.Xml.XPath;
41
42 namespace System.Xml.XPath
43 {
44 #if NET_2_0obsolete
45         [XmlSchemaProvider ("GetSchema")]
46         public class XPathDocument : IXPathNavigable//, IXPathEditable,
47 //              IChangeTracking, IRevertibleChangeTracking, IXmlSerializable
48         {
49                 // FIXME: In the future this switch will disappear.
50                 // Regardless of this switch, those constructors that does 
51                 // not take input document use editable XPathDocument.
52                 static bool useEditable;
53
54                 static XPathDocument ()
55                 {
56                         // FIXME: remove when new XPathDocument2 got more 
57                         // stable. This environment value is temporary.
58                         if (Environment.GetEnvironmentVariable ("MONO_XPATH_DOCUMENT_2") == "yes")
59                                 useEditable = true;
60                 }
61
62                 XPathDocument2Editable editable;
63                 DTMXPathDocument dtm;
64
65                 XmlSchemaSet schemas;
66
67                 // save parameters
68                 Encoding encoding;
69                 bool preserveWhitespace;
70
71 #region Constructors
72                 [MonoTODO]
73                 public XPathDocument ()
74                         : this (new NameTable ())
75                 {
76                 }
77
78                 [MonoTODO]
79                 public XPathDocument (XmlNameTable nameTable)
80                 {
81                         editable = new XPathDocument2Editable (new XPathDocument2 (nameTable));
82
83                         InitializeEvents ();
84                 }
85
86                 public XPathDocument (Stream stream)
87                         : this (stream, true)
88                 {
89                 }
90
91                 public XPathDocument (string uri) 
92                         : this (uri, XmlSpace.None, true)
93                 {
94                 }
95
96                 public XPathDocument (string uri, bool acceptChangesOnLoad) 
97                         : this (uri, XmlSpace.None, acceptChangesOnLoad)
98                 {
99                 }
100
101                 public XPathDocument (TextReader reader)
102                         : this (reader, true)
103                 {
104                 }
105
106                 [MonoTODO]
107                 public XPathDocument (XmlReader reader)
108                         : this (reader, XmlSpace.None, true)
109                 {
110                 }
111
112                 [MonoTODO]
113                 public XPathDocument (XmlReader reader, bool acceptChangesOnLoad)
114                         : this (reader, XmlSpace.None, acceptChangesOnLoad)
115                 {
116                 }
117
118                 [MonoTODO]
119                 public XPathDocument (string uri, XmlSpace space)
120                         : this (uri, space, true)
121                 {
122                 }
123
124                 [MonoTODO]
125                 public XPathDocument (XmlReader reader, XmlSpace space)
126                         : this (reader, space, true)
127                 {
128                 }
129
130                 [MonoTODO]
131                 public XPathDocument (string uri, XmlSpace space, bool acceptChangesOnLoad)
132                 {
133                         XmlValidatingReader vr = null;
134                         try {
135                                 vr = new XmlValidatingReader (new XmlTextReader (uri));
136                                 vr.ValidationType = ValidationType.None;
137                                 Initialize (vr, space, acceptChangesOnLoad);
138                         } finally {
139                                 if (vr != null)
140                                         vr.Close ();
141                         }
142                 }
143
144                 [MonoTODO]
145                 public XPathDocument (Stream stream, bool acceptChangesOnLoad)
146                 {
147                         XmlValidatingReader vr = new XmlValidatingReader (new XmlTextReader (stream));
148                         vr.ValidationType = ValidationType.None;
149                         Initialize (vr, XmlSpace.None, acceptChangesOnLoad);
150                 }
151
152                 [MonoTODO]
153                 public XPathDocument (TextReader reader, bool acceptChangesOnLoad)
154                 {
155                         XmlValidatingReader vr = new XmlValidatingReader (new XmlTextReader (reader));
156                         vr.ValidationType = ValidationType.None;
157                         Initialize (vr, XmlSpace.None, acceptChangesOnLoad);
158                 }
159
160                 [MonoTODO]
161                 public XPathDocument (XmlReader reader, XmlSpace space, bool acceptChangesOnLoad)
162                 {
163                         Initialize (reader, space, acceptChangesOnLoad);
164                 }
165
166                 private void Initialize (XmlReader reader, XmlSpace space, bool acceptChangesOnLoad)
167                 {
168                         if (useEditable)
169                                 InitializeEditable (reader, space, acceptChangesOnLoad);
170                         else
171                                 dtm = new DTMXPathDocumentBuilder (reader, space).CreateDocument ();
172                 }
173
174                 private void InitializeEditable (XmlReader reader, XmlSpace space, bool acceptChangesOnLoad)
175                 {
176                         XmlReaderSettings settings = new XmlReaderSettings ();
177                         settings.NameTable = reader.NameTable;
178                         settings.IgnoreWhitespace = (space == XmlSpace.Preserve);
179                         XmlReader r = XmlReader.Create (reader, settings);
180                         XPathDocument2 doc = new XPathDocument2 ();
181                         doc.Load (r, space);
182                         editable = new XPathDocument2Editable (doc);
183                         if (acceptChangesOnLoad)
184                                 AcceptChanges ();
185                         this.preserveWhitespace = space == XmlSpace.Preserve;
186                         this.schemas = reader.Settings != null ? reader.Settings.Schemas : null;
187
188                         InitializeEvents ();
189                 }
190
191                 private void InitializeEvents ()
192                 {
193                         editable.ChangeRejected += this.ChangeRejected;
194                         editable.ItemUpdated += this.ItemUpdated;
195                         editable.ItemUpdating += this.ItemUpdating;
196                         editable.ItemInserted += this.ItemInserted;
197                         editable.ItemInserting += this.ItemInserting;
198                         editable.ItemDeleted += this.ItemDeleted;
199                         editable.ItemDeleting += this.ItemDeleting;
200                         editable.RejectingChange += this.RejectingChange;
201                 }
202 #endregion
203
204 #region Events
205
206                 public event NodeChangedEventHandler ChangeRejected;
207
208                 public event NodeChangedEventHandler ItemUpdated;
209
210                 public event NodeChangedEventHandler ItemUpdating;
211
212                 public event NodeChangedEventHandler ItemInserted;
213
214                 public event NodeChangedEventHandler ItemInserting;
215
216                 public event NodeChangedEventHandler ItemDeleted;
217
218                 public event NodeChangedEventHandler ItemDeleting;
219
220                 public event NodeChangedEventHandler RejectingChange;
221
222 #endregion // Events
223
224 #region Properties
225
226                 [MonoTODO]
227                 public bool EnableChangeTracking {
228                         get { return editable.EnableChangeTracking; }
229                         set { editable.EnableChangeTracking = value; }
230                 }
231
232                 public Encoding Encoding {
233                         get { return encoding; }
234                         set { encoding = value; }
235                 }
236
237                 [MonoTODO]
238                 bool IChangeTracking.IsChanged {
239                         get { return editable.IsChanged; }
240                 }
241
242                 public XmlNameTable NameTable {
243                         get { return editable.NameTable; }
244                 }
245
246                 public bool PreserveWhiteSpace {
247                         get { return preserveWhitespace; }
248                 }
249
250                 public XmlSchemaSet Schemas {
251                         get { return schemas; }
252                         set { schemas = value; }
253                 }
254
255 #endregion // Properies
256
257 #region Methods
258                 [MonoTODO]
259                 public void AcceptChanges ()
260                 {
261                         editable.AcceptChanges ();
262                 }
263
264                 /* It will disappear in 2.0 RTM
265                 [MonoTODO]
266                 public XPathChangeNavigator CreateChangeNavigator ()
267                 {
268                         throw new NotImplementedException ();
269                 }
270                 */
271
272                 public XPathEditableNavigator CreateEditor ()
273                 {
274                         return editable.CreateEditor ();
275                 }
276
277                 [MonoTODO ("Remove switch")]
278                 public XPathNavigator CreateNavigator ()
279                 {
280                         if (editable != null)
281                                 return editable.CreateNavigator ();
282                         else
283                                 return dtm.CreateNavigator ();
284                 }
285
286                 public XmlWriter CreateWriter ()
287                 {
288                         return CreateEditor ().AppendChild ();
289                 }
290
291                 [MonoTODO]
292                 public virtual XmlSchema GetSchema ()
293                 {
294                         return editable.GetSchema ();
295                 }
296
297                 [MonoTODO]
298                 public static XmlQualifiedName GetXPathDocumentSchema (XmlSchemaSet schemas)
299                 {
300                         throw new NotImplementedException ();
301                 }
302
303                 [MonoTODO]
304                 public bool HasChanges ()
305                 {
306                         return editable.HasChanges ();
307                 }
308
309                 /* It will disappear in 2.0 RTM
310                 [Obsolete]
311                 [MonoTODO]
312                 public void LoadXml (string xml)  
313                 {
314                         throw new NotImplementedException ();
315 //                      tree = new XPathDocumentTree (xmlReader);
316 //                      if (acceptChangesOnLoad)
317 //                              AcceptChanges ();
318                 }
319                 */
320
321                 public void ReadXml (XmlReader reader)
322                 {
323                         editable.ReadXml (reader);
324                 }
325
326                 [MonoTODO]
327                 public void RejectChanges ()
328                 {
329                         editable.RejectChanges ();
330                 }
331
332                 [MonoTODO ("Confirm writer settings etc.")]
333                 public void Save (Stream stream)
334                 {
335                         Save (new XmlTextWriter (stream, encoding));
336                 }
337
338                 [MonoTODO ("Confirm writer settings etc.")]
339                 public void Save (string filename)
340                 {
341                         using (XmlWriter w = new XmlTextWriter (filename, encoding)) {
342                                 Save (w);
343                         }
344                 }
345
346                 [MonoTODO ("Confirm writer settings etc.")]
347                 public void Save (TextWriter writer)
348                 {
349                         Save (new XmlTextWriter (writer));
350                 }
351
352                 [MonoTODO]
353                 public void Save (XmlWriter writer)
354                 {
355                         writer.WriteNode (CreateNavigator ().ReadSubtree (), false);
356                 }
357
358                 [MonoTODO]
359                 public XPathNodeIterator SelectNodes (string xpath)
360                 {
361                         return CreateEditor ().Select (xpath);
362                 }
363
364                 [MonoTODO]
365                 public XPathNodeIterator SelectNodes (XPathExpression expr)
366                 {
367                         return CreateEditor ().Select (expr);
368                 }
369
370                 [MonoTODO]
371                 public XPathNodeIterator SelectNodes (string xpath ,IXmlNamespaceResolver nsResolver)
372                 {
373                         return CreateEditor ().Select (xpath, nsResolver);
374                 }
375
376                 [MonoTODO]
377                 public XPathEditableNavigator SelectSingleNode (string xpath)
378                 {
379                         XPathNodeIterator iter = CreateEditor ().Select (xpath);
380                         if (iter.MoveNext ())
381                                 return (XPathEditableNavigator) iter.Current;
382                         else
383                                 return null;
384                 }
385
386                 [MonoTODO]
387                 public XPathEditableNavigator SelectSingleNode (XPathExpression expr)
388                 {
389                         XPathNodeIterator iter = CreateEditor ().Select (expr);
390                         if (iter.MoveNext ())
391                                 return (XPathEditableNavigator) iter.Current;
392                         else
393                                 return null;
394                 }
395
396                 [MonoTODO]
397                 public XPathEditableNavigator SelectSingleNode (string xpath ,IXmlNamespaceResolver nsResolver)
398                 {
399                         XPathNodeIterator iter = CreateEditor ().Select (xpath, nsResolver);
400                         if (iter.MoveNext ())
401                                 return (XPathEditableNavigator) iter.Current;
402                         else
403                                 return null;
404                 }
405
406                 [MonoTODO]
407                 public void WriteXml (XmlWriter writer)
408                 {
409                         Save (writer);
410                 }
411 #endregion
412         }
413
414
415 #else // !NET_2_0
416
417         public class XPathDocument : IXPathNavigable
418         {
419                 DTMXPathDocument document;
420
421                 public XPathDocument (Stream stream)
422                 {
423                         XmlValidatingReader vr = new XmlValidatingReader (new XmlTextReader (stream));
424                         vr.ValidationType = ValidationType.None;
425                         Initialize (vr, XmlSpace.None);
426                 }
427
428                 public XPathDocument (string uri) 
429                         : this (uri, XmlSpace.None)
430                 {
431                 }
432
433                 public XPathDocument (TextReader reader)
434                 {
435                         XmlValidatingReader vr = new XmlValidatingReader (new XmlTextReader (reader));
436                         vr.ValidationType = ValidationType.None;
437                         Initialize (vr, XmlSpace.None);
438                 }
439
440                 public XPathDocument (XmlReader reader)
441                         : this (reader, XmlSpace.None)
442                 {
443                 }
444
445                 public XPathDocument (string uri, XmlSpace space)
446                 {
447                         XmlValidatingReader vr = null;
448                         try {
449                                 vr = new XmlValidatingReader (new XmlTextReader (uri));
450                                 vr.ValidationType = ValidationType.None;
451                                 Initialize (vr, space);
452                         } finally {
453                                 if (vr != null)
454                                         vr.Close ();
455                         }
456                 }
457
458                 public XPathDocument (XmlReader reader, XmlSpace space)
459                 {
460                         Initialize (reader, space);
461                 }
462
463                 private void Initialize (XmlReader reader, XmlSpace space)
464                 {
465                         document = new DTMXPathDocumentBuilder (reader, space).CreateDocument ();
466                 }
467
468                 private void Initialize (XmlReader reader, XmlSpace space, bool acceptChangesOnLoad)
469                 {
470                         document = new DTMXPathDocumentBuilder (reader, space).CreateDocument ();
471                 }
472
473                 public XPathNavigator CreateNavigator ()
474                 {
475                         return document.CreateNavigator ();
476                 }
477         }
478
479 #endif
480
481 }
482
483