* Makefile: Don't build make-map.exe.
[mono.git] / mcs / class / System.XML / System.Xml / XmlTextReader2.cs
1 //
2 // System.Xml.XmlTextReader2.cs - XmlTextReader for .NET 2.0
3 //
4 // Author:
5 //   Atsushi Enomoto  (ginga@kit.hi-ho.ne.jp)
6 //
7 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 #if NET_2_0
30
31 using XmlTextReaderImpl = Mono.Xml2.XmlTextReader;
32
33 using System.Collections.Generic;
34 using System.Globalization;
35 using System.IO;
36 using System.Security.Permissions;
37 using System.Text;
38 using System.Xml.Schema;
39 using Mono.Xml;
40
41 namespace System.Xml
42 {
43         [PermissionSet (SecurityAction.InheritanceDemand, Unrestricted = true)]
44         public class XmlTextReader : XmlReader,
45                 IXmlLineInfo, IXmlNamespaceResolver, IHasXmlParserContext
46         {
47                 XmlTextReader entity;
48                 XmlTextReaderImpl source; // dtd2xsd expects this field's existence.
49                 bool entityInsideAttribute;
50                 bool insideAttribute;
51                 Stack<string> entityNameStack;
52
53                 protected XmlTextReader ()
54                 {
55                 }
56
57                 public XmlTextReader (Stream input)
58                         : this (new XmlStreamReader (input))
59                 {
60                 }
61
62                 public XmlTextReader (string url)
63                         : this(url, new NameTable ())
64                 {
65                 }
66
67                 public XmlTextReader (TextReader input)
68                         : this (input, new NameTable ())
69                 {
70                 }
71
72                 protected XmlTextReader (XmlNameTable nt)
73                         : this (String.Empty, XmlNodeType.Element, null)
74                 {
75                 }
76
77                 public XmlTextReader (Stream input, XmlNameTable nt)
78                         : this(new XmlStreamReader (input), nt)
79                 {
80                 }
81
82                 public XmlTextReader (string url, Stream input)
83                         : this (url, new XmlStreamReader (input))
84                 {
85                 }
86
87                 public XmlTextReader (string url, TextReader input)
88                         : this (url, input, new NameTable ())
89                 {
90                 }
91
92                 public XmlTextReader (string url, XmlNameTable nt)
93                 {
94                         source = new XmlTextReaderImpl (url, nt);
95                 }
96
97                 public XmlTextReader (TextReader input, XmlNameTable nt)
98                         : this (String.Empty, input, nt)
99                 {
100                 }
101
102                 public XmlTextReader (Stream xmlFragment, XmlNodeType fragType, XmlParserContext context)
103                 {
104                         source = new XmlTextReaderImpl (xmlFragment, fragType, context);
105                 }
106
107                 public XmlTextReader (string url, Stream input, XmlNameTable nt)
108                         : this (url, new XmlStreamReader (input), nt)
109                 {
110                 }
111
112                 public XmlTextReader (string url, TextReader input, XmlNameTable nt)
113                 {
114                         source = new XmlTextReaderImpl (url, input, nt);
115                 }
116
117                 public XmlTextReader (string xmlFragment, XmlNodeType fragType, XmlParserContext context)
118                 {
119                         source = new XmlTextReaderImpl (xmlFragment, fragType, context);
120                 }
121
122                 internal XmlTextReader (string baseURI, TextReader xmlFragment, XmlNodeType fragType)
123                 {
124                         source = new XmlTextReaderImpl (baseURI, xmlFragment, fragType);
125                 }
126
127                 internal XmlTextReader (string baseURI, TextReader xmlFragment, XmlNodeType fragType, XmlParserContext context)
128                 {
129                         source = new XmlTextReaderImpl (baseURI, xmlFragment, fragType, context);
130                 }
131
132                 internal XmlTextReader (bool dummy, string url, XmlNodeType fragType, XmlParserContext context)
133                 {
134                         source = new XmlTextReaderImpl (dummy, url, fragType, context);
135                 }
136
137                 private XmlTextReader (XmlTextReaderImpl entityContainer, bool insideAttribute)
138                 {
139                         source = entityContainer;
140                         this.entityInsideAttribute = insideAttribute;
141                 }
142
143                 #region Properties
144
145                 private XmlReader Current {
146                         get { return entity != null && entity.ReadState != ReadState.Initial ? (XmlReader) entity : source; }
147                 }
148
149                 public override int AttributeCount {
150                         get { return Current.AttributeCount; }
151                 }
152
153                 public override string BaseURI {
154                         get { return Current.BaseURI; }
155                 }
156
157                 public override bool CanReadBinaryContent {
158                         get { return true; }
159                 }
160
161                 public override bool CanReadValueChunk {
162                         get { return true; }
163                 }
164
165                 public override bool CanResolveEntity {
166                         get { return true; }
167                 }
168
169                 public override int Depth {
170                         get {
171                                 // On EndEntity, depth is the same as that 
172                                 // of EntityReference.
173                                 if (entity != null && entity.ReadState == ReadState.Interactive)
174                                         return source.Depth + entity.Depth + 1;
175                                 else
176                                         return source.Depth;
177                         }
178                 }
179
180                 public override bool EOF {
181                         get { return source.EOF; }
182                 }
183
184                 public override bool HasValue {
185                         get { return Current.HasValue; }
186                 }
187
188                 public override bool IsDefault {
189                         get { return Current.IsDefault; }
190                 }
191
192                 public override bool IsEmptyElement {
193                         get { return Current.IsEmptyElement; }
194                 }
195
196                 public override string LocalName {
197                         get { return Current.LocalName; }
198                 }
199
200                 public override string Name {
201                         get { return Current.Name; }
202                 }
203
204                 public override string NamespaceURI {
205                         get { return Current.NamespaceURI; }
206                 }
207
208                 public override XmlNameTable NameTable {
209                         get { return Current.NameTable; }
210                 }
211
212                 public override XmlNodeType NodeType {
213                         get {
214                                 if (entity != null)
215                                         return entity.ReadState == ReadState.Initial ?
216                                                 source.NodeType :
217                                                 entity.EOF ? XmlNodeType.EndEntity :
218                                                 entity.NodeType;
219                                 else
220                                         return source.NodeType;
221                         }
222                 }
223
224                 internal XmlParserContext ParserContext {
225                         get { return ((IHasXmlParserContext) Current).ParserContext; }
226                 }
227
228                 XmlParserContext IHasXmlParserContext.ParserContext {
229                         get { return this.ParserContext; }
230                 }
231
232                 public override string Prefix {
233                         get { return Current.Prefix; }
234                 }
235
236                 public override char QuoteChar {
237                         get { return Current.QuoteChar; }
238                 }
239
240                 public override ReadState ReadState {
241                         get { return entity != null ? ReadState.Interactive : source.ReadState; }
242                 }
243
244                 public override XmlReaderSettings Settings {
245                         get { return base.Settings; }
246                 }
247
248                 public override string Value {
249                         get { return Current.Value; }
250                 }
251
252                 public override string XmlLang {
253                         get { return Current.XmlLang; }
254                 }
255
256                 public override XmlSpace XmlSpace {
257                         get { return Current.XmlSpace; }
258                 }
259
260                 // non-overrides
261
262                 internal bool CharacterChecking {
263                         get {
264                                 if (entity != null)
265                                         return entity.CharacterChecking;
266                                 else
267                                         return source.CharacterChecking;
268                         }
269                         set {
270                                 if (entity != null)
271                                         entity.CharacterChecking = value;
272                                 source.CharacterChecking = value;
273                         }
274                 }
275
276                 internal bool CloseInput {
277                         get {
278                                 if (entity != null)
279                                         return entity.CloseInput;
280                                 else
281                                         return source.CloseInput;
282                         }
283                         set {
284                                 if (entity != null)
285                                         entity.CloseInput = value;
286                                 source.CloseInput = value;
287                         }
288                 }
289
290                 internal ConformanceLevel Conformance {
291                         get { return source.Conformance; }
292                         set {
293                                 if (entity != null)
294                                         entity.Conformance = value;
295                                 source.Conformance = value;
296                         }
297                 }
298
299                 internal XmlResolver Resolver {
300                         get { return source.Resolver; }
301                 }
302
303                 private void CopyProperties (XmlTextReader other)
304                 {
305                         CharacterChecking = other.CharacterChecking;
306                         CloseInput = other.CloseInput;
307                         if (other.Settings != null)
308                                 Conformance = other.Settings.ConformanceLevel;
309                         XmlResolver = other.Resolver;
310                 }
311
312                 // public members
313
314                 public Encoding Encoding {
315                         get {
316                                 if (entity != null)
317                                         return entity.Encoding;
318                                 else
319                                         return source.Encoding;
320                         }
321                 }
322
323                 public EntityHandling EntityHandling {
324                         get { return source.EntityHandling; }
325                         set {
326                                 if (entity != null)
327                                         entity.EntityHandling = value;
328                                 source.EntityHandling = value;
329                         }
330                 }
331
332                 public int LineNumber {
333                         get {
334                                 if (entity != null)
335                                         return entity.LineNumber;
336                                 else
337                                         return source.LineNumber;
338                         }
339                 }
340
341                 public int LinePosition {
342                         get {
343                                 if (entity != null)
344                                         return entity.LinePosition;
345                                 else
346                                         return source.LinePosition;
347                         }
348                 }
349
350                 public bool Namespaces {
351                         get { return source.Namespaces; }
352                         set {
353                                 if (entity != null)
354                                         entity.Namespaces = value;
355                                 source.Namespaces = value;
356                         }
357                 }
358
359                 public bool Normalization {
360                         get { return source.Normalization; }
361                         set {
362                                 if (entity != null)
363                                         entity.Normalization = value;
364                                 source.Normalization = value;
365                         }
366                 }
367
368                 public bool ProhibitDtd {
369                         get { return source.ProhibitDtd; }
370                         set {
371                                 if (entity != null)
372                                         entity.ProhibitDtd = value;
373                                 source.ProhibitDtd = value;
374                         }
375                 }
376
377                 public WhitespaceHandling WhitespaceHandling {
378                         get { return source.WhitespaceHandling; }
379                         set {
380                                 if (entity != null)
381                                         entity.WhitespaceHandling = value;
382                                 source.WhitespaceHandling = value;
383                         }
384                 }
385
386                 public XmlResolver XmlResolver {
387                         set {
388                                 if (entity != null)
389                                         entity.XmlResolver = value;
390                                 source.XmlResolver = value;
391                         }
392                 }
393
394                 #endregion
395
396                 #region Methods
397
398                 internal void AdjustLineInfoOffset (int lineNumberOffset, int linePositionOffset)
399                 {
400                         if (entity != null)
401                                 entity.AdjustLineInfoOffset (lineNumberOffset, linePositionOffset);
402                         source.AdjustLineInfoOffset (lineNumberOffset, linePositionOffset);
403                 }
404
405                 internal void SetNameTable (XmlNameTable nameTable)
406                 {
407                         if (entity != null)
408                                 entity.SetNameTable (nameTable);
409                         source.SetNameTable (nameTable);
410                 }
411
412                 internal void SkipTextDeclaration ()
413                 {
414                         if (entity != null)
415                                 entity.SkipTextDeclaration ();
416                         else
417                                 source.SkipTextDeclaration ();
418                 }
419
420                 // overrides
421
422                 public override void Close ()
423                 {
424                         if (entity != null)
425                                 entity.Close ();
426                         source.Close ();
427                 }
428
429                 public override string GetAttribute (int i)
430                 {
431                         return Current.GetAttribute (i);
432                 }
433
434                 // MS.NET 1.0 msdn says that this method returns String.Empty
435                 // for absent attribute, but in fact it returns null.
436                 // This description is corrected in MS.NET 1.1 msdn.
437                 public override string GetAttribute (string name)
438                 {
439                         return Current.GetAttribute (name);
440                 }
441
442                 public override string GetAttribute (string localName, string namespaceURI)
443                 {
444                         return Current.GetAttribute (localName, namespaceURI);
445                 }
446
447                 public IDictionary<string, string> GetNamespacesInScope (XmlNamespaceScope scope)
448                 {
449                         return ((IXmlNamespaceResolver) Current).GetNamespacesInScope (scope);
450                 }
451
452                 IDictionary<string, string> IXmlNamespaceResolver.GetNamespacesInScope (XmlNamespaceScope scope)
453                 {
454                         return GetNamespacesInScope (scope);
455                 }
456
457                 public override string LookupNamespace (string prefix)
458                 {
459                         return Current.LookupNamespace (prefix);
460                 }
461
462                 string IXmlNamespaceResolver.LookupPrefix (string ns)
463                 {
464                         return ((IXmlNamespaceResolver) Current).LookupPrefix (ns);
465                 }
466
467                 public override void MoveToAttribute (int i)
468                 {
469                         if (entity != null && entityInsideAttribute)
470                                 CloseEntity ();
471                         Current.MoveToAttribute (i);
472                         insideAttribute = true;
473                 }
474
475                 public override bool MoveToAttribute (string name)
476                 {
477                         if (entity != null && !entityInsideAttribute)
478                                 return entity.MoveToAttribute (name);
479                         if (!source.MoveToAttribute (name))
480                                 return false;
481                         if (entity != null && entityInsideAttribute)
482                                 CloseEntity ();
483                         insideAttribute = true;
484                         return true;
485                 }
486
487                 public override bool MoveToAttribute (string localName, string namespaceName)
488                 {
489                         if (entity != null && !entityInsideAttribute)
490                                 return entity.MoveToAttribute (localName, namespaceName);
491                         if (!source.MoveToAttribute (localName, namespaceName))
492                                 return false;
493                         if (entity != null && entityInsideAttribute)
494                                 CloseEntity ();
495                         insideAttribute = true;
496                         return true;
497                 }
498
499                 public override bool MoveToElement ()
500                 {
501                         if (entity != null && entityInsideAttribute)
502                                 CloseEntity ();
503                         if (!Current.MoveToElement ())
504                                 return false;
505                         insideAttribute = false;
506                         return true;
507                 }
508
509                 public override bool MoveToFirstAttribute ()
510                 {
511                         if (entity != null && !entityInsideAttribute)
512                                 return entity.MoveToFirstAttribute ();
513                         if (!source.MoveToFirstAttribute ())
514                                 return false;
515                         if (entity != null && entityInsideAttribute)
516                                 CloseEntity ();
517                         insideAttribute = true;
518                         return true;
519                 }
520
521                 public override bool MoveToNextAttribute ()
522                 {
523                         if (entity != null && !entityInsideAttribute)
524                                 return entity.MoveToNextAttribute ();
525                         if (!source.MoveToNextAttribute ())
526                                 return false;
527                         if (entity != null && entityInsideAttribute)
528                                 CloseEntity ();
529                         insideAttribute = true;
530                         return true;
531                 }
532
533                 public override bool Read ()
534                 {
535                         insideAttribute = false;
536
537                         if (entity != null && (entityInsideAttribute || entity.EOF))
538                                 CloseEntity ();
539                         if (entity != null) {
540                                 if (entity.Read ())
541                                         return true;
542                                 if (EntityHandling == EntityHandling.ExpandEntities) {
543                                         // EndEntity must be skipped
544                                         CloseEntity ();
545                                         return Read ();
546                                 }
547                                 else
548                                         return true; // either success or EndEntity
549                         }
550                         else {
551                                 if (!source.Read ())
552                                         return false;
553                                 if (EntityHandling == EntityHandling.ExpandEntities
554                                         && source.NodeType == XmlNodeType.EntityReference) {
555                                         ResolveEntity ();
556                                         return Read ();
557                                 }
558                                 return true;
559                         }
560                 }
561
562                 public override bool ReadAttributeValue ()
563                 {
564                         if (entity != null && entityInsideAttribute) {
565                                 if (entity.EOF)
566                                         CloseEntity ();
567                                 else {
568                                         entity.Read ();
569                                         return true; // either success or EndEntity
570                                 }
571                         }
572                         return Current.ReadAttributeValue ();
573                 }
574
575                 public override string ReadString ()
576                 {
577                         return base.ReadString ();
578                 }
579
580                 public void ResetState ()
581                 {
582                         if (entity != null)
583                                 entity.ResetState ();
584                         source.ResetState ();
585                 }
586
587                 public override void ResolveEntity ()
588                 {
589                         if (entity != null)
590                                 entity.ResolveEntity ();
591                         else {
592                                 if (source.NodeType != XmlNodeType.EntityReference)
593                                         throw new InvalidOperationException ("The current node is not an Entity Reference");
594                                 XmlTextReaderImpl entReader = 
595                                         ParserContext.Dtd.GenerateEntityContentReader (source.Name, ParserContext);
596                                 if (entReader == null)
597                                         throw new XmlException (this as IXmlLineInfo, this.BaseURI, String.Format ("Reference to undeclared entity '{0}'.", source.Name));
598                                 if (entityNameStack == null)
599                                         entityNameStack = new Stack<string> ();
600                                 else if (entityNameStack.Contains (Name))
601                                         throw new XmlException (String.Format ("General entity '{0}' has an invalid recursive reference to itself.", Name));
602                                 entityNameStack.Push (Name);
603                                 entity = new XmlTextReader (
604                                         entReader, insideAttribute);
605                                 entity.entityNameStack = entityNameStack;
606                                 entity.CopyProperties (this);
607                         }
608                 }
609
610                 void CloseEntity ()
611                 {
612                         entity.Close ();
613                         entity = null;
614                         entityNameStack.Pop ();
615                 }
616
617                 public override void Skip ()
618                 {
619                         base.Skip ();
620                 }
621
622                 [MonoTODO ("Check how expanded entity is handled here.")]
623                 public TextReader GetRemainder ()
624                 {
625                         if (entity != null) {
626                                 entity.Close ();
627                                 entity = null;
628                                 entityNameStack.Pop ();
629                         }
630                         return source.GetRemainder ();
631                 }
632
633                 public bool HasLineInfo ()
634                 {
635                         return true;
636                 }
637
638                 [MonoTODO ("Check how expanded entity is handled here.")]
639                 public int ReadBase64 (byte [] buffer, int offset, int length)
640                 {
641                         if (entity != null)
642                                 return entity.ReadBase64 (buffer, offset, length);
643                         else
644                                 return source.ReadBase64 (buffer, offset, length);
645                 }
646
647                 [MonoTODO ("Check how expanded entity is handled here.")]
648                 public int ReadBinHex (byte [] buffer, int offset, int length)
649                 {
650                         if (entity != null)
651                                 return entity.ReadBinHex (buffer, offset, length);
652                         else
653                                 return source.ReadBinHex (buffer, offset, length);
654                 }
655
656                 [MonoTODO ("Check how expanded entity is handled here.")]
657                 public int ReadChars (char [] buffer, int offset, int length)
658                 {
659                         if (entity != null)
660                                 return entity.ReadChars (buffer, offset, length);
661                         else
662                                 return source.ReadChars (buffer, offset, length);
663                 }
664
665
666                 [MonoTODO ("Check how expanded entity is handled here.")]
667                 public override int ReadContentAsBase64 (byte [] buffer, int offset, int length)
668                 {
669                         if (entity != null)
670                                 return entity.ReadContentAsBase64 (buffer, offset, length);
671                         else
672                                 return source.ReadContentAsBase64 (buffer, offset, length);
673                 }
674
675                 [MonoTODO ("Check how expanded entity is handled here.")]
676                 public override int ReadContentAsBinHex (byte [] buffer, int offset, int length)
677                 {
678                         if (entity != null)
679                                 return entity.ReadContentAsBinHex (buffer, offset, length);
680                         else
681                                 return source.ReadContentAsBinHex (buffer, offset, length);
682                 }
683
684                 [MonoTODO ("Check how expanded entity is handled here.")]
685                 public override int ReadElementContentAsBase64 (byte [] buffer, int offset, int length)
686                 {
687                         if (entity != null)
688                                 return entity.ReadElementContentAsBase64 (buffer, offset, length);
689                         else
690                                 return source.ReadElementContentAsBase64 (buffer, offset, length);
691                 }
692
693                 [MonoTODO ("Check how expanded entity is handled here.")]
694                 public override int ReadElementContentAsBinHex (byte [] buffer, int offset, int length)
695                 {
696                         if (entity != null)
697                                 return entity.ReadElementContentAsBinHex (buffer, offset, length);
698                         else
699                                 return source.ReadElementContentAsBinHex (buffer, offset, length);
700                 }
701                 #endregion
702         }
703 }
704
705 #endif