2005-12-05 Lluis Sanchez Gual <lluis@novell.com>
[mono.git] / mcs / class / System.XML / System.Xml / XmlNodeReader2.cs
1 //
2 // System.Xml.XmlNodeReader2.cs - splitted XmlNodeReader that manages entities.
3 //
4 // Author:
5 //      Duncan Mak  (duncan@ximian.com)
6 //      Atsushi Enomoto  (ginga@kit.hi-ho.ne.jp)
7 //
8 // (C) Ximian, Inc.
9 // (C) 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
33 using System;
34 #if NET_2_0
35 using System.Collections.Generic;
36 #endif
37 using System.Xml;
38 using System.Xml.Schema;
39 using System.Text;
40 using Mono.Xml;
41
42 namespace System.Xml
43 {
44 #if NET_2_0
45         public class XmlNodeReader : XmlReader, IHasXmlParserContext, IXmlNamespaceResolver
46 #else
47         public class XmlNodeReader : XmlReader, IHasXmlParserContext
48 #endif
49         {
50                 XmlReader entity;
51                 XmlNodeReaderImpl source;
52                 bool entityInsideAttribute;
53                 bool insideAttribute;
54
55                 #region Constructor
56
57                 public XmlNodeReader (XmlNode node)
58                 {
59                         source = new XmlNodeReaderImpl (node);
60                 }
61                 
62                 private XmlNodeReader (XmlNodeReaderImpl entityContainer, bool insideAttribute)
63                 {
64                         source = new XmlNodeReaderImpl (entityContainer);
65                         this.entityInsideAttribute = insideAttribute;
66                 }
67                 
68                 #endregion
69
70                 #region Properties
71
72                 private XmlReader Current {
73                         get { return entity != null && entity.ReadState != ReadState.Initial ? entity : source; }
74                 }
75
76                 public override int AttributeCount {
77                         get { return Current.AttributeCount; }
78                 }
79
80                 public override string BaseURI {
81                         get { return Current.BaseURI; }
82                 }
83
84 #if NET_2_0
85                 public override bool CanReadBinaryContent {
86                         get { return true; }
87                 }
88
89 /*
90                 public override bool CanReadValueChunk {
91                         get { return true; }
92                 }
93 */
94 #else
95                 internal override bool CanReadBinaryContent {
96                         get { return true; }
97                 }
98
99 /*
100                 internal override bool CanReadValueChunk {
101                         get { return true; }
102                 }
103 */
104 #endif
105
106                 public override bool CanResolveEntity {
107                         get { return true; }
108                 }
109
110                 public override int Depth {
111                         get {
112                                 // On EndEntity, depth is the same as that 
113                                 // of EntityReference.
114                                 if (entity != null && entity.ReadState == ReadState.Interactive)
115                                         return source.Depth + entity.Depth + 1;
116                                 else
117                                         return source.Depth;
118                         }
119                 }
120
121                 public override bool EOF {
122                         get { return source.EOF; }
123                 }
124
125                 public override bool HasAttributes {
126                         get { return Current.HasAttributes; }
127                 }
128
129                 public override bool HasValue {
130                         get { return Current.HasValue; }
131                 }
132
133                 public override bool IsDefault {
134                         get { return Current.IsDefault; }
135                 }
136
137                 public override bool IsEmptyElement {
138                         get { return Current.IsEmptyElement; }
139                 }
140
141 #if NET_2_0
142 #else
143                 public override string this [int i] {
144                         get { return GetAttribute (i); }
145                 }
146
147                 public override string this [string name] {
148                         get { return GetAttribute (name); }
149                 }
150
151                 public override string this [string name, string namespaceURI] {
152                         get { return GetAttribute (name, namespaceURI); }
153                 }
154 #endif
155
156                 public override string LocalName {
157                         get { return Current.LocalName; }
158                 }
159
160                 public override string Name {
161                         get { return Current.Name; }
162                 }
163
164                 public override string NamespaceURI {
165                         get { return Current.NamespaceURI; }
166                 }
167
168                 public override XmlNameTable NameTable {
169                         get { return Current.NameTable; }
170                 }
171
172                 public override XmlNodeType NodeType {
173                         get {
174                                 if (Current == entity)
175                                         return entity.EOF ? XmlNodeType.EndEntity : entity.NodeType;
176                                 else
177                                         return source.NodeType;
178                         }
179                 }
180
181                 XmlParserContext IHasXmlParserContext.ParserContext {
182                         get { return ((IHasXmlParserContext) Current).ParserContext; }
183                 }
184
185                 public override string Prefix {
186                         get { return Current.Prefix; }
187                 }
188
189 #if NET_2_0
190 #else
191                 public override char QuoteChar {
192                         get { return '"'; }
193                 }
194 #endif
195
196                 public override ReadState ReadState {
197                         get { return entity != null ? ReadState.Interactive : source.ReadState; }
198                 }
199
200 #if NET_2_0
201                 public override IXmlSchemaInfo SchemaInfo {
202                         get { return entity != null ? entity.SchemaInfo : source.SchemaInfo; }
203                 }
204 #endif
205
206                 public override string Value {
207                         get { return Current.Value; }
208                 }
209
210                 public override string XmlLang {
211                         get { return Current.XmlLang; }
212                 }
213
214                 public override XmlSpace XmlSpace {
215                         get { return Current.XmlSpace; }
216                 }
217                 #endregion
218
219                 #region Methods
220
221                 // If current entityReference is a child of an attribute,
222                 // then MoveToAttribute simply means that we no more need this entity Current.
223                 // Otherwise, this invokation means that
224                 // it is expected to move to resolved (maybe) element's attribute.
225                 //
226                 // This rule applies to many methods like MoveTo*Attribute().
227
228                 public override void Close ()
229                 {
230                         if (entity != null)
231                                 entity.Close ();
232                         source.Close ();
233                 }
234
235                 public override string GetAttribute (int attributeIndex)
236                 {
237                         return Current.GetAttribute (attributeIndex);
238                 }
239
240                 public override string GetAttribute (string name)
241                 {
242                         return Current.GetAttribute (name);
243                 }
244
245                 public override string GetAttribute (string name, string namespaceURI)
246                 {
247                         return Current.GetAttribute (name, namespaceURI);
248                 }
249
250 #if NET_2_0
251                 IDictionary<string, string> IXmlNamespaceResolver.GetNamespacesInScope (XmlNamespaceScope scope)
252                 {
253                         return ((IXmlNamespaceResolver) Current).GetNamespacesInScope (scope);
254                 }
255 #endif
256
257                 public override string LookupNamespace (string prefix)
258                 {
259                         return Current.LookupNamespace (prefix);
260                 }
261
262 #if NET_2_0
263                 string IXmlNamespaceResolver.LookupPrefix (string ns)
264                 {
265                         return ((IXmlNamespaceResolver) Current).LookupPrefix (ns);
266                 }
267 #endif
268
269                 public override void MoveToAttribute (int i)
270                 {
271                         if (entity != null && entityInsideAttribute) {
272                                 entity.Close ();
273                                 entity = null;
274                         }
275                         Current.MoveToAttribute (i);
276                         insideAttribute = true;
277                 }
278
279                 public override bool MoveToAttribute (string name)
280                 {
281                         if (entity != null && !entityInsideAttribute)
282                                 return entity.MoveToAttribute (name);
283                         if (!source.MoveToAttribute (name))
284                                 return false;
285                         if (entity != null && entityInsideAttribute) {
286                                 entity.Close ();
287                                 entity = null;
288                         }
289                         insideAttribute = true;
290                         return true;
291                 }
292
293                 public override bool MoveToAttribute (string localName, string namespaceURI)
294                 {
295                         if (entity != null && !entityInsideAttribute)
296                                 return entity.MoveToAttribute (localName, namespaceURI);
297                         if (!source.MoveToAttribute (localName, namespaceURI))
298                                 return false;
299                         if (entity != null && entityInsideAttribute) {
300                                 entity.Close ();
301                                 entity = null;
302                         }
303                         insideAttribute = true;
304                         return true;
305                 }
306
307                 public override bool MoveToElement ()
308                 {
309                         if (entity != null && entityInsideAttribute)
310                                 entity = null;
311                         if (!Current.MoveToElement ())
312                                 return false;
313                         insideAttribute = false;
314                         return true;
315                 }
316
317                 public override bool MoveToFirstAttribute ()
318                 {
319                         if (entity != null && !entityInsideAttribute)
320                                 return entity.MoveToFirstAttribute ();
321                         if (!source.MoveToFirstAttribute ())
322                                 return false;
323                         if (entity != null && entityInsideAttribute) {
324                                 entity.Close ();
325                                 entity = null;
326                         }
327                         insideAttribute = true;
328                         return true;
329                 }
330
331                 public override bool MoveToNextAttribute ()
332                 {
333                         if (entity != null && !entityInsideAttribute)
334                                 return entity.MoveToNextAttribute ();
335                         if (!source.MoveToNextAttribute ())
336                                 return false;
337                         if (entity != null && entityInsideAttribute) {
338                                 entity.Close ();
339                                 entity = null;
340                         }
341                         insideAttribute = true;
342                         return true;
343                 }
344
345                 public override bool Read ()
346                 {
347                         insideAttribute = false;
348                         if (entity != null && (entityInsideAttribute || entity.EOF))
349                                 entity = null;
350                         if (entity != null) {
351                                 entity.Read ();
352                                 return true; // either success or EndEntity
353                         }
354                         else
355                                 return source.Read ();
356                 }
357
358                 public override bool ReadAttributeValue ()
359                 {
360                         if (entity != null && entityInsideAttribute) {
361                                 if (entity.EOF)
362                                         entity = null;
363                                 else {
364                                         entity.Read ();
365                                         return true; // either success or EndEntity
366                                 }
367                         }
368                         return Current.ReadAttributeValue ();
369                 }
370
371 #if NET_2_0
372                 public override int ReadContentAsBase64 (
373                         byte [] buffer, int offset, int length)
374                 {
375 //                      return base.ReadContentAsBase64 (
376 //                              buffer, offset, length);
377                         // FIXME: This is problematic wrt end of entity.
378                         if (entity != null)
379                                 return entity.ReadContentAsBase64 (
380                                         buffer, offset, length);
381                         else
382                                 return source.ReadContentAsBase64 (
383                                         buffer, offset, length);
384                 }
385
386                 public override int ReadContentAsBinHex (
387                         byte [] buffer, int offset, int length)
388                 {
389 //                      return base.ReadContentAsBinHex (
390 //                              buffer, offset, length);
391                         // FIXME: This is problematic wrt end of entity.
392                         if (entity != null)
393                                 return entity.ReadContentAsBinHex (
394                                         buffer, offset, length);
395                         else
396                                 return source.ReadContentAsBinHex (
397                                         buffer, offset, length);
398                 }
399
400                 public override int ReadElementContentAsBase64 (
401                         byte [] buffer, int offset, int length)
402                 {
403 //                      return base.ReadElementContentAsBase64 (
404 //                              buffer, offset, length);
405                         // FIXME: This is problematic wrt end of entity.
406                         if (entity != null)
407                                 return entity.ReadElementContentAsBase64 (
408                                         buffer, offset, length);
409                         else
410                                 return source.ReadElementContentAsBase64 (
411                                         buffer, offset, length);
412                 }
413
414                 public override int ReadElementContentAsBinHex (
415                         byte [] buffer, int offset, int length)
416                 {
417 //                      return base.ReadElementContentAsBinHex (
418 //                              buffer, offset, length);
419                         // FIXME: This is problematic wrt end of entity.
420                         if (entity != null)
421                                 return entity.ReadElementContentAsBinHex (
422                                         buffer, offset, length);
423                         else
424                                 return source.ReadElementContentAsBinHex (
425                                         buffer, offset, length);
426                 }
427 #endif
428
429 #if NET_1_0
430                 public override string ReadInnerXml ()
431                 {
432                         return ReadInnerXmlInternal ();
433                 }
434
435                 public override string ReadOuterXml ()
436                 {
437                         return ReadOuterXmlInternal ();
438                 }
439 #endif
440
441                 public override string ReadString ()
442                 {
443                         return ReadStringInternal ();
444                 }
445
446                 public override void ResolveEntity ()
447                 {
448                         if (entity != null)
449                                 entity.ResolveEntity ();
450                         else {
451                                 if (source.NodeType != XmlNodeType.EntityReference)
452                                         throw new InvalidOperationException ("The current node is not an Entity Reference");
453                                 entity = new XmlNodeReader (source, insideAttribute);
454                         }
455                 }
456
457                 public override void Skip ()
458                 {
459                         if (entity != null && entityInsideAttribute)
460                                 entity = null;
461                         Current.Skip ();
462                 }
463                 #endregion
464         }
465 }