When compiling CORLIB: pass the INSIDE_CORLIB setting, so X509Certificate class is...
[mono.git] / mcs / class / System.XML / System.Xml / DTDObjectModel.cs
1 //
2 // Mono.Xml.DTDObjectModel
3 //
4 // Author:
5 //      Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
6 //
7 //      (C)2003 Atsushi Enomoto
8 //
9 using System;
10 using System.Collections;
11 using System.Collections.Specialized;
12 using System.Globalization;
13 using System.IO;
14 using System.Text;
15 using System.Xml;
16 using System.Xml.Schema;
17 using Mono.Xml.Schema;
18 using Mono.Xml.Native;
19
20 namespace Mono.Xml
21 {
22         public class DTDObjectModel
23         {
24                 DTDElementDeclarationCollection elementDecls;
25                 DTDAttListDeclarationCollection attListDecls;
26                 DTDEntityDeclarationCollection entityDecls;
27                 DTDNotationDeclarationCollection notationDecls;
28                 ArrayList validationErrors;
29                 XmlResolver resolver;
30
31                 public DTDObjectModel ()
32                 {
33                         elementDecls = new DTDElementDeclarationCollection (this);
34                         attListDecls = new DTDAttListDeclarationCollection (this);
35                         entityDecls = new DTDEntityDeclarationCollection (this);
36                         notationDecls = new DTDNotationDeclarationCollection (this);
37                         factory = new DTDAutomataFactory (this);
38                         validationErrors = new ArrayList ();
39                 }
40
41                 public string BaseURI;
42
43                 public string Name;
44                 
45                 public string PublicId;
46                 
47                 public string SystemId;
48                 
49                 public string InternalSubset;
50
51                 public bool InternalSubsetHasPEReference;
52                 
53                 public string ResolveEntity (string name)
54                 {
55                         DTDEntityDeclaration decl = EntityDecls [name] 
56                                 as DTDEntityDeclaration;
57                         return decl.EntityValue;
58                 }
59
60                 internal XmlResolver Resolver {
61                         get { return resolver; }
62                 }
63
64                 public XmlResolver XmlResolver {
65                         set { resolver = value; }
66                 }
67
68                 private DTDAutomataFactory factory;
69                 public DTDAutomataFactory Factory {
70                         get { return factory; }
71                 }
72
73                 public DTDElementDeclaration RootElement {
74                         get { return ElementDecls [Name]; }
75                 }
76
77                 public DTDElementDeclarationCollection ElementDecls {
78                         get { return elementDecls; }
79                 }
80
81                 public DTDAttListDeclarationCollection AttListDecls {
82                         get { return attListDecls; }
83                 }
84
85                 public DTDEntityDeclarationCollection EntityDecls {
86                         get { return entityDecls; }
87                 }
88
89                 public DTDNotationDeclarationCollection NotationDecls {
90                         get { return notationDecls; }
91                 }
92
93                 DTDElementAutomata rootAutomata;
94                 public DTDAutomata RootAutomata {
95                         get {
96                                 if (rootAutomata == null)
97                                         rootAutomata = new DTDElementAutomata (this, this.Name);
98                                 return rootAutomata;
99                         }
100                 }
101
102                 DTDEmptyAutomata emptyAutomata;
103                 public DTDEmptyAutomata Empty {
104                         get {
105                                 if (emptyAutomata == null)
106                                         emptyAutomata = new DTDEmptyAutomata (this);
107                                 return emptyAutomata;
108                         }
109                 }
110
111                 DTDAnyAutomata anyAutomata;
112                 public DTDAnyAutomata Any {
113                         get {
114                                 if (anyAutomata == null)
115                                         anyAutomata = new DTDAnyAutomata (this);
116                                 return anyAutomata;
117                         }
118                 }
119
120                 DTDInvalidAutomata invalidAutomata;
121                 public DTDInvalidAutomata Invalid {
122                         get {
123                                 if (invalidAutomata == null)
124                                         invalidAutomata = new DTDInvalidAutomata (this);
125                                 return invalidAutomata;
126                         }
127                 }
128
129                 public XmlSchemaException [] Errors {
130                         get { return validationErrors.ToArray (typeof (XmlSchemaException)) as XmlSchemaException []; }
131                 }
132
133                 public void AddError (XmlSchemaException ex)
134                 {
135                         validationErrors.Add (ex);
136                 }
137         }
138
139         public class DTDElementDeclarationCollection
140         {
141                 Hashtable elementDecls = new Hashtable ();
142                 DTDObjectModel root;
143
144                 public DTDElementDeclarationCollection (DTDObjectModel root)
145                 {
146                         this.root = root;
147                 }
148
149                 public DTDElementDeclaration this [string name] {
150                         get { return elementDecls [name] as DTDElementDeclaration; }
151                 }
152
153                 public void Add (string name, DTDElementDeclaration decl)
154                 {
155                         if (elementDecls [name] != null) {
156                                 this.root.AddError (new XmlSchemaException (String.Format (
157                                         "Element declaration for {0} was already added.",
158                                         name), null));
159                                 return;
160                         }
161                         decl.SetRoot (root);
162                         elementDecls.Add (name, decl);
163                 }
164
165                 public ICollection Keys {
166                         get { return elementDecls.Keys; }
167                 }
168
169                 public ICollection Values {
170                         get { return elementDecls.Values; }
171                 }
172         }
173
174         public class DTDAttListDeclarationCollection
175         {
176                 Hashtable attListDecls = new Hashtable ();
177                 DTDObjectModel root;
178
179                 public DTDAttListDeclarationCollection (DTDObjectModel root)
180                 {
181                         this.root = root;
182                 }
183
184                 public DTDAttListDeclaration this [string name] {
185                         get { return attListDecls [name] as DTDAttListDeclaration; }
186                 }
187
188                 public void Add (string name, DTDAttListDeclaration decl)
189                 {
190                         DTDAttListDeclaration existing = this [name];
191                         if (existing != null) {
192                                 // It should be valid and 
193                                 // has effect of additive declaration.
194                                 foreach (DTDAttributeDefinition def in decl.Definitions)
195                                         if (decl.Get (def.Name) == null)
196                                                 existing.Add (def);
197                         } else {
198                                 decl.SetRoot (root);
199                                 attListDecls.Add (name, decl);
200                         }
201                 }
202
203                 public ICollection Keys {
204                         get { return attListDecls.Keys; }
205                 }
206
207                 public ICollection Values {
208                         get { return attListDecls.Values; }
209                 }
210         }
211
212         public class DTDEntityDeclarationCollection
213         {
214                 Hashtable entityDecls = new Hashtable ();
215                 DTDObjectModel root;
216
217                 public DTDEntityDeclarationCollection (DTDObjectModel root)
218                 {
219                         this.root = root;
220                 }
221
222                 public DTDEntityDeclaration this [string name] {
223                         get { return entityDecls [name] as DTDEntityDeclaration; }
224                 }
225
226                 public void Add (string name, DTDEntityDeclaration decl)
227                 {
228                         if (entityDecls [name] != null)
229                                 throw new InvalidOperationException (String.Format (
230                                         "Entity declaration for {0} was already added.",
231                                         name));
232                         decl.SetRoot (root);
233                         entityDecls.Add (name, decl);
234                 }
235
236                 public ICollection Keys {
237                         get { return entityDecls.Keys; }
238                 }
239
240                 public ICollection Values {
241                         get { return entityDecls.Values; }
242                 }
243         }
244
245         public class DTDNotationDeclarationCollection
246         {
247                 Hashtable notationDecls = new Hashtable ();
248                 DTDObjectModel root;
249
250                 public DTDNotationDeclarationCollection (DTDObjectModel root)
251                 {
252                         this.root = root;
253                 }
254
255                 public DTDNotationDeclaration this [string name] {
256                         get { return notationDecls [name] as DTDNotationDeclaration; }
257                 }
258
259                 public void Add (string name, DTDNotationDeclaration decl)
260                 {
261                         if (notationDecls [name] != null)
262                                 throw new InvalidOperationException (String.Format (
263                                         "Notation declaration for {0} was already added.",
264                                         name));
265                         decl.SetRoot (root);
266                         notationDecls.Add (name, decl);
267                 }
268
269                 public ICollection Keys {
270                         get { return notationDecls.Keys; }
271                 }
272
273                 public ICollection Values {
274                         get { return notationDecls.Values; }
275                 }
276         }
277
278         public class DTDContentModel
279         {
280                 private DTDObjectModel root;
281                 DTDAutomata compiledAutomata;
282
283                 private string ownerElementName;
284                 public string ElementName;
285                 public DTDContentOrderType OrderType = DTDContentOrderType.None;
286                 public DTDContentModelCollection ChildModels 
287                         = new DTDContentModelCollection ();
288                 public DTDOccurence Occurence = DTDOccurence.One;
289
290                 internal DTDContentModel (DTDObjectModel root, string ownerElementName)
291                 {
292                         this.root = root;
293                         this.ownerElementName = ownerElementName;
294                 }
295
296                 public DTDElementDeclaration ElementDecl {
297                         get {
298                               return root.ElementDecls [ownerElementName];
299                         }
300                 }
301
302                 public DTDAutomata GetAutomata ()
303                 {
304                         if (compiledAutomata == null)
305                                 Compile ();
306                         return compiledAutomata;
307                 }
308
309                 public DTDAutomata Compile ()
310                 {
311                         compiledAutomata = CompileInternal ();
312                         return compiledAutomata;
313                 }
314
315                 private DTDAutomata CompileInternal ()
316                 {
317                         if (ElementDecl.IsAny)
318                                 return root.Any;
319                         if (ElementDecl.IsEmpty)
320                                 return root.Empty;
321
322                         DTDAutomata basis = GetBasicContentAutomata ();
323                         switch (Occurence) {
324                         case DTDOccurence.One:
325                                 return basis;
326                         case DTDOccurence.Optional:
327                                 return Choice (root.Empty, basis);
328                         case DTDOccurence.OneOrMore:
329                                 return new DTDOneOrMoreAutomata (root, basis);
330                         case DTDOccurence.ZeroOrMore:
331                                 return Choice (root.Empty, new DTDOneOrMoreAutomata (root, basis));
332                         }
333                         throw new InvalidOperationException ();
334                 }
335
336                 private DTDAutomata GetBasicContentAutomata ()
337                 {
338                         if (ElementName != null)
339                                 return new DTDElementAutomata (root, ElementName);
340                         switch (ChildModels.Count) {
341                         case 0:
342                                 return root.Empty;
343                         case 1:
344                                 return ChildModels [0].GetAutomata ();
345                         }
346
347                         DTDAutomata current = null;
348                         int childCount = ChildModels.Count;
349                         switch (OrderType) {
350                         case DTDContentOrderType.Seq:
351                                 current = Sequence (
352                                         ChildModels [childCount - 2].GetAutomata (),
353                                         ChildModels [childCount - 1].GetAutomata ());
354                                 for (int i = childCount - 2; i > 0; i--)
355                                         current = Sequence (
356                                                 ChildModels [i - 1].GetAutomata (), current);
357                                 return current;
358                         case DTDContentOrderType.Or:
359                                 current = Choice (
360                                         ChildModels [childCount - 2].GetAutomata (),
361                                         ChildModels [childCount - 1].GetAutomata ());
362                                 for (int i = childCount - 2; i > 0; i--)
363                                         current = Choice (
364                                                 ChildModels [i - 1].GetAutomata (), current);
365                                 return current;
366                         default:
367                                 throw new InvalidOperationException ("Invalid pattern specification");
368                         }
369                 }
370
371                 private DTDAutomata Sequence (DTDAutomata l, DTDAutomata r)
372                 {
373                         return root.Factory.Sequence (l, r);
374                 }
375
376                 private DTDAutomata Choice (DTDAutomata l, DTDAutomata r)
377                 {
378                         return l.MakeChoice (r);
379                 }
380
381         }
382
383         public class DTDContentModelCollection
384         {
385                 ArrayList contentModel = new ArrayList ();
386
387                 public DTDContentModelCollection ()
388                 {
389                 }
390
391                 public DTDContentModel this [int i] {
392                         get { return contentModel [i] as DTDContentModel; }
393                 }
394
395                 public int Count {
396                         get { return contentModel.Count; }
397                 }
398
399                 public void Add (DTDContentModel model)
400                 {
401                         contentModel.Add (model);
402                 }
403         }
404
405         public abstract class DTDNode
406         {
407                 private DTDObjectModel root;
408                 public string BaseURI;
409                 public int LineNumber;
410                 public int LinePosition;
411
412                 internal void SetRoot (DTDObjectModel root)
413                 {
414                         this.root = root;
415                         if (BaseURI == null)
416                                 this.BaseURI = root.BaseURI;
417                 }
418
419                 protected DTDObjectModel Root {
420                         get { return root; }
421                 }
422         }
423
424         public class DTDElementDeclaration : DTDNode // : ICloneable
425         {
426                 public string Name;
427                 public bool IsEmpty;
428                 public bool IsAny;
429                 public bool IsMixedContent;
430                 public DTDContentModel contentModel;
431                 DTDObjectModel root;
432
433                 internal DTDElementDeclaration (DTDObjectModel root)
434                 {
435                         this.root = root;
436                 }
437
438                 public DTDContentModel ContentModel {
439                         get {
440                                 if (contentModel == null)
441                                         contentModel = new DTDContentModel (root, Name);
442                                 return contentModel;
443                         }
444                 }
445
446                 public DTDAttListDeclaration Attributes {
447                         get {
448                                 return Root.AttListDecls [Name];
449                         }
450                 }
451
452 //              public object Clone ()
453 //              {
454 //                      return this.MemberwiseClone ();
455 //              }
456         }
457
458         public class DTDAttributeDefinition : DTDNode// : ICloneable
459         {
460                 public string Name;
461                 public XmlSchemaDatatype Datatype;
462                 // entity reference inside enumerated values are not allowed,
463                 // but on the other hand, they are allowed inside default value.
464                 // Then I decided to use string ArrayList for enumerated values,
465                 // and unresolved string value for DefaultValue.
466                 public ArrayList EnumeratedAttributeDeclaration = new ArrayList ();
467                 public string UnresolvedDefaultValue = null;
468                 public ArrayList EnumeratedNotations = new ArrayList();
469                 public DTDAttributeOccurenceType OccurenceType = DTDAttributeOccurenceType.None;
470                 private string resolvedDefaultValue;
471                 private string resolvedNormalizedDefaultValue;
472
473                 internal DTDAttributeDefinition () {}
474
475                 public string DefaultValue {
476                         get {
477                                 if (resolvedDefaultValue == null)
478                                         resolvedDefaultValue = ComputeDefaultValue ();
479                                 return resolvedDefaultValue;
480                         }
481                 }
482
483                 public string NormalizedDefaultValue {
484                         get {
485                                 if (resolvedNormalizedDefaultValue == null) {
486                                         object o = Datatype.ParseValue (ComputeDefaultValue (), null, null);
487                                         resolvedNormalizedDefaultValue = 
488                                                 (o is string []) ? 
489                                                 String.Join (" ", (string []) o) :
490                                                 o.ToString ();
491                                 }
492                                 return resolvedNormalizedDefaultValue;
493                         }
494                 }
495
496                 private string ComputeDefaultValue ()
497                 {
498                         if (UnresolvedDefaultValue == null)
499                                 return null;
500
501                         StringBuilder sb = new StringBuilder ();
502                         int pos = 0;
503                         int next = 0;
504                         string value = this.UnresolvedDefaultValue;
505                         while ((next = value.IndexOf ('&', pos)) >= 0) {
506                                 int semicolon = value.IndexOf (';', next);
507                                 if (value [next + 1] == '#') {
508                                         // character reference.
509                                         char c = value [next + 2];
510                                         NumberStyles style = NumberStyles.Integer;
511                                         string spec;
512                                         if (c == 'x' || c == 'X') {
513                                                 spec = value.Substring (next + 3, semicolon - next - 3);
514                                                 style |= NumberStyles.HexNumber;
515                                         }
516                                         else
517                                                 spec = value.Substring (next + 2, semicolon - next - 2);
518                                         sb.Append ((char) int.Parse (spec, style));
519                                 } else {
520                                         sb.Append (value.Substring (pos, next - 1));
521                                         string name = value.Substring (pos + 1, semicolon - 1);
522                                         char predefined = XmlChar.GetPredefinedEntity (name);
523                                         if (predefined != 0)
524                                                 sb.Append (predefined);
525                                         else
526                                                 sb.Append (Root.ResolveEntity (name));
527                                 }
528                                 pos = semicolon + 1;
529                         }
530                         sb.Append (value.Substring (pos));
531                         // strip quote chars
532                         string ret = sb.ToString (1, sb.Length - 2);
533                         sb.Length = 0;
534                         return ret;
535                 }
536
537                 public char QuoteChar {
538                         get {
539                                 return UnresolvedDefaultValue.Length > 0 ?
540                                         this.UnresolvedDefaultValue [0] :
541                                         '"';
542                         }
543                 }
544
545 //              public object Clone ()
546 //              {
547 //                      return this.MemberwiseClone ();
548 //              }
549         }
550
551         public class DTDAttListDeclaration : DTDNode // : ICloneable
552         {
553                 public string Name;
554
555                 internal DTDAttListDeclaration (DTDObjectModel root)
556                 {
557                         SetRoot (root);
558                 }
559
560                 private Hashtable attributeOrders = new Hashtable ();
561                 private ArrayList attributes = new ArrayList ();
562
563                 public DTDAttributeDefinition this [int i] {
564                         get { return Get (i); }
565                 }
566
567                 public DTDAttributeDefinition this [string name] {
568                         get { return Get (name); }
569                 }
570
571                 public DTDAttributeDefinition Get (int i)
572                 {
573                         return attributes [i] as DTDAttributeDefinition;
574                 }
575
576                 public DTDAttributeDefinition Get (string name)
577                 {
578                         object o = attributeOrders [name];
579                         if (o != null)
580                                 return attributes [(int) o] as DTDAttributeDefinition;
581                         else
582                                 return null;
583                 }
584
585                 public ICollection Definitions {
586                         get { return attributes; }
587                 }
588
589                 public void Add (DTDAttributeDefinition def)
590                 {
591                         if (attributeOrders [def.Name] != null)
592                                 throw new InvalidOperationException (String.Format (
593                                         "Attribute definition for {0} was already added at element {1}.",
594                                         def.Name, this.Name));
595                         def.SetRoot (Root);
596                         attributeOrders.Add (def.Name, attributes.Count);
597                         attributes.Add (def);
598                 }
599
600                 public int Count {
601                         get { return attributeOrders.Count; }
602                 }
603
604 //              public object Clone ()
605 //              {
606 //                      return this.MemberwiseClone ();
607 //              }
608         }
609
610         public class DTDEntityDeclaration : DTDNode
611         {
612                 string entityValue;
613
614                 public string Name;
615                 public string PublicId;
616                 public string SystemId;
617                 public string NotationName;
618                 public string LiteralEntityValue;
619                 public bool IsInternalSubset;
620                 public StringCollection ReferencingEntities = new StringCollection ();
621                 bool scanned;
622                 bool recursed;
623
624                 public string EntityValue {
625                         get {
626                                 if (entityValue == null) {
627                                         if (NotationName != null)
628                                                 entityValue = "";
629                                         else if (SystemId == null)
630                                                 entityValue = LiteralEntityValue;
631                                         else {
632                                                 // FIXME: should use specified XmlUrlResolver.
633                                                 entityValue = ResolveExternalEntity (Root.Resolver);
634                                         }
635                                         // Check illegal recursion.
636                                         ScanEntityValue (new StringCollection ());
637                                 }
638                                 return entityValue;
639                         }
640                 }
641
642                 public void ScanEntityValue (StringCollection refs)
643                 {
644                         // To modify this code, beware nesting between this and EntityValue.
645                         string value = EntityValue;
646
647                         if (recursed)
648                                 throw new XmlException ("Entity recursion was found.");
649                         recursed = true;
650
651                         if (scanned) {
652                                 foreach (string referenced in refs)
653                                         if (this.ReferencingEntities.Contains (referenced))
654                                                 throw new XmlException (String.Format (
655                                                         "Nested entity was found between {0} and {1}",
656                                                         referenced, Name));
657                                 recursed = false;
658                                 return;
659                         }
660
661                         int len = value.Length;
662                         int start = 0;
663                         for (int i=0; i<len; i++) {
664                                 switch (value [i]) {
665                                 case '&':
666                                         start = i+1;
667                                         break;
668                                 case ';':
669                                         if (start == 0)
670                                                 break;
671                                         string name = value.Substring (start, i - start);
672                                         this.ReferencingEntities.Add (name);
673                                         DTDEntityDeclaration decl = Root.EntityDecls [name];
674                                         if (decl != null) {
675                                                 refs.Add (Name);
676                                                 decl.ScanEntityValue (refs);
677                                                 foreach (string str in decl.ReferencingEntities)
678                                                         ReferencingEntities.Add (str);
679                                                 refs.Remove (Name);
680                                         }
681                                         start = 0;
682                                         break;
683                                 }
684                         }
685                         scanned = true;
686                         recursed = false;
687                 }
688
689                 private string ResolveExternalEntity (XmlResolver resolver)
690                 {
691                         if (resolver == null)
692                                 return String.Empty;
693
694                         string baseUri = Root.BaseURI;
695                         if (baseUri == "")
696                                 baseUri = null;
697                         Uri uri = resolver.ResolveUri (
698                                 baseUri != null ? new Uri (baseUri) : null, SystemId);
699                         Stream stream = resolver.GetEntity (uri, null, typeof (Stream)) as Stream;
700                         XmlStreamReader reader = new XmlStreamReader (stream, false);
701
702                         StringBuilder sb = new StringBuilder ();
703
704                         bool checkTextDecl = true;
705                         while (reader.Peek () != -1) {
706                                 sb.Append ((char) reader.Read ());
707                                 if (checkTextDecl && sb.Length == 6) {
708                                         if (sb.ToString () == "<?xml ") {
709                                                 // Skip Text declaration.
710                                                 sb.Length = 0;
711                                                 StringBuilder textdecl = new StringBuilder ();
712                                                 while (reader.Peek () != '>' && reader.Peek () != -1)
713                                                         textdecl.Append ((char) reader.Read ());
714                                                 if (textdecl.ToString ().IndexOf ("encoding") < 0)
715                                                         throw new XmlException ("Text declaration must have encoding specification: " + BaseURI);
716                                                 if (textdecl.ToString ().IndexOf ("standalone") >= 0)
717                                                         throw new XmlException ("Text declaration cannot have standalone declaration: " + BaseURI);
718                                         }
719                                         checkTextDecl = false;
720                                 }
721                         }
722                         return sb.ToString ();
723                 }
724
725                 internal DTDEntityDeclaration (DTDObjectModel root)
726                 {
727                         this.SetRoot (root);
728                 }
729         }
730
731         public class DTDNotationDeclaration : DTDNode
732         {
733                 public string Name;
734                 public string LocalName;
735                 public string Prefix;
736                 public string PublicId;
737                 public string SystemId;
738
739                 internal DTDNotationDeclaration () {}
740         }
741
742         public class DTDParameterEntityDeclaration : DTDNode
743         {
744                 string resolvedValue;
745                 Exception loadException;
746
747                 public string Name;
748                 public string PublicId;
749                 public string SystemId;
750                 public string LiteralValue;
751                 public bool LoadFailed;
752
753                 public string Value {
754                         get {
755                                 if (LiteralValue != null)
756                                         return LiteralValue;
757                                 if (resolvedValue == null)
758                                         throw new InvalidOperationException ();
759                                 return resolvedValue;
760                         }
761                 }
762
763                 public void Resolve (XmlResolver resolver)
764                 {
765                         if (resolver == null) {
766                                 resolvedValue = String.Empty;
767                                 LoadFailed = true;
768                                 return;
769                         }
770
771                         Uri baseUri = null;
772                         try {
773                                 baseUri = new Uri (BaseURI);
774                         } catch (UriFormatException) {
775                         }
776
777                         Uri absUri = resolver.ResolveUri (baseUri, SystemId);
778                         string absPath = absUri.ToString ();
779
780                         try {
781                                 XmlStreamReader tw = new XmlStreamReader (absUri.ToString (), false, resolver, BaseURI);
782                                 string s = tw.ReadToEnd ();
783                                 if (s.StartsWith ("<?xml")) {
784                                         int end = s.IndexOf (">") + 1;
785                                         if (end < 0)
786                                                 throw new XmlException (this as IXmlLineInfo,
787                                                         "Inconsistent text declaration markup.");
788                                         if (s.IndexOf ("encoding", 0, end) < 0)
789                                                 throw new XmlException (this as IXmlLineInfo,
790                                                         "Text declaration must not omit encoding specification.");
791                                         if (s.IndexOf ("standalone", 0, end) >= 0)
792                                                 throw new XmlException (this as IXmlLineInfo,
793                                                         "Text declaration cannot have standalone declaration.");
794                                         resolvedValue = s.Substring (end);
795                                 }
796                                 else
797                                         resolvedValue = s;
798                         } catch (IOException ex) {
799                                 loadException = ex;
800                                 resolvedValue = String.Empty;
801                                 LoadFailed = true;
802                         }
803                 }
804         }
805
806         public enum DTDContentOrderType
807         {
808                 None,
809                 Seq,
810                 Or
811         }
812
813         public enum DTDAttributeOccurenceType
814         {
815                 None,
816                 Required,
817                 Optional,
818                 Fixed
819         }
820
821         public enum DTDOccurence
822         {
823                 One,
824                 Optional,
825                 ZeroOrMore,
826                 OneOrMore
827         }
828 }