2009-01-20 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / Commons.Xml.Relaxng / Commons.Xml.Relaxng / RelaxngPattern.cs
1 //
2 // Commons.Xml.Relaxng.RelaxngPattern.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.IO;
37 using System.Xml;
38 using Commons.Xml.Relaxng.Derivative;
39 using Commons.Xml.Relaxng.Rnc;
40
41 #if NET_2_0
42 using NSResolver = System.Xml.IXmlNamespaceResolver;
43 #else
44 using NSResolver = System.Xml.XmlNamespaceManager;
45 #endif
46
47 namespace Commons.Xml.Relaxng
48 {
49         #region Common abstract
50         public abstract class RelaxngElementBase
51         {
52                 bool isCompiled;
53                 int lineNumber, linePosition;
54                 string baseUri;
55
56                 internal bool IsCompiled {
57                         get { return isCompiled; }
58                         set { isCompiled = value; }
59                 }
60
61                 public int LineNumber {
62                         get { return lineNumber; }
63                         set { lineNumber = value; }
64                 }
65
66                 public int LinePosition {
67                         get { return linePosition; }
68                         set { linePosition = value; }
69                 }
70
71                 public string BaseUri {
72                         get { return baseUri; }
73                         set { baseUri = value; }
74                 }
75
76                 public abstract void Write (XmlWriter writer);
77
78                 internal abstract void WriteRnc (RncWriter writer);
79
80                 public RelaxngPattern ReadExternalResource (RelaxngGrammar grammar, Uri uri, string nsContext)
81                 {
82                         XmlTextReader xtr = null;
83                         RelaxngGrammar g = null;
84                         try {
85                                 if (grammar.IsSourceCompactSyntax) {
86                                         return RncParser.ParseRnc (new StreamReader ((Stream) grammar.Resolver.GetEntity (uri, null, typeof (Stream))), null, BaseUri, nsContext);
87                                 } else {
88                                         xtr = new XmlTextReader (uri.AbsoluteUri, (Stream) grammar.Resolver.GetEntity (uri, null, typeof (Stream)));
89                                         RelaxngReader r = new RelaxngReader (xtr, nsContext, grammar.Resolver);
90                                         r.MoveToContent ();
91                                         return r.ReadPattern ();
92                                 }
93                         } catch (Exception ex) { // umm, bad catch though :-(
94                                 throw new RelaxngException (this, String.Format("Could not include grammar {0}: {1}", uri.AbsoluteUri, ex.Message), ex);
95                         } finally {
96                                 if (xtr != null)
97                                         xtr.Close ();
98                         }
99                 }
100         }
101
102         public abstract class RelaxngSingleContentPattern : RelaxngPattern
103         {
104                 private RelaxngPatternList patterns = new RelaxngPatternList ();
105
106                 public RelaxngPatternList Patterns {
107                         get { return patterns; }
108                 }
109
110                 internal RdpPattern makeSingle (RelaxngGrammar g)
111                 {
112                         // Flatten patterns into RdpGroup. See 4.12.
113                         if (patterns.Count == 0)
114                                 throw new RelaxngException (this, "No pattern contents.");
115                         RdpPattern p = ((RelaxngPattern) patterns [0]).Compile (g);
116                         if (patterns.Count == 1)
117                                 return p;
118                         for (int i=1; i<patterns.Count; i++) {
119                                 p = new RdpGroup (p,
120                                         ((RelaxngPattern) patterns [i]).Compile (g));
121                         }
122                         return p;
123                 }
124
125                 internal override void CheckConstraints () 
126                 {
127                         foreach (RelaxngPattern p in Patterns)
128                                 p.CheckConstraints ();
129                 }
130         }
131
132         public abstract class RelaxngBinaryContentPattern : RelaxngPattern
133         {
134                 private RelaxngPatternList patterns = new RelaxngPatternList ();
135
136                 public RelaxngPatternList Patterns {
137                         get { return patterns; }
138                 }
139
140                 internal RdpPattern makeBinary (RelaxngGrammar g)
141                 {
142                         // Flatten patterns. See 4.12.
143                         if (patterns.Count == 0)
144                                 throw new RelaxngException (this, "No pattern contents.");
145
146                         RdpPattern p = ((RelaxngPattern) patterns [0]).Compile (g);
147                         if (patterns.Count == 1)
148                                 return p;
149
150                         for (int i=1; i<patterns.Count; i++) {
151                                 RdpPattern cp =
152                                         ((RelaxngPattern) patterns [i]).Compile (g);
153                                 switch (this.PatternType) {
154                                 case RelaxngPatternType.Choice:
155                                         p = new RdpChoice (p, cp);
156                                         break;
157                                 case RelaxngPatternType.Group:
158                                         p = new RdpGroup (p, cp);
159                                         break;
160                                 case RelaxngPatternType.Interleave:
161                                         p = new RdpInterleave (p, cp);
162                                         break;
163                                 }
164                         }
165
166                         return p;
167                 }
168
169                 internal override void CheckConstraints () 
170                 {
171                         foreach (RelaxngPattern p in Patterns)
172                                 p.CheckConstraints ();
173                 }
174         }
175         #endregion
176
177         #region Grammatical elements
178         public interface IGrammarContent
179         {
180         }
181
182         public class RelaxngStart : RelaxngElementBase, IGrammarContent
183         {
184                 RelaxngPattern p;
185                 string combine;
186
187                 public RelaxngStart ()
188                 {
189                 }
190
191                 public string Combine {
192                         get { return combine; }
193                         set { combine = value; }
194                 }
195
196                 public RelaxngPattern Pattern {
197                         get { return p; }
198                         set { p = value; }
199                 }
200
201                 public override void Write (XmlWriter writer)
202                 {
203                         writer.WriteStartElement ("", "start", RelaxngGrammar.NamespaceURI);
204                         if (combine != null)
205                                 writer.WriteAttributeString ("combine", combine);
206                         p.Write (writer);
207                         writer.WriteEndElement ();
208                 }
209
210                 internal override void WriteRnc (RncWriter writer)
211                 {
212                         writer.WriteStart (this);
213                 }
214
215                 internal RdpPattern Compile (RelaxngGrammar grammar)
216                 {
217                         return p.Compile (grammar);
218                 }
219         }
220
221         public class RelaxngDefine : RelaxngElementBase, IGrammarContent
222         {
223                 string name;
224                 private RelaxngPatternList patterns = new RelaxngPatternList ();
225                 string combine;
226
227                 public RelaxngDefine ()
228                 {
229                 }
230
231                 public RelaxngPatternList Patterns {
232                         get { return patterns; }
233                 }
234
235                 public string Combine {
236                         get { return combine; }
237                         set { combine = value; }
238                 }
239
240                 public string Name {
241                         get { return name; }
242                         set { name = value; }
243                 }
244
245                 public override void Write (XmlWriter writer)
246                 {
247                         writer.WriteStartElement ("", "define", RelaxngGrammar.NamespaceURI);
248                         writer.WriteAttributeString ("name", name);
249                         if (combine != null)
250                                 writer.WriteAttributeString ("combine", combine);
251                         foreach (RelaxngPattern p in Patterns)
252                                 p.Write (writer);
253                         writer.WriteEndElement ();
254                 }
255
256                 internal override void WriteRnc (RncWriter writer)
257                 {
258                         writer.WriteDefine (this);
259                 }
260
261                 internal RdpPattern Compile (RelaxngGrammar grammar)
262                 {
263                         return makeSingle (grammar);
264                 }
265
266                 private RdpPattern makeSingle (RelaxngGrammar g)
267                 {
268                         // Flatten patterns into RdpGroup. See 4.12.
269                         if (patterns.Count == 0)
270                                 throw new RelaxngException (this, "No pattern contents.");
271                         RdpPattern p = ((RelaxngPattern) patterns [0]).Compile (g);
272                         if (patterns.Count == 1)
273                                 return p;
274                         for (int i=1; i<patterns.Count; i++) {
275                                 p = new RdpGroup (p,
276                                         ((RelaxngPattern) patterns [i]).Compile (g));
277                         }
278                         return p;
279                 }
280         }
281
282         public class RelaxngInclude : RelaxngElementBase, IGrammarContent
283         {
284                 string href;
285                 RelaxngGrammarContentList starts = new RelaxngGrammarContentList ();
286                 RelaxngGrammarContentList defines = new RelaxngGrammarContentList ();
287                 RelaxngGrammarContentList divs = new RelaxngGrammarContentList ();
288                 string ns;
289
290                 public RelaxngInclude ()
291                 {
292                 }
293
294                 public string Href {
295                         get { return href; }
296                         set { href = value; }
297                 }
298
299                 public RelaxngGrammarContentList Starts {
300                         get { return starts; }
301                 }
302
303                 public RelaxngGrammarContentList Defines {
304                         get { return defines; }
305                 }
306
307                 public RelaxngGrammarContentList Divs {
308                         get { return divs; }
309                 }
310
311                 public string NSContext {
312                         get { return ns; }
313                         set { ns = value; }
314                 }
315
316                 public override void Write (XmlWriter writer)
317                 {
318                         writer.WriteStartElement ("", "include", RelaxngGrammar.NamespaceURI);
319                         writer.WriteAttributeString ("href", href);
320                         foreach (RelaxngStart start in Starts)
321                                 start.Write (writer);
322                         foreach (RelaxngDefine define in Defines)
323                                 define.Write (writer);
324                         foreach (RelaxngDiv div in Divs)
325                                 div.Write (writer);
326                         writer.WriteEndElement ();
327                 }
328
329                 internal override void WriteRnc (RncWriter writer)
330                 {
331                         writer.WriteInclude (this);
332                 }
333
334                 // compile into div
335                 internal RelaxngDiv Compile (RelaxngGrammar grammar)
336                 {
337                         grammar.CheckIncludeRecursion (Href);
338                         grammar.IncludedUris.Add (Href, Href);
339                         if (grammar.Resolver == null)
340                                 throw new RelaxngException (this, "To compile 'include' element, XmlResolver is required.");
341                         Uri baseUri = null;
342                         try {
343                                 if (BaseUri != null && BaseUri != String.Empty)
344                                         baseUri = new Uri (BaseUri);
345                         } catch (UriFormatException) {
346                                 if (File.Exists (BaseUri))
347                                         baseUri = new Uri (Path.GetFullPath (BaseUri));
348                         }
349                         Uri uri = grammar.Resolver.ResolveUri (baseUri, Href);
350
351                         RelaxngGrammar g = ReadExternalResource (grammar, uri, (ns != null && ns.Length != 0) || !grammar.IsSourceCompactSyntax ? ns : grammar.DefaultNamespace) as RelaxngGrammar;
352                         if (g == null)
353                                 throw new RelaxngException (this, "Included syntax must start with \"grammar\" element.");
354                         g.DataProvider = grammar.Provider;
355                         g.IsSourceCompactSyntax = grammar.IsSourceCompactSyntax;
356
357                         // process recursive inclusions.
358                         foreach (RelaxngInclude inc in g.Includes)
359                                 g.Divs.Add (inc.Compile (grammar));
360
361                         // process this own div children.
362                         // each div subelements are also compiled.
363                         foreach (RelaxngDiv cdiv in divs)
364                                 cdiv.Compile (g);
365                         foreach (RelaxngDiv cdiv in g.Divs)
366                                 cdiv.Compile (g);
367
368                         // replace redifinitions into div.
369                         // starts.
370                         if (this.Starts.Count > 0 && g.Starts.Count == 0)
371                                 throw new RelaxngException (this, "When the included grammar does not contain start components, this include component must not contain start components.");
372                         RelaxngGrammarContentList appliedStarts = (this.starts.Count > 0) ?
373                                 this.starts : g.Starts;
374
375                         RelaxngDiv div = new RelaxngDiv ();
376                         div.BaseUri = this.BaseUri;
377                         div.LinePosition = this.LinePosition;
378                         div.LineNumber = this.LineNumber;
379
380                         foreach (RelaxngStart start in appliedStarts)
381                                 div.Starts.Add (start);
382
383                         // defines.
384                         Hashtable overrides = new Hashtable ();
385                         Hashtable originalDefs = new Hashtable ();
386                         foreach (RelaxngDefine def in defines) {
387                                 overrides.Add (def.Name, def.Name);
388                                 div.Defines.Add (def);
389                         }
390                         foreach (RelaxngDefine def in g.Defines) {
391                                 originalDefs [def.Name] = def.Name;
392                                 if (!overrides.ContainsKey (def.Name)) {
393                                         div.Defines.Add (def);
394                                 }
395                                 // else discard.
396                         }
397
398                         foreach (string name in overrides.Values)
399                                 if (!originalDefs.ContainsKey (name))
400                                         throw new RelaxngException (this, "The include component must not contain define components whose name does not appear in the included grammar component.");
401
402                         grammar.IncludedUris.Remove (Href);
403                         return div;
404                 }
405         }
406
407         public class RelaxngDiv : RelaxngElementBase, IGrammarContent
408         {
409                 RelaxngGrammarContentList starts = new RelaxngGrammarContentList ();
410                 RelaxngGrammarContentList defines = new RelaxngGrammarContentList ();
411                 RelaxngGrammarContentList includes = new RelaxngGrammarContentList ();
412                 RelaxngGrammarContentList divs = new RelaxngGrammarContentList ();
413
414                 public RelaxngDiv ()
415                 {
416                 }
417
418                 public RelaxngGrammarContentList Starts {
419                         get { return starts; }
420                 }
421
422                 public RelaxngGrammarContentList Defines {
423                         get { return defines; }
424                 }
425
426                 public RelaxngGrammarContentList Includes {
427                         get { return includes; }
428                 }
429
430                 public RelaxngGrammarContentList Divs {
431                         get { return divs; }
432                 }
433
434                 public override void Write (XmlWriter writer)
435                 {
436                         writer.WriteStartElement ("", "div", RelaxngGrammar.NamespaceURI);
437                         foreach (RelaxngStart start in Starts)
438                                 start.Write (writer);
439                         foreach (RelaxngDefine define in Defines)
440                                 define.Write (writer);
441                         foreach (RelaxngInclude include in Includes)
442                                 include.Write (writer);
443                         foreach (RelaxngDiv div in Divs)
444                                 div.Write (writer);
445                         writer.WriteEndElement ();
446                 }
447
448                 internal override void WriteRnc (RncWriter writer)
449                 {
450                         writer.WriteDiv (this);
451                 }
452
453                 internal void Compile (RelaxngGrammar grammar)
454                 {
455                         foreach (RelaxngDiv div in divs)
456                                 div.Compile (grammar);
457                         foreach (RelaxngInclude inc in includes)
458                                 inc.Compile (grammar).Compile (grammar); // compile compiled divs
459                         foreach (RelaxngStart start in starts)
460                                 grammar.Starts.Add (start);
461                         foreach (RelaxngDefine define in defines)
462                                 grammar.Defines.Add (define);
463                 }
464         }
465         #endregion
466
467         #region RelaxngPatterns
468         public abstract class RelaxngPattern : RelaxngElementBase
469         {
470                 // static
471
472                 public static RelaxngPattern Read (XmlReader xmlReader)
473                 {
474                         return Read (xmlReader, null);
475                 }
476
477                 public static RelaxngPattern Read (XmlReader xmlReader, RelaxngDatatypeProvider provider)
478                 {
479                         return Read (xmlReader, provider, new XmlUrlResolver ());
480                 }
481                 
482                 public static RelaxngPattern Read (XmlReader xmlReader, RelaxngDatatypeProvider provider, XmlResolver xmlResolver)
483                 {
484                         RelaxngReader r = new RelaxngReader (xmlReader, null, xmlResolver);
485                         if (r.ReadState == ReadState.Initial)
486                                 r.Read ();
487                         r.MoveToContent ();
488                         RelaxngPattern p = r.ReadPattern ();
489                         p.DataProvider = provider;
490                         p.XmlResolver = xmlResolver;
491                         return p;
492                 }
493
494                 // Private Fields
495                 RdpPattern startRelaxngPattern;
496                 RelaxngDatatypeProvider provider;
497                 XmlResolver resolver;
498                 bool nullResolver;
499
500                 // Public
501                 public XmlResolver XmlResolver {
502                         set {
503                                 nullResolver = value == null;
504                                 resolver = value;
505                         }
506                 }
507
508                 public abstract RelaxngPatternType PatternType { get; }
509                 public RelaxngDatatypeProvider DataProvider {
510                         get {
511                                 return provider; 
512                         }
513                         set { 
514                                 provider = value; 
515                         }
516                 }
517
518                 public void Compile ()
519                 {
520                         RelaxngGrammar g = null;
521                         if (this is RelaxngGrammar)
522                                 g = (RelaxngGrammar) this;
523                         else {
524                                 g = new RelaxngGrammar ();
525                                 g.XmlResolver = this.Resolver;
526                                 g.BaseUri = this.BaseUri;
527                                 g.LineNumber = this.LineNumber;
528                                 g.LinePosition = this.LinePosition;
529                                 RelaxngStart st = new RelaxngStart ();
530                                 st.BaseUri = this.BaseUri;
531                                 st.LineNumber = this.LineNumber;
532                                 st.LinePosition = this.LinePosition;
533                                 st.Pattern = this;
534                                 g.Starts.Add (st);
535                                 g.Provider = provider;
536                         }
537                         startRelaxngPattern = g.Compile (null);
538                         this.IsCompiled = true;
539                 }
540
541                 public void WriteCompact (TextWriter writer)
542                 {
543                         WriteCompact (new RncWriter (writer));
544                 }
545
546                 public void WriteCompact (TextWriter writer, NSResolver res)
547                 {
548                         WriteCompact (new RncWriter (writer, res));
549                 }
550
551                 void WriteCompact (RncWriter writer)
552                 {
553                         RelaxngGrammar g = this as RelaxngGrammar;
554                         string ns = (g != null ? g.DefaultNamespace : null);
555                         writer.WriteNamespaces (ns);
556                         WriteRnc (writer);
557                 }
558
559                 // Internal
560                 internal XmlResolver Resolver {
561                         get {
562                                 if (nullResolver)
563                                         return null;
564                                 if (resolver == null)
565                                         resolver = new XmlUrlResolver ();
566                                 return resolver;
567                         }
568                 }
569
570                 internal abstract void CheckConstraints ();
571
572                 protected RelaxngPattern () 
573                 {
574                 }
575
576                 internal abstract RdpPattern Compile (RelaxngGrammar grammar);
577
578                 internal RdpPattern StartPattern {
579                         get { return startRelaxngPattern; }
580                 }
581         }
582
583         public class RelaxngPatternList : CollectionBase
584         {
585                 public RelaxngPatternList ()
586                 {
587                 }
588
589                 public void Add (RelaxngPattern p)
590                 {
591                         List.Add (p);
592                 }
593
594                 public RelaxngPattern this [int i] {
595                         get { return this.List [i] as RelaxngPattern; }
596                         set { this.List [i] = value; }
597                 }
598
599                 public void Insert (int pos, RelaxngPattern p)
600                 {
601                         List.Insert (pos, p);
602                 }
603
604                 public void Remove (RelaxngPattern p)
605                 {
606                         List.Remove (p);
607                 }
608         }
609
610         public class RelaxngGrammarContentList : CollectionBase
611         {
612                 public RelaxngGrammarContentList ()
613                 {
614                 }
615
616                 public void Add (IGrammarContent p)
617                 {
618                         List.Add (p);
619                 }
620
621                 public IGrammarContent this [int i] {
622                         get { return this.List [i] as IGrammarContent; }
623                         set { this.List [i] = value; }
624                 }
625
626                 public void Insert (int pos, IGrammarContent p)
627                 {
628                         List.Insert (pos, p);
629                 }
630
631                 public void Remove (IGrammarContent p)
632                 {
633                         List.Remove (p);
634                 }
635         }
636
637         // strict to say, it's not a pattern ;)
638         public class RelaxngNotAllowed : RelaxngPattern
639         {
640                 public RelaxngNotAllowed () 
641                 {
642                 }
643
644                 public override RelaxngPatternType PatternType {
645                         get { return RelaxngPatternType.NotAllowed; }
646                 }
647
648                 public override void Write (XmlWriter writer)
649                 {
650                         writer.WriteStartElement ("", "notAllowed", RelaxngGrammar.NamespaceURI);
651                         writer.WriteEndElement ();
652                 }
653
654                 internal override void WriteRnc (RncWriter writer)
655                 {
656                         writer.WriteNotAllowed (this);
657                 }
658
659                 internal override RdpPattern Compile (RelaxngGrammar grammar)
660                 {
661                         return RdpNotAllowed.Instance;
662                 }
663
664                 internal override void CheckConstraints () 
665                 {
666                         // nothing to check
667                 }
668         }
669
670         public class RelaxngEmpty : RelaxngPattern
671         {
672                 public RelaxngEmpty ()
673                 {
674                 }
675
676                 public override RelaxngPatternType PatternType {
677                         get { return RelaxngPatternType.Empty; }
678                 }
679
680                 public override void Write (XmlWriter writer)
681                 {
682                         writer.WriteStartElement ("", "empty", RelaxngGrammar.NamespaceURI);
683                         writer.WriteEndElement ();
684                 }
685
686                 internal override void WriteRnc (RncWriter writer)
687                 {
688                         writer.WriteEmpty (this);
689                 }
690
691                 internal override RdpPattern Compile (RelaxngGrammar grammar)
692                 {
693                         return RdpEmpty.Instance;
694                 }
695
696                 internal override void CheckConstraints () 
697                 {
698                         // nothing to check
699                 }
700         }
701
702         public class RelaxngText : RelaxngPattern
703         {
704                 public RelaxngText () 
705                 {
706                 }
707
708                 public override RelaxngPatternType PatternType {
709                         get { return RelaxngPatternType.Text; }
710                 }
711
712                 public override void Write (XmlWriter writer)
713                 {
714                         writer.WriteStartElement ("", "text", RelaxngGrammar.NamespaceURI);
715                         writer.WriteEndElement ();
716                 }
717
718                 internal override void WriteRnc (RncWriter writer)
719                 {
720                         writer.WriteText (this);
721                 }
722
723                 internal override RdpPattern Compile (RelaxngGrammar grammar)
724                 {
725                         return RdpText.Instance;
726                 }
727
728                 internal override void CheckConstraints () 
729                 {
730                         // nothing to check
731                 }
732         }
733
734         public abstract class RelaxngDataSupport : RelaxngPattern
735         {
736                 string type;
737                 string datatypeLibrary;
738
739                 public string Type {
740                         get { return type; }
741                         set { type = value; }
742                 }
743
744                 public string DatatypeLibrary {
745                         get { return datatypeLibrary; }
746                         set { datatypeLibrary = value; }
747                 }
748
749                 internal void CheckDatatypeName ()
750                 {
751                         // Data type name check is done in RdpData(Except) derivative creation.
752                 }
753         }
754
755         public class RelaxngData : RelaxngDataSupport
756         {
757                 RelaxngParamList paramList = new RelaxngParamList ();
758                 RelaxngExcept except;
759
760                 public RelaxngData ()
761                 {
762                 }
763
764                 public override RelaxngPatternType PatternType {
765                         get { return RelaxngPatternType.Data; }
766                 }
767
768                 public RelaxngParamList ParamList {
769                         get { return paramList; }
770                 }
771
772                 public RelaxngExcept Except {
773                         get { return except; }
774                         set { except = value; }
775                 }
776
777                 public override void Write (XmlWriter writer)
778                 {
779                         writer.WriteStartElement ("", "data", RelaxngGrammar.NamespaceURI);
780                         if (DatatypeLibrary != null && DatatypeLibrary != String.Empty)
781                                 writer.WriteAttributeString ("datatypeLibrary", DatatypeLibrary);
782                         writer.WriteAttributeString ("type", Type);
783
784                         foreach (RelaxngParam p in ParamList)
785                                 p.Write (writer);
786
787                         if (Except != null)
788                                 Except.Write (writer);
789
790                         writer.WriteEndElement ();
791                 }
792
793                 internal override void WriteRnc (RncWriter writer)
794                 {
795                         writer.WriteData (this);
796                 }
797
798                 internal override RdpPattern Compile (RelaxngGrammar grammar)
799                 {
800 //                      RdpParamList rdpl = new RdpParamList ();
801 //                      foreach (RelaxngParam prm in this.paramList)
802 //                              rdpl.Add (prm.Compile (grammar));
803                         RdpPattern p = null;
804                         if (this.except != null) {
805                                 if (except.Patterns.Count == 0)
806                                         throw new RelaxngException (this, "data except pattern have no children.");
807                                 p = except.Patterns [0].Compile (grammar);
808                                 for (int i=1; i<except.Patterns.Count; i++)
809                                         p = new RdpChoice (p,
810                                                 except.Patterns [i].Compile (grammar));
811                         }
812
813                         IsCompiled = true;
814                         if (this.except != null)
815                                 return new RdpDataExcept (new RdpDatatype (DatatypeLibrary, Type, ParamList, grammar.Provider), p);
816                         else
817                                 return new RdpData (new RdpDatatype (DatatypeLibrary, Type, ParamList, grammar.Provider));
818                 }
819
820                 internal override void CheckConstraints () 
821                 {
822                         CheckDatatypeName ();
823                 }
824         }
825
826         public class RelaxngValue : RelaxngDataSupport
827         {
828                 string value;
829
830                 public override RelaxngPatternType PatternType {
831                         get { return RelaxngPatternType.Value; }
832                 }
833
834                 public string Value {
835                         get { return value; }
836                         set { this.value = value; }
837                 }
838
839                 public override void Write (XmlWriter writer)
840                 {
841                         writer.WriteStartElement ("", "value", RelaxngGrammar.NamespaceURI);
842                         if (Type != null) {
843                                 writer.WriteStartAttribute ("type", String.Empty);
844                                 if (DatatypeLibrary != null && DatatypeLibrary != String.Empty)
845                                         writer.WriteAttributeString ("datatypeLibrary", DatatypeLibrary);
846                                 writer.WriteAttributeString ("type", Type);
847                         }
848                         writer.WriteString (Value);
849                         writer.WriteEndElement ();
850                 }
851
852                 internal override void WriteRnc (RncWriter writer)
853                 {
854                         writer.WriteValue (this);
855                 }
856
857                 internal override RdpPattern Compile (RelaxngGrammar grammar)
858                 {
859                         IsCompiled = true;
860                         return new RdpValue (new RdpDatatype (DatatypeLibrary,
861                                 Type, null, grammar.Provider), value);
862                 }
863
864                 internal override void CheckConstraints () 
865                 {
866                         CheckDatatypeName ();
867                 }
868         }
869
870         public class RelaxngList : RelaxngSingleContentPattern
871         {
872                 internal RelaxngList ()
873                 {
874                 }
875
876                 public override RelaxngPatternType PatternType {
877                         get { return RelaxngPatternType.List; }
878                 }
879
880                 public override void Write (XmlWriter writer)
881                 {
882                         writer.WriteStartElement ("", "list", RelaxngGrammar.NamespaceURI);
883                         foreach (RelaxngPattern p in Patterns)
884                                 p.Write (writer);
885                         writer.WriteEndElement ();
886                 }
887
888                 internal override void WriteRnc (RncWriter writer)
889                 {
890                         writer.WriteList (this);
891                 }
892
893                 internal override RdpPattern Compile (RelaxngGrammar grammar)
894                 {
895
896                         IsCompiled = true;
897                         return new RdpList (makeSingle (grammar));
898                 }
899
900                 internal override void CheckConstraints () 
901                 {
902                         // nothing to check
903                 }
904         }
905
906         public class RelaxngElement : RelaxngSingleContentPattern
907         {
908                 RelaxngNameClass nc;
909
910                 public RelaxngElement ()
911                 {
912                 }
913
914                 public RelaxngNameClass NameClass {
915                         get { return nc; }
916                         set { nc = value; }
917                 }
918
919                 public override RelaxngPatternType PatternType {
920                         get { return RelaxngPatternType.Element; }
921                 }
922
923                 public override void Write (XmlWriter writer)
924                 {
925                         writer.WriteStartElement ("", "element", RelaxngGrammar.NamespaceURI);
926                         nc.Write (writer);
927                         foreach (RelaxngPattern p in Patterns)
928                                 p.Write (writer);
929                         writer.WriteEndElement ();
930                 }
931
932                 internal override void WriteRnc (RncWriter writer)
933                 {
934                         writer.WriteElement (this);
935                 }
936
937                 internal override RdpPattern Compile (RelaxngGrammar grammar)
938                 {
939                         return new RdpElement (
940                                 nc.Compile (grammar), this.makeSingle (grammar));
941                 }
942
943                 internal override void CheckConstraints () 
944                 {
945                         NameClass.CheckConstraints (false, false);
946
947                         foreach (RelaxngPattern p in Patterns)
948                                 p.CheckConstraints ();
949                 }
950         }
951
952         public class RelaxngAttribute : RelaxngPattern
953         {
954                 RelaxngNameClass nc;
955                 RelaxngPattern p;
956
957                 public RelaxngAttribute ()
958                 {
959                 }
960
961                 public RelaxngPattern Pattern {
962                         get { return p; }
963                         set { p = value; }
964                 }
965
966                 public RelaxngNameClass NameClass {
967                         get { return nc; }
968                         set { nc = value; }
969                 }
970
971                 public override RelaxngPatternType PatternType {
972                         get { return RelaxngPatternType.Attribute; }
973                 }
974
975                 public override void Write (XmlWriter writer)
976                 {
977                         writer.WriteStartElement ("", "attribute", RelaxngGrammar.NamespaceURI);
978                         nc.Write (writer);
979                         if (p != null)
980                                 p.Write (writer);
981                         writer.WriteEndElement ();
982                 }
983
984                 internal override void WriteRnc (RncWriter writer)
985                 {
986                         writer.WriteAttribute (this);
987                 }
988
989                 private void checkInvalidAttrNameClass (RdpNameClass nc)
990                 {
991                         string xmlnsNS = "http://www.w3.org/2000/xmlns";
992                         RdpNameClassChoice choice = nc as RdpNameClassChoice;
993                         if (choice != null) {
994                                 checkInvalidAttrNameClass (choice.LValue);
995                                 checkInvalidAttrNameClass (choice.RValue);
996                                 return;
997                         }
998                         RdpAnyNameExcept except = nc as RdpAnyNameExcept;
999                         if (except != null) {
1000                                 checkInvalidAttrNameClass (except.ExceptNameClass);
1001                                 return;
1002                         }
1003                         if (nc is RdpAnyName)
1004                                 return;
1005
1006                         RdpName n = nc as RdpName;
1007                         if (n != null) {
1008                                 if (n.NamespaceURI == xmlnsNS)
1009                                         throw new RelaxngException (this, "cannot specify \"" + xmlnsNS + "\" for name of attribute.");
1010                                 if (n.LocalName == "xmlns" && n.NamespaceURI == "")
1011                                         throw new RelaxngException (this, "cannot specify \"xmlns\" inside empty ns context.");
1012                         } else {
1013                                 RdpNsName nn = nc as RdpNsName;
1014                                 if (nn.NamespaceURI == "http://www.w3.org/2000/xmlns")
1015                                         throw new RelaxngException (this, "cannot specify \"" + xmlnsNS + "\" for name of attribute.");
1016                                 RdpNsNameExcept x = nc as RdpNsNameExcept;
1017                                 if (x != null)
1018                                         checkInvalidAttrNameClass (x.ExceptNameClass);
1019                         }
1020                 }
1021
1022                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1023                 {
1024                         IsCompiled = true;
1025                         RdpNameClass cnc = nc.Compile (grammar);
1026                         this.checkInvalidAttrNameClass (cnc);
1027
1028                         return new RdpAttribute (cnc,
1029                                 (p != null) ?
1030                                         p.Compile (grammar) :
1031                                         RdpText.Instance);
1032                 }
1033
1034                 internal override void CheckConstraints () 
1035                 {
1036                         NameClass.CheckConstraints (false, false);
1037
1038                         if (p != null)
1039                                 p.CheckConstraints ();
1040                 }
1041         }
1042
1043         internal class RdpUnresolvedRef : RdpPattern
1044         {
1045                 string name;
1046 //              bool parentRef;
1047                 RelaxngGrammar targetGrammar;
1048                 RdpPattern referencedPattern;
1049
1050                 public RdpUnresolvedRef (string name, RelaxngGrammar g)
1051                 {
1052                         this.name = name;
1053 //                      this.parentRef = parentRef;
1054                         targetGrammar = g;
1055                 }
1056
1057                 public string Name {
1058                         get { return name; }
1059                         set { name = value; }
1060                 }
1061
1062                 public RdpPattern RefPattern {
1063                         get { return referencedPattern; }
1064                         set { referencedPattern = value; }
1065                 }
1066
1067 //              public bool IsParentRef {
1068 //                      get { return parentRef; }
1069 //              }
1070
1071                 public RelaxngGrammar TargetGrammar {
1072                         get { return targetGrammar; }
1073                 }
1074
1075                 public override RelaxngPatternType PatternType {
1076                         get { return RelaxngPatternType.Ref; }
1077                 }
1078
1079                 public override RdpContentType ContentType {
1080                         get { return RdpContentType.Empty; }
1081                 }
1082
1083
1084                 public override bool Nullable {
1085                         get {
1086                                 throw new InvalidOperationException ("Internal error: should not reach.");
1087                         }
1088                 }
1089
1090                 public override void GetLabels (Hashtable elements, Hashtable attributes, bool collectNameClass)
1091                 {
1092                         // Now it could reach (CheckNameOverlap) so comment out here.
1093 //                      throw new InvalidOperationException ("Internal error: should not reach.");
1094                 }
1095
1096                 internal override RdpPattern ExpandRef (Hashtable defs)
1097                 {
1098                         return referencedPattern.ExpandRef (defs);
1099                 }
1100
1101                 internal override void MarkReachableDefs () 
1102                 {
1103                         TargetGrammar.MarkReacheableDefine (this.name);
1104                 }
1105
1106                 internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
1107                 {
1108                         referencedPattern =
1109                                 referencedPattern.ReduceEmptyAndNotAllowed (
1110                                 ref result, visited);
1111                         return this;
1112                 }
1113
1114                 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept) 
1115                 {
1116 //                      throw new InvalidOperationException ();
1117                 }
1118
1119                 internal override bool ContainsText ()
1120                 {
1121                         return false;
1122 //                      throw new InvalidOperationException ();
1123                 }
1124         }
1125
1126         public class RelaxngRef : RelaxngPattern
1127         {
1128                 string name;
1129
1130                 public RelaxngRef ()
1131                 {
1132                 }
1133
1134                 public string Name {
1135                         get { return name; }
1136                         set { name = value; }
1137                 }
1138
1139                 public override RelaxngPatternType PatternType {
1140                         get { return RelaxngPatternType.Ref; }
1141                 }
1142
1143                 public override void Write (XmlWriter writer)
1144                 {
1145                         writer.WriteStartElement ("", "ref", RelaxngGrammar.NamespaceURI);
1146                         writer.WriteAttributeString ("name", name);
1147                         writer.WriteEndElement ();
1148                 }
1149
1150                 internal override void WriteRnc (RncWriter writer)
1151                 {
1152                         writer.WriteRef (this);
1153                 }
1154
1155                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1156                 {
1157                         // Important!! This compile method only generates stub.
1158                         IsCompiled = false;
1159                         return new RdpUnresolvedRef (name, grammar);
1160                 }
1161
1162                 internal override void CheckConstraints () 
1163                 {
1164                         // nothing to check
1165                 }
1166         }
1167
1168         public class RelaxngParentRef : RelaxngPattern
1169         {
1170                 string name;
1171
1172                 public RelaxngParentRef ()
1173                 {
1174                 }
1175
1176                 public string Name {
1177                         get { return name; }
1178                         set { name = value; }
1179                 }
1180
1181                 public override RelaxngPatternType PatternType {
1182                         get { return RelaxngPatternType.ParentRef; }
1183                 }
1184
1185                 public override void Write (XmlWriter writer)
1186                 {
1187                         writer.WriteStartElement ("", "parentRef", RelaxngGrammar.NamespaceURI);
1188                         writer.WriteAttributeString ("name", name);
1189                         writer.WriteEndElement ();
1190                 }
1191
1192                 internal override void WriteRnc (RncWriter writer)
1193                 {
1194                         writer.WriteParentRef (this);
1195                 }
1196
1197                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1198                 {
1199                         IsCompiled = false;
1200                         return new RdpUnresolvedRef (name, grammar.ParentGrammar);
1201                 }
1202
1203                 internal override void CheckConstraints () 
1204                 {
1205                         // nothing to check
1206                 }
1207         }
1208
1209         public class RelaxngExternalRef : RelaxngPattern
1210         {
1211                 string href;
1212                 string ns;
1213
1214                 public RelaxngExternalRef ()
1215                 {
1216                 }
1217
1218                 public string Href {
1219                         get { return href; }
1220                         set { href = value; }
1221                 }
1222
1223                 public string NSContext {
1224                         get { return ns; }
1225                         set { ns = value; }
1226                 }
1227
1228                 public override RelaxngPatternType PatternType {
1229                         get { return RelaxngPatternType.ExternalRef; }
1230                 }
1231
1232                 public override void Write (XmlWriter writer)
1233                 {
1234                         writer.WriteStartElement ("", "externalRef", RelaxngGrammar.NamespaceURI);
1235                         writer.WriteAttributeString ("href", Href);
1236                         writer.WriteEndElement ();
1237                 }
1238
1239                 internal override void WriteRnc (RncWriter writer)
1240                 {
1241                         writer.WriteExternalRef (this);
1242                 }
1243
1244                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1245                 {
1246                         grammar.CheckIncludeRecursion (Href);
1247                         grammar.IncludedUris.Add (Href, Href);
1248                         if (grammar.Resolver == null)
1249                                 throw new RelaxngException (this, "To compile 'include' element, XmlResolver is required.");
1250                         Uri uri = grammar.Resolver.ResolveUri (BaseUri != String.Empty ? new Uri (BaseUri) : null, Href);
1251                         RelaxngPattern p = ReadExternalResource (grammar, uri, ns);
1252
1253                         p.DataProvider = grammar.Provider;
1254                         RdpPattern ret = p.Compile (grammar);
1255
1256                         grammar.IncludedUris.Remove (Href);
1257
1258                         return ret;
1259
1260                 }
1261
1262                 internal override void CheckConstraints () 
1263                 {
1264                         // nothing to check
1265                 }
1266         }
1267
1268         public class RelaxngOneOrMore : RelaxngSingleContentPattern
1269         {
1270                 public RelaxngOneOrMore ()
1271                 {
1272                 }
1273
1274                 public override RelaxngPatternType PatternType {
1275                         get { return RelaxngPatternType.OneOrMore; }
1276                 }
1277
1278                 public override void Write (XmlWriter writer)
1279                 {
1280                         writer.WriteStartElement ("", "oneOrMore", RelaxngGrammar.NamespaceURI);
1281                         foreach (RelaxngPattern p in Patterns)
1282                                 p.Write (writer);
1283                         writer.WriteEndElement ();
1284                 }
1285
1286                 internal override void WriteRnc (RncWriter writer)
1287                 {
1288                         writer.WriteOneOrMore (this);
1289                 }
1290
1291                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1292                 {
1293                         IsCompiled = true;
1294                         return new RdpOneOrMore (makeSingle (grammar));
1295                 }
1296         }
1297
1298         public class RelaxngZeroOrMore : RelaxngSingleContentPattern
1299         {
1300                 public RelaxngZeroOrMore ()
1301                 {
1302                 }
1303
1304                 public override RelaxngPatternType PatternType {
1305                         get { return RelaxngPatternType.ZeroOrMore; }
1306                 }
1307
1308                 public override void Write (XmlWriter writer)
1309                 {
1310                         writer.WriteStartElement ("", "zeroOrMore", RelaxngGrammar.NamespaceURI);
1311                         foreach (RelaxngPattern p in Patterns)
1312                                 p.Write (writer);
1313                         writer.WriteEndElement ();
1314                 }
1315
1316                 internal override void WriteRnc (RncWriter writer)
1317                 {
1318                         writer.WriteZeroOrMore (this);
1319                 }
1320
1321                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1322                 {
1323                         IsCompiled = true;
1324                         return new RdpChoice (
1325                                 new RdpOneOrMore (makeSingle (grammar)),
1326                                 RdpEmpty.Instance);
1327                 }
1328         }
1329
1330         public class RelaxngOptional : RelaxngSingleContentPattern
1331         {
1332                 public RelaxngOptional ()
1333                 {
1334                 }
1335
1336                 public override RelaxngPatternType PatternType {
1337                         get { return RelaxngPatternType.Optional; }
1338                 }
1339
1340                 public override void Write (XmlWriter writer)
1341                 {
1342                         writer.WriteStartElement ("", "optional", RelaxngGrammar.NamespaceURI);
1343                         foreach (RelaxngPattern p in Patterns)
1344                                 p.Write (writer);
1345                         writer.WriteEndElement ();
1346                 }
1347
1348                 internal override void WriteRnc (RncWriter writer)
1349                 {
1350                         writer.WriteOptional (this);
1351                 }
1352
1353                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1354                 {
1355                         IsCompiled = true;
1356                         return new RdpChoice (
1357                                 makeSingle (grammar), RdpEmpty.Instance);
1358                 }
1359         }
1360
1361         public class RelaxngMixed : RelaxngSingleContentPattern
1362         {
1363                 public RelaxngMixed ()
1364                 {
1365                 }
1366
1367                 public override RelaxngPatternType PatternType {
1368                         get { return RelaxngPatternType.Mixed; }
1369                 }
1370
1371                 public override void Write (XmlWriter writer)
1372                 {
1373                         writer.WriteStartElement ("", "mixed", RelaxngGrammar.NamespaceURI);
1374                         foreach (RelaxngPattern p in Patterns)
1375                                 p.Write (writer);
1376                         writer.WriteEndElement ();
1377                 }
1378
1379                 internal override void WriteRnc (RncWriter writer)
1380                 {
1381                         writer.WriteMixed (this);
1382                 }
1383
1384                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1385                 {
1386                         IsCompiled = true;
1387                         return new RdpInterleave (makeSingle (grammar), RdpText.Instance);
1388                 }
1389         }
1390
1391         public class RelaxngChoice : RelaxngBinaryContentPattern
1392         {
1393                 public RelaxngChoice ()
1394                 {
1395                 }
1396
1397                 public override RelaxngPatternType PatternType {
1398                         get { return RelaxngPatternType.Choice; }
1399                 }
1400
1401                 public override void Write (XmlWriter writer)
1402                 {
1403                         writer.WriteStartElement ("", "choice", RelaxngGrammar.NamespaceURI);
1404                         foreach (RelaxngPattern p in Patterns)
1405                                 p.Write (writer);
1406                         writer.WriteEndElement ();
1407                 }
1408
1409                 internal override void WriteRnc (RncWriter writer)
1410                 {
1411                         writer.WriteChoice (this);
1412                 }
1413
1414                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1415                 {
1416                         IsCompiled = true;
1417                         return makeBinary (grammar);
1418                 }
1419         }
1420
1421         public class RelaxngGroup : RelaxngBinaryContentPattern
1422         {
1423                 public RelaxngGroup ()
1424                 {
1425                 }
1426
1427                 public override RelaxngPatternType PatternType {
1428                         get { return RelaxngPatternType.Group; }
1429                 }
1430
1431                 public override void Write (XmlWriter writer)
1432                 {
1433                         writer.WriteStartElement ("", "group", RelaxngGrammar.NamespaceURI);
1434                         foreach (RelaxngPattern p in Patterns)
1435                                 p.Write (writer);
1436                         writer.WriteEndElement ();
1437                 }
1438
1439                 internal override void WriteRnc (RncWriter writer)
1440                 {
1441                         writer.WriteGroup (this);
1442                 }
1443
1444                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1445                 {
1446                         IsCompiled = true;
1447                         return makeBinary (grammar);
1448                 }
1449         }
1450
1451         public class RelaxngInterleave : RelaxngBinaryContentPattern
1452         {
1453                 public RelaxngInterleave ()
1454                 {
1455                 }
1456
1457                 public override RelaxngPatternType PatternType {
1458                         get { return RelaxngPatternType.Interleave; }
1459                 }
1460
1461                 public override void Write (XmlWriter writer)
1462                 {
1463                         writer.WriteStartElement ("", "interleave", RelaxngGrammar.NamespaceURI);
1464                         foreach (RelaxngPattern p in Patterns)
1465                                 p.Write (writer);
1466                         writer.WriteEndElement ();
1467                 }
1468
1469                 internal override void WriteRnc (RncWriter writer)
1470                 {
1471                         writer.WriteInterleave (this);
1472                 }
1473
1474                 internal override RdpPattern Compile (RelaxngGrammar grammar)
1475                 {
1476                         IsCompiled = true;
1477                         return makeBinary (grammar);
1478                 }
1479         }
1480
1481         public class RelaxngParam : RelaxngElementBase
1482         {
1483                 string name;
1484                 string value;
1485
1486                 public RelaxngParam ()
1487                 {
1488                 }
1489
1490                 public RelaxngParam (string name, string value)
1491                 {
1492                         this.name = name;
1493                         this.value = value;
1494                 }
1495
1496                 public string Name {
1497                         get { return name; }
1498                         set { name = value; }
1499                 }
1500
1501                 public string Value {
1502                         get { return value; }
1503                         set { this.value = value; }
1504                 }
1505
1506                 public override void Write (XmlWriter writer)
1507                 {
1508                         writer.WriteStartElement ("", "param", RelaxngGrammar.NamespaceURI);
1509                         writer.WriteAttributeString ("name", name);
1510                         writer.WriteString (Value);
1511                         writer.WriteEndElement ();
1512                 }
1513
1514                 internal override void WriteRnc (RncWriter writer)
1515                 {
1516                         writer.WriteParam (this);
1517                 }
1518
1519                 internal RdpParam Compile (RelaxngGrammar grammar)
1520                 {
1521                         IsCompiled = true;
1522                         return new RdpParam (name, value);
1523                 }
1524         }
1525
1526         public class RelaxngParamList : CollectionBase
1527         {
1528                 public RelaxngParamList ()
1529                 {
1530                 }
1531
1532                 public void Add (RelaxngParam p)
1533                 {
1534                         List.Add (p);
1535                 }
1536
1537                 public RelaxngParam this [int i] {
1538                         get { return this.List [i] as RelaxngParam; }
1539                         set { this.List [i] = value; }
1540                 }
1541
1542                 public void Insert (int pos, RelaxngParam p)
1543                 {
1544                         List.Insert (pos, p);
1545                 }
1546
1547                 public void Remove (RelaxngParam p)
1548                 {
1549                         List.Remove (p);
1550                 }
1551         }
1552
1553         public class RelaxngExcept : RelaxngElementBase
1554         {
1555                 RelaxngPatternList patterns = new RelaxngPatternList ();
1556
1557                 public RelaxngExcept ()
1558                 {
1559                 }
1560
1561                 public RelaxngPatternList Patterns {
1562                         get { return patterns; }
1563                 }
1564
1565                 public override void Write (XmlWriter writer)
1566                 {
1567                         writer.WriteStartElement ("", "except", RelaxngGrammar.NamespaceURI);
1568                         foreach (RelaxngPattern p in Patterns)
1569                                 p.Write (writer);
1570                         writer.WriteEndElement ();
1571                 }
1572
1573                 internal override void WriteRnc (RncWriter writer)
1574                 {
1575                         writer.WriteDataExcept (this);
1576                 }
1577         }
1578
1579         internal class RelaxngRefPattern
1580         {
1581                 RelaxngPattern patternRef;
1582                 string name;
1583
1584                 // When we found ref, use it.
1585                 public RelaxngRefPattern (string name)
1586                 {
1587                         this.name = name;
1588                 }
1589
1590                 // When we found define, use it.
1591                 public RelaxngRefPattern (RelaxngPattern patternRef)
1592                 {
1593                         this.patternRef = patternRef;
1594                 }
1595
1596                 public string Name {
1597                         get { return name; }
1598                 }
1599
1600                 public RelaxngPattern PatternRef {
1601                         get { return patternRef; }
1602                         set { patternRef = value; }
1603                 }
1604         }
1605         #endregion
1606 }