2005-12-27 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / Commons.Xml.Relaxng / Commons.Xml.Relaxng / RelaxngReader.cs
1 //
2 // Commons.Xml.Relaxng.RelaxngReader.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
6 //
7 // 2003 Atsushi Enomoto "No rights reserved."
8 //
9 // Copyright (c) 2004 Novell Inc.
10 // All rights reserved
11 //
12
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 // 
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 // 
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33
34 using System;
35 using System.Collections;
36 using System.Xml;
37
38 namespace Commons.Xml.Relaxng
39 {
40         public class RelaxngReader : XmlDefaultReader
41         {
42                 // static members.
43                 static RelaxngPattern grammarForRelaxng;
44                 static XmlReader relaxngXmlReader;
45                 static RelaxngReader ()
46                 {
47                         relaxngXmlReader = new XmlTextReader (typeof (RelaxngReader).Assembly.GetManifestResourceStream ("relaxng.rng"));
48                         grammarForRelaxng =
49                                 RelaxngPattern.Read (relaxngXmlReader);
50                 }
51
52                 [Obsolete] // incorrectly introduced
53                 public static string RelaxngNS = "http://relaxng.org/ns/structure/1.0";
54                 public static RelaxngPattern GrammarForRelaxng {
55                         get { return grammarForRelaxng; }
56                 }
57
58
59                 // fields
60                 Stack nsStack = new Stack ();
61                 Stack datatypeLibraryStack = new Stack ();
62                 XmlResolver resolver = new XmlUrlResolver ();
63 //              ArrayList annotationNamespaces = new ArrayList ();
64
65                 // ctor
66                 public RelaxngReader (XmlReader reader)
67                         : this (reader, null)
68                 {
69                 }
70
71                 public RelaxngReader (XmlReader reader, string ns)
72 //                      : base (grammarForRelaxng == null ? reader : new RelaxngValidatingReader (reader, grammarForRelaxng))
73                         : base (reader)
74                 {
75                         if (Reader.ReadState == ReadState.Initial)
76                                 Read ();
77                         MoveToContent ();
78                         string nsval = GetSpaceStrippedAttribute ("ns", String.Empty);
79                         if (nsval == null)
80                                 nsval = ns;
81                         nsStack.Push (nsval == null ? String.Empty : nsval);
82                         string dtlib = GetSpaceStrippedAttribute ("datatypeLibrary", String.Empty);
83                         datatypeLibraryStack.Push (dtlib != null ?
84                                 dtlib : String.Empty);
85                 }
86
87                 public XmlResolver XmlResolver {
88                         set { resolver = value; }
89                 }
90
91                 internal XmlResolver Resolver {
92                         get { return resolver; }
93                 }
94
95                 private void FillLocation (RelaxngElementBase el)
96                 {
97                         el.BaseUri = BaseURI;
98                         IXmlLineInfo li = this as IXmlLineInfo;
99                         el.LineNumber = li != null ? li.LineNumber : 0;
100                         el.LinePosition = li != null ? li.LinePosition : 0;
101                 }
102
103 /*
104                 public void AddAnnotationNamespace (string ns)
105                 {
106                         if (!annotationNamespaces.Contains (ns))
107                                 annotationNamespaces.Add (ns);
108                 }
109 */
110
111                 // public
112                 public override bool Read ()
113                 {
114                         bool skipRead = false;
115                         bool b = false;
116                         bool loop = true;
117                         if (IsEmptyElement) { // this should be done here
118                                 nsStack.Pop ();
119                                 datatypeLibraryStack.Pop ();
120                         }
121                         do {
122                                 if (!skipRead)
123                                         Reader.Read ();
124                                 else
125                                         skipRead = false;
126                                 switch (NodeType) {
127                                 case XmlNodeType.ProcessingInstruction:
128                                 case XmlNodeType.Comment:
129                                 case XmlNodeType.EntityReference:
130                                         continue;
131                                 case XmlNodeType.Whitespace:
132                                 // Skip whitespaces except for data and param.
133                                 case XmlNodeType.SignificantWhitespace:
134                                         if (LocalName != "value" && LocalName != "param") {
135                                                 continue;
136                                         }
137                                         else
138                                                 loop = false;
139                                         break;
140                                 default:
141                                         if (NamespaceURI != RelaxngGrammar.NamespaceURI) {
142                                                 Reader.Skip ();
143                                                 skipRead = true;
144                                         }
145                                         else
146                                                 loop = false;
147                                         break;
148                                 }
149                         } while (!Reader.EOF && loop);
150
151                         switch (NodeType) {
152                         case XmlNodeType.Element:
153                                 if (MoveToAttribute ("ns")) {
154                                         nsStack.Push (Value.Trim ());
155                                         MoveToElement ();
156                                 }
157                                 else
158                                         nsStack.Push (ContextNamespace);
159
160                                 if (MoveToAttribute ("datatypeLibrary")) {
161                                         string uriString = Value.Trim ();
162                                         if (uriString.Length == 0)
163                                                 datatypeLibraryStack.Push (String.Empty);
164                                         else {
165                                                 try {
166                                                         Uri uri = new Uri (uriString);
167                                                         // MS.NET Uri is too lamespec
168                                                         datatypeLibraryStack.Push (uri.ToString ());
169                                                 } catch (UriFormatException ex) {
170                                                         throw new RelaxngException (ex.Message, ex);
171                                                 }
172                                         }
173                                         MoveToElement ();
174                                 }
175                                 else
176                                         datatypeLibraryStack.Push (DatatypeLibrary);
177                                 break;
178
179                         case XmlNodeType.EndElement:
180                                 nsStack.Pop ();
181                                 datatypeLibraryStack.Pop ();
182                                 break;
183                         }
184
185                         return b;
186                 }
187
188                 // Properties
189
190                 public string ContextNamespace {
191                         get {
192                                 if (nsStack.Count == 0)
193                                         // It happens only on initialization.
194                                         return String.Empty;
195                                 return nsStack.Peek () as string;
196                         }
197                 }
198
199                 public string DatatypeLibrary {
200                         get {
201                                 if (datatypeLibraryStack.Count == 0)
202                                         // It happens only on initialization.
203                                         return String.Empty;
204                                 return datatypeLibraryStack.Peek () as string;
205                         }
206                 }
207
208                 // Utility methods.
209                 private void expect (string name)
210                 {
211                         if (NamespaceURI != RelaxngGrammar.NamespaceURI)
212                                 throw new RelaxngException (String.Format ("Invalid document: expected namespace {0} but found {1}", RelaxngGrammar.NamespaceURI, NamespaceURI));
213                         else if (LocalName != name)
214                                 throw new RelaxngException (String.Format ("Invalid document: expected local name {0} but found {1}", name, LocalName));
215                 }
216
217                 private void expectEnd (string name)
218                 {
219                         if (NodeType != XmlNodeType.EndElement)
220                                 throw new RelaxngException (String.Format ("Expected EndElement but found {0}.", NodeType));
221                         expect (name);
222
223                         Read ();
224                 }
225
226                 // Other than name class and pattern.
227                 private RelaxngStart ReadStart ()
228                 {
229                         RelaxngStart s = new RelaxngStart ();
230                         FillLocation (s);
231                         expect ("start");
232
233                         if (MoveToFirstAttribute ()) {
234                                 do {
235                                         if (NamespaceURI != String.Empty)
236                                                 continue;
237                                         switch (LocalName) {
238                                         case "datatypeLibrary":
239                                         case  "combine":
240                                                 break;
241                                         default:
242                                                 throw new RelaxngException ("Invalid attribute.");
243                                         }
244                                 } while (MoveToNextAttribute ());
245                                 MoveToElement ();
246                         }
247
248                         if (MoveToAttribute ("combine")) {
249                                 s.Combine = Value.Trim ();
250                                 if (s.Combine != "choice" && s.Combine != "interleave")
251                                         throw new RelaxngException ("Invalid combine attribute: " + s.Combine);
252                         }
253
254                         MoveToElement ();
255                         Read ();
256                         s.Pattern = ReadPattern ();
257                         expectEnd ("start");
258                         return s;
259                 }
260
261                 private string GetNameAttribute ()
262                 {
263                         string name = GetSpaceStrippedAttribute ("name", String.Empty);
264                         if (name == null)
265                                 throw new RelaxngException ("Required attribute name is not found.");
266                         return XmlConvert.VerifyNCName (name);
267                 }
268
269                 private string GetSpaceStrippedAttribute (string name, string ns)
270                 {
271                         string v = GetAttribute (name, ns);
272                         return v != null ? v.Trim () : null;
273                 }
274
275                 private RelaxngDefine ReadDefine ()
276                 {
277                         RelaxngDefine def = new RelaxngDefine ();
278                         FillLocation (def);
279                         expect ("define");
280                         def.Name = GetNameAttribute ();
281                         def.Combine = GetSpaceStrippedAttribute ("combine", String.Empty);
282
283                         Read ();
284                         while (NodeType == XmlNodeType.Element)
285                                 def.Patterns.Add (ReadPattern ());
286                         expectEnd ("define");
287                         return def;
288                 }
289
290                 private RelaxngParam ReadParam ()
291                 {
292                         RelaxngParam p = new RelaxngParam ();
293                         FillLocation (p);
294                         expect ("param");
295                         p.Name = GetNameAttribute ();
296                         p.Value = ReadString ().Trim ();
297                         expectEnd ("param");
298                         return p;
299                 }
300
301                 // NameClass reader (only if it is element-style.)
302                 private RelaxngNameClass ReadNameClass ()
303                 {
304                         switch (LocalName) {
305                         case "name":
306                                 return ReadNameClassName ();
307                         case "anyName":
308                                 return ReadNameClassAnyName ();
309                         case "nsName":
310                                 return ReadNameClassNsName ();
311                         case "choice":
312                                 return ReadNameClassChoice ();
313                         }
314                         throw new RelaxngException ("Invalid name class: " + LocalName);
315                 }
316
317                 private RelaxngName ReadNameClassName ()
318                 {
319                         string name = ReadString ().Trim ();
320                         RelaxngName rName = resolvedName (name);
321                         expectEnd ("name");
322                         return rName;
323                 }
324
325                 private RelaxngAnyName ReadNameClassAnyName ()
326                 {
327                         RelaxngAnyName an = new RelaxngAnyName ();
328                         FillLocation (an);
329                         if (!IsEmptyElement) {
330                                 Read ();
331                                 if (NodeType == XmlNodeType.EndElement) {
332                                 } else {
333                                         // expect except
334                                         expect ("except");
335                                         Read ();
336                                         an.Except = new RelaxngExceptNameClass ();
337                                         FillLocation (an.Except);
338                                         while (NodeType == XmlNodeType.Element)
339                                                 an.Except.Names.Add (
340                                                         ReadNameClass ());
341                                         expectEnd ("except");
342                                 }
343                                 expectEnd ("anyName");
344                         } else
345                                 Read ();
346                         return an;
347                 }
348
349                 private RelaxngNsName ReadNameClassNsName ()
350                 {
351                         RelaxngNsName nn = new RelaxngNsName ();
352                         FillLocation (nn);
353                         nn.Namespace = this.ContextNamespace;
354                         if (!IsEmptyElement) {
355                                 Read ();
356                                 if (NodeType == XmlNodeType.EndElement) {
357                                 } else {
358                                         // expect except
359                                         expect ("except");
360 //                                      Read ();
361                                         nn.Except = ReadNameClassExcept ();//new RelaxngExceptNameClass ();
362                                         FillLocation (nn.Except);
363                                 }
364                                 expectEnd ("nsName");
365                         } else
366                                 Read ();
367                         return nn;
368                 }
369
370                 private RelaxngNameChoice ReadNameClassChoice ()
371                 {
372                         RelaxngNameChoice nc = new RelaxngNameChoice ();
373                         FillLocation (nc);
374                         if (IsEmptyElement)
375                                 throw new RelaxngException ("Name choice must have at least one name class.");
376
377                         Read ();
378                         while (NodeType != XmlNodeType.EndElement) {
379                                 nc.Children.Add (ReadNameClass ());
380                         }
381                         if (nc.Children.Count == 0)
382                                 throw new RelaxngException ("Name choice must have at least one name class.");
383
384                         expectEnd ("choice");
385                         return nc;
386                 }
387
388                 private RelaxngExceptNameClass ReadNameClassExcept ()
389                 {
390                         RelaxngExceptNameClass x = new RelaxngExceptNameClass ();
391                         FillLocation (x);
392                         if (IsEmptyElement)
393                                 throw new RelaxngException ("Name choice must have at least one name class.");
394
395                         Read ();
396                         while (NodeType != XmlNodeType.EndElement)
397                                 x.Names.Add (ReadNameClass ());
398                         if (x.Names.Count == 0)
399                                 throw new RelaxngException ("Name choice must have at least one name class.");
400
401                         expectEnd ("except");
402                         return x;
403                 }
404
405                 // Pattern reader
406
407                 public RelaxngPattern ReadPattern ()
408                 {
409                         while (NodeType != XmlNodeType.Element)
410                                 if (!Read ())
411                                         throw new RelaxngException ("RELAX NG pattern did not appear.");
412
413                         switch (LocalName) {
414                         case "element":
415                                 return ReadElementPattern ();
416                         case "attribute":
417                                 return ReadAttributePattern ();
418                         case "group":
419                                 return ReadGroupPattern ();
420                         case "interleave":
421                                 return ReadInterleavePattern ();
422                         case "choice":
423                                 return ReadChoicePattern ();
424                         case "optional":
425                                 return ReadOptionalPattern ();
426                         case "zeroOrMore":
427                                 return ReadZeroOrMorePattern ();
428                         case "oneOrMore":
429                                 return ReadOneOrMorePattern ();
430                         case "list":
431                                 return ReadListPattern ();
432                         case "mixed":
433                                 return ReadMixedPattern ();
434                         case "ref":
435                                 return ReadRefPattern ();
436                         case "parentRef":
437                                 return ReadParentRefPattern ();
438                         case "empty":
439                                 return ReadEmptyPattern ();
440                         case "text":
441                                 return ReadTextPattern ();
442                         case "data":
443                                 return ReadDataPattern ();
444                         case "value":
445                                 return ReadValuePattern ();
446                         case "notAllowed":
447                                 return ReadNotAllowedPattern ();
448                         case "externalRef":
449                                 return ReadExternalRefPattern ();
450                         case "grammar":
451                                 return ReadGrammarPattern ();
452                         }
453                         throw new RelaxngException ("Non-supported pattern specification: " + LocalName);
454                 }
455
456                 private void ReadPatterns (RelaxngSingleContentPattern el)
457                 {
458                         do {
459                                 el.Patterns.Add (ReadPattern ());
460                         } while (NodeType == XmlNodeType.Element);
461                 }
462
463                 private void ReadPatterns (RelaxngBinaryContentPattern el)
464                 {
465                         do {
466                                 el.Patterns.Add (ReadPattern ());
467                         } while (NodeType == XmlNodeType.Element);
468                 }
469
470                 private RelaxngExcept ReadPatternExcept ()
471                 {
472                         RelaxngExcept x = new RelaxngExcept ();
473                         FillLocation (x);
474                         if (IsEmptyElement)
475                                 throw new RelaxngException ("'except' must have at least one pattern.");
476                         Read ();
477                         while (NodeType != XmlNodeType.EndElement)
478                                 x.Patterns.Add (ReadPattern ());
479                         if (x.Patterns.Count == 0)
480                                 throw new RelaxngException ("'except' must have at least one pattern.");
481
482                         expectEnd ("except");
483                         return x;
484                 }
485
486                 private RelaxngInclude ReadInclude ()
487                 {
488                         RelaxngInclude i = new RelaxngInclude ();
489                         FillLocation (i);
490                         expect ("include");
491                         i.NSContext = ContextNamespace;
492                         string href = GetSpaceStrippedAttribute ("href", String.Empty);
493                         if (href == null)
494                                 throw new RelaxngException ("Required attribute href was not found.");
495                         XmlResolver res = resolver != null ? resolver : new XmlUrlResolver ();
496                         i.Href = res.ResolveUri (BaseURI != null ? new Uri (BaseURI) : null, href).AbsoluteUri;
497                         if (!IsEmptyElement) {
498                                 Read ();
499                                 this.readGrammarIncludeContent (i.Starts, i.Defines, i.Divs, null);
500                                 expectEnd ("include");
501                         }
502                         else
503                                 Read ();
504                         return i;
505                 }
506
507                 private void readGrammarIncludeContent (IList starts, IList defines, IList divs, IList includes)
508                 {
509                         while (NodeType == XmlNodeType.Element) {
510                                 switch (LocalName) {
511                                 case "start":
512                                         starts.Add (ReadStart ());
513                                         break;
514                                 case "define":
515                                         defines.Add (ReadDefine ());
516                                         break;
517                                 case "div":
518                                         divs.Add (ReadDiv (includes != null));
519                                         break;
520                                 case "include":
521                                         if (includes != null)
522                                                 includes.Add (ReadInclude ());
523                                         else
524                                                 throw new RelaxngException ("Unexpected content: " + Name);
525                                         break;
526                                 default:
527                                         throw new RelaxngException ("Unexpected content: " + Name);
528                                 }
529                         }
530                 }
531
532                 private RelaxngDiv ReadDiv (bool allowIncludes)
533                 {
534                         expect ("div");
535                         RelaxngDiv div = new RelaxngDiv ();
536                         FillLocation (div);
537                         if (!IsEmptyElement) {
538                                 Read ();
539                                 readGrammarIncludeContent (div.Starts, div.Defines, div.Divs, div.Includes);
540                                 expectEnd ("div");
541                         }
542                         else
543                                 Read ();
544                         return div;
545                 }
546
547                 private RelaxngName resolvedName (string nameSpec)
548                 {
549                         int colonAt = nameSpec.IndexOf (':');
550                         string prefix = (colonAt < 0) ? "" : nameSpec.Substring (0, colonAt);
551                         string local = (colonAt < 0) ? nameSpec : nameSpec.Substring (colonAt + 1, nameSpec.Length - colonAt - 1);
552                         string uri = ContextNamespace;
553
554                         if (prefix != "") {
555                                 uri = LookupNamespace (prefix);
556                                 if (uri == null)
557                                         throw new RelaxngException ("Undeclared prefix in name component: " + nameSpec);
558                         }
559                         RelaxngName n = new RelaxngName (local, uri);
560                         FillLocation (n);
561                         return n;
562                 }
563
564                 private RelaxngElement ReadElementPattern ()
565                 {
566                         RelaxngElement el = new RelaxngElement ();
567                         FillLocation (el);
568
569                         if (MoveToFirstAttribute ()) {
570                                 do {
571                                         if (NamespaceURI != String.Empty)
572                                                 continue;
573                                         switch (LocalName) {
574                                         case "datatypeLibrary":
575                                         case  "name":
576                                         case "ns":
577                                                 break;
578                                         default:
579                                                 throw new RelaxngException ("Invalid attribute.");
580                                         }
581                                 } while (MoveToNextAttribute ());
582                                 MoveToElement ();
583                         }
584
585                         // try to get name from attribute.
586                         if (MoveToAttribute ("name"))
587                                 el.NameClass = resolvedName (XmlConvert.VerifyName (Value.Trim ()));
588                         MoveToElement ();
589                         Read ();
590
591                         // read nameClass from content.
592                         if (el.NameClass == null)
593                                 el.NameClass = ReadNameClass ();
594
595                         // read patterns.
596                         this.ReadPatterns (el);
597
598                         expectEnd ("element");
599
600                         if (el.NameClass == null)
601                                 throw new RelaxngException ("Name class was not specified.");
602                         return el;
603                 }
604
605                 private RelaxngAttribute ReadAttributePattern ()
606                 {
607                         RelaxngAttribute attr = new RelaxngAttribute ();
608                         FillLocation (attr);
609
610                         if (MoveToFirstAttribute ()) {
611                                 do {
612                                         if (NamespaceURI != String.Empty)
613                                                 continue;
614                                         switch (LocalName) {
615                                         case "datatypeLibrary":
616                                         case "name":
617                                         case "ns":
618                                                 break;
619                                         default:
620                                                 throw new RelaxngException ("Invalid attribute.");
621                                         }
622                                 } while (MoveToNextAttribute ());
623                                 MoveToElement ();
624                         }
625
626                         string ns = GetSpaceStrippedAttribute ("ns", String.Empty);
627
628                         // try to get name from attribute.
629                         if (MoveToAttribute ("name", String.Empty)) {
630 //                              attr.NameClass = resolvedName (XmlConvert.VerifyName (Value.Trim ()), false);
631                                 RelaxngName nc = new RelaxngName ();
632                                 string name = XmlConvert.VerifyName (Value.Trim ());
633                                 if (name.IndexOf (':') > 0)
634                                         nc = resolvedName (name);
635                                 else {
636                                         nc.LocalName = name;
637                                         nc.Namespace = ns == null ? String.Empty : ns;
638                                 }
639                                 attr.NameClass = nc;
640                         }
641
642                         MoveToElement ();
643                         if (!IsEmptyElement) {
644                                 Read ();
645                                 // read nameClass from content.
646                                 if (attr.NameClass == null)
647                                         attr.NameClass = ReadNameClass ();
648
649                                 if (NodeType == XmlNodeType.Element)
650                                         attr.Pattern = ReadPattern ();
651
652                                 expectEnd ("attribute");
653                         } else
654                                 Read ();
655
656                         if (attr.NameClass == null)
657                                 throw new RelaxngException ("Name class was not specified.");
658                         return attr;
659                 }
660
661                 private RelaxngGrammar ReadGrammarPattern ()
662                 {
663                         RelaxngGrammar grammar = new RelaxngGrammar ();
664                         FillLocation (grammar);
665                         grammar.DefaultNamespace = Reader.GetAttribute ("ns");
666                         Read ();
667                         this.readGrammarIncludeContent (grammar.Starts, grammar.Defines, grammar.Divs, grammar.Includes);
668                         expectEnd ("grammar");
669
670                         return grammar;
671                 }
672
673                 private RelaxngRef ReadRefPattern ()
674                 {
675                         RelaxngRef r = new RelaxngRef ();
676                         FillLocation (r);
677                         expect ("ref");
678                         r.Name = GetNameAttribute ();
679                         if (!IsEmptyElement) {
680                                 Read ();
681                                 expectEnd ("ref");
682                         }
683                         else
684                                 Read ();
685                         return r;
686                 }
687
688                 private RelaxngExternalRef ReadExternalRefPattern ()
689                 {
690                         RelaxngExternalRef r = new RelaxngExternalRef ();
691                         FillLocation (r);
692                         expect ("externalRef");
693                         string href = GetSpaceStrippedAttribute ("href", String.Empty);
694                         if (href == null)
695                                 throw new RelaxngException ("Required attribute href was not found.");
696                         XmlResolver res = resolver != null ? resolver : new XmlUrlResolver ();
697                         r.Href = res.ResolveUri (BaseURI != null ? new Uri (BaseURI) : null, href).AbsoluteUri;
698                         r.NSContext = ContextNamespace;
699                         if (!IsEmptyElement) {
700                                 Read ();
701                                 expectEnd ("externalRef");
702                         }
703                         else
704                                 Read ();
705                         return r;
706                 }
707
708                 private RelaxngParentRef ReadParentRefPattern ()
709                 {
710                         RelaxngParentRef r = new RelaxngParentRef ();
711                         FillLocation (r);
712                         expect ("parentRef");
713                         r.Name = GetNameAttribute ();
714                         if (!IsEmptyElement) {
715                                 Read ();
716                                 expectEnd ("parentRef");
717                         }
718                         else
719                                 Read ();
720                         return r;
721                 }
722
723                 private RelaxngEmpty ReadEmptyPattern ()
724                 {
725                         expect ("empty");
726
727                         if (MoveToFirstAttribute ()) {
728                                 do {
729                                         if (NamespaceURI == String.Empty && LocalName != "datatypeLibrary")
730                                                 throw new RelaxngException ("Invalid attribute.");
731                                 } while (MoveToNextAttribute ());
732                                 MoveToElement ();
733                         }
734
735                         if (!IsEmptyElement) {
736                                 Read ();
737                                 expectEnd ("empty");
738                         }
739                         else
740                                 Read ();
741
742                         RelaxngEmpty empty = new RelaxngEmpty ();
743                         FillLocation (empty);
744                         return empty;
745                 }
746
747                 private RelaxngText ReadTextPattern ()
748                 {
749                         expect ("text");
750
751                         if (MoveToFirstAttribute ()) {
752                                 do {
753                                         if (NamespaceURI == String.Empty && LocalName != "datatypeLibrary")
754                                                 throw new RelaxngException ("Invalid attribute.");
755                                 } while (MoveToNextAttribute ());
756                                 MoveToElement ();
757                         }
758
759                         if (!IsEmptyElement) {
760                                 Read ();
761                                 expectEnd ("text");
762                         }
763                         else
764                                 Read ();
765
766                         RelaxngText t = new RelaxngText ();
767                         FillLocation (t);
768                         return t;
769                 }
770
771                 private RelaxngData ReadDataPattern ()
772                 {
773                         RelaxngData data = new RelaxngData ();
774                         FillLocation (data);
775
776                         expect ("data");
777                         data.Type = GetSpaceStrippedAttribute ("type", String.Empty);
778                         if (data.Type == null)
779                                 throw new RelaxngException ("Attribute type is required.");
780                         data.DatatypeLibrary = DatatypeLibrary;
781
782                         if (MoveToFirstAttribute ()) {
783                                 do {
784                                         if (NamespaceURI != String.Empty)
785                                                 continue;
786                                         switch (LocalName) {
787                                         case "datatypeLibrary":
788                                         case "type":
789                                                 break;
790                                         default:
791                                                 throw new RelaxngException ("Invalid attribute.");
792                                         }
793                                 } while (MoveToNextAttribute ());
794                                 MoveToElement ();
795                         }
796
797                         if (!IsEmptyElement) {
798                                 Read ();
799                                 while (Name == "param") {
800                                         data.ParamList.Add (ReadParam ());
801                                 }
802                                 if (LocalName == "except")
803                                         data.Except = ReadPatternExcept ();
804                                 expectEnd ("data");
805                         } else
806                                 Read ();
807
808                         return data;
809                 }
810
811                 private RelaxngValue ReadValuePattern ()
812                 {
813                         RelaxngValue v = new RelaxngValue ();
814                         FillLocation (v);
815                         expect ("value");
816
817                         if (MoveToFirstAttribute ()) {
818                                 do {
819                                         if (NamespaceURI != String.Empty)
820                                                 continue;
821                                         switch (LocalName) {
822                                         case "datatypeLibrary":
823                                         case "type":
824                                         case "ns":
825                                                 break;
826                                         default:
827                                                 throw new RelaxngException ("Invalid attribute.");
828                                         }
829                                 } while (MoveToNextAttribute ());
830                                 MoveToElement ();
831                         }
832
833                         if (MoveToAttribute ("type")) {
834                                 v.Type = Value.Trim ();
835                                 v.DatatypeLibrary = DatatypeLibrary;
836                         } else {
837                                 v.Type = "token";
838                                 v.DatatypeLibrary = "";
839                         }
840 //                      v.Namespace = GetSpaceStrippedAttribute ("ns", String.Empty);
841                         MoveToElement ();
842                         if (IsEmptyElement) {
843                                 v.Value = String.Empty;
844                                 Read ();
845                         } else {
846                                 v.Value = ReadString ();
847                                 expectEnd ("value");
848                         }
849
850                         return v;
851                 }
852
853                 private RelaxngList ReadListPattern ()
854                 {
855                         RelaxngList list = new RelaxngList ();
856                         FillLocation (list);
857                         expect ("list");
858                         Read ();
859                         ReadPatterns (list);
860                         expectEnd ("list");
861                         return list;
862                 }
863
864                 private RelaxngOneOrMore ReadOneOrMorePattern ()
865                 {
866                         RelaxngOneOrMore o = new RelaxngOneOrMore ();
867                         FillLocation (o);
868                         expect ("oneOrMore");
869                         Read ();
870                         ReadPatterns (o);
871                         expectEnd ("oneOrMore");
872                         return o;
873                 }
874
875                 private RelaxngZeroOrMore ReadZeroOrMorePattern ()
876                 {
877                         RelaxngZeroOrMore o = new RelaxngZeroOrMore ();
878                         FillLocation (o);
879                         expect ("zeroOrMore");
880                         Read ();
881                         ReadPatterns (o);
882                         expectEnd ("zeroOrMore");
883                         return o;
884                 }
885
886                 private RelaxngOptional ReadOptionalPattern ()
887                 {
888                         RelaxngOptional o = new RelaxngOptional ();
889                         FillLocation (o);
890                         expect ("optional");
891                         Read ();
892                         ReadPatterns (o);
893                         expectEnd ("optional");
894                         return o;
895                 }
896
897                 private RelaxngMixed ReadMixedPattern ()
898                 {
899                         RelaxngMixed o = new RelaxngMixed ();
900                         FillLocation (o);
901                         expect ("mixed");
902                         Read ();
903                         ReadPatterns (o);
904                         expectEnd ("mixed");
905                         return o;
906                 }
907
908                 private RelaxngGroup ReadGroupPattern ()
909                 {
910                         RelaxngGroup g = new RelaxngGroup ();
911                         FillLocation (g);
912                         expect ("group");
913                         Read ();
914                         ReadPatterns (g);
915                         expectEnd ("group");
916                         return g;
917                 }
918
919                 private RelaxngInterleave ReadInterleavePattern ()
920                 {
921                         RelaxngInterleave i = new RelaxngInterleave ();
922                         FillLocation (i);
923                         expect ("interleave");
924                         Read ();
925                         ReadPatterns (i);
926                         expectEnd ("interleave");
927                         return i;
928                 }
929
930                 private RelaxngChoice ReadChoicePattern ()
931                 {
932                         RelaxngChoice c = new RelaxngChoice ();
933                         FillLocation (c);
934                         expect ("choice");
935                         Read ();
936                         ReadPatterns (c);
937                         expectEnd ("choice");
938                         return c;
939                 }
940
941                 private RelaxngNotAllowed ReadNotAllowedPattern ()
942                 {
943                         expect ("notAllowed");
944                         if (!IsEmptyElement) {
945                                 Read ();
946                                 expectEnd ("notAllowed");
947                         }
948                         else
949                                 Read ();
950                         RelaxngNotAllowed na = new RelaxngNotAllowed ();
951                         FillLocation (na);
952                         return na;
953                 }
954         }
955 }