2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / Commons.Xml.Relaxng / Commons.Xml.Relaxng / RelaxngPattern.cs
blobc7cebd9b06da34d5afbb5b5ac0815bde431ebf25
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
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.
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;
41 #if NET_2_0
42 using NSResolver = System.Xml.IXmlNamespaceResolver;
43 #else
44 using NSResolver = System.Xml.XmlNamespaceManager;
45 #endif
47 namespace Commons.Xml.Relaxng
49 #region Common abstract
50 public abstract class RelaxngElementBase
52 bool isCompiled;
53 int lineNumber, linePosition;
54 string baseUri;
56 internal bool IsCompiled {
57 get { return isCompiled; }
58 set { isCompiled = value; }
61 public int LineNumber {
62 get { return lineNumber; }
63 set { lineNumber = value; }
66 public int LinePosition {
67 get { return linePosition; }
68 set { linePosition = value; }
71 public string BaseUri {
72 get { return baseUri; }
73 set { baseUri = value; }
76 public abstract void Write (XmlWriter writer);
78 internal abstract void WriteRnc (RncWriter writer);
80 public RelaxngPattern ReadExternalResource (RelaxngGrammar grammar, Uri uri, string nsContext)
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 ();
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 ();
102 public abstract class RelaxngSingleContentPattern : RelaxngPattern
104 private RelaxngPatternList patterns = new RelaxngPatternList ();
106 public RelaxngPatternList Patterns {
107 get { return patterns; }
110 internal RdpPattern makeSingle (RelaxngGrammar g)
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));
122 return p;
125 internal override void CheckConstraints ()
127 foreach (RelaxngPattern p in Patterns)
128 p.CheckConstraints ();
132 public abstract class RelaxngBinaryContentPattern : RelaxngPattern
134 private RelaxngPatternList patterns = new RelaxngPatternList ();
136 public RelaxngPatternList Patterns {
137 get { return patterns; }
140 internal RdpPattern makeBinary (RelaxngGrammar g)
142 // Flatten patterns. See 4.12.
143 if (patterns.Count == 0)
144 throw new RelaxngException (this, "No pattern contents.");
146 RdpPattern p = ((RelaxngPattern) patterns [0]).Compile (g);
147 if (patterns.Count == 1)
148 return p;
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;
166 return p;
169 internal override void CheckConstraints ()
171 foreach (RelaxngPattern p in Patterns)
172 p.CheckConstraints ();
175 #endregion
177 #region Grammatical elements
178 public interface IGrammarContent
182 public class RelaxngStart : RelaxngElementBase, IGrammarContent
184 RelaxngPattern p;
185 string combine;
187 public RelaxngStart ()
191 public string Combine {
192 get { return combine; }
193 set { combine = value; }
196 public RelaxngPattern Pattern {
197 get { return p; }
198 set { p = value; }
201 public override void Write (XmlWriter writer)
203 writer.WriteStartElement ("", "start", RelaxngGrammar.NamespaceURI);
204 if (combine != null)
205 writer.WriteAttributeString ("combine", combine);
206 p.Write (writer);
207 writer.WriteEndElement ();
210 internal override void WriteRnc (RncWriter writer)
212 writer.WriteStart (this);
215 internal RdpPattern Compile (RelaxngGrammar grammar)
217 return p.Compile (grammar);
221 public class RelaxngDefine : RelaxngElementBase, IGrammarContent
223 string name;
224 private RelaxngPatternList patterns = new RelaxngPatternList ();
225 string combine;
227 public RelaxngDefine ()
231 public RelaxngPatternList Patterns {
232 get { return patterns; }
235 public string Combine {
236 get { return combine; }
237 set { combine = value; }
240 public string Name {
241 get { return name; }
242 set { name = value; }
245 public override void Write (XmlWriter writer)
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 ();
256 internal override void WriteRnc (RncWriter writer)
258 writer.WriteDefine (this);
261 internal RdpPattern Compile (RelaxngGrammar grammar)
263 return makeSingle (grammar);
266 private RdpPattern makeSingle (RelaxngGrammar g)
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));
278 return p;
282 public class RelaxngInclude : RelaxngElementBase, IGrammarContent
284 string href;
285 RelaxngGrammarContentList starts = new RelaxngGrammarContentList ();
286 RelaxngGrammarContentList defines = new RelaxngGrammarContentList ();
287 RelaxngGrammarContentList divs = new RelaxngGrammarContentList ();
288 string ns;
290 public RelaxngInclude ()
294 public string Href {
295 get { return href; }
296 set { href = value; }
299 public RelaxngGrammarContentList Starts {
300 get { return starts; }
303 public RelaxngGrammarContentList Defines {
304 get { return defines; }
307 public RelaxngGrammarContentList Divs {
308 get { return divs; }
311 public string NSContext {
312 get { return ns; }
313 set { ns = value; }
316 public override void Write (XmlWriter writer)
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 ();
329 internal override void WriteRnc (RncWriter writer)
331 writer.WriteInclude (this);
334 // compile into div
335 internal RelaxngDiv Compile (RelaxngGrammar grammar)
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));
349 Uri uri = grammar.Resolver.ResolveUri (baseUri, Href);
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;
357 // process recursive inclusions.
358 foreach (RelaxngInclude inc in g.Includes)
359 g.Divs.Add (inc.Compile (grammar));
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);
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;
375 RelaxngDiv div = new RelaxngDiv ();
376 div.BaseUri = this.BaseUri;
377 div.LinePosition = this.LinePosition;
378 div.LineNumber = this.LineNumber;
380 foreach (RelaxngStart start in appliedStarts)
381 div.Starts.Add (start);
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);
390 foreach (RelaxngDefine def in g.Defines) {
391 originalDefs [def.Name] = def.Name;
392 if (!overrides.ContainsKey (def.Name)) {
393 div.Defines.Add (def);
395 // else discard.
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.");
402 grammar.IncludedUris.Remove (Href);
403 return div;
407 public class RelaxngDiv : RelaxngElementBase, IGrammarContent
409 RelaxngGrammarContentList starts = new RelaxngGrammarContentList ();
410 RelaxngGrammarContentList defines = new RelaxngGrammarContentList ();
411 RelaxngGrammarContentList includes = new RelaxngGrammarContentList ();
412 RelaxngGrammarContentList divs = new RelaxngGrammarContentList ();
414 public RelaxngDiv ()
418 public RelaxngGrammarContentList Starts {
419 get { return starts; }
422 public RelaxngGrammarContentList Defines {
423 get { return defines; }
426 public RelaxngGrammarContentList Includes {
427 get { return includes; }
430 public RelaxngGrammarContentList Divs {
431 get { return divs; }
434 public override void Write (XmlWriter writer)
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 ();
448 internal override void WriteRnc (RncWriter writer)
450 writer.WriteDiv (this);
453 internal void Compile (RelaxngGrammar grammar)
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);
465 #endregion
467 #region RelaxngPatterns
468 public abstract class RelaxngPattern : RelaxngElementBase
470 // static
472 public static RelaxngPattern Read (XmlReader xmlReader)
474 return Read (xmlReader, null);
477 public static RelaxngPattern Read (XmlReader xmlReader, RelaxngDatatypeProvider provider)
479 return Read (xmlReader, provider, new XmlUrlResolver ());
482 public static RelaxngPattern Read (XmlReader xmlReader, RelaxngDatatypeProvider provider, XmlResolver xmlResolver)
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;
494 // Private Fields
495 RdpPattern startRelaxngPattern;
496 RelaxngDatatypeProvider provider;
497 XmlResolver resolver;
498 bool nullResolver;
500 // Public
501 public XmlResolver XmlResolver {
502 set {
503 nullResolver = value == null;
504 resolver = value;
508 public abstract RelaxngPatternType PatternType { get; }
509 public RelaxngDatatypeProvider DataProvider {
510 get {
511 return provider;
513 set {
514 provider = value;
518 public void Compile ()
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;
537 startRelaxngPattern = g.Compile (null);
538 this.IsCompiled = true;
541 public void WriteCompact (TextWriter writer)
543 WriteCompact (new RncWriter (writer));
546 public void WriteCompact (TextWriter writer, NSResolver res)
548 WriteCompact (new RncWriter (writer, res));
551 void WriteCompact (RncWriter writer)
553 RelaxngGrammar g = this as RelaxngGrammar;
554 string ns = (g != null ? g.DefaultNamespace : null);
555 writer.WriteNamespaces (ns);
556 WriteRnc (writer);
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;
570 internal abstract void CheckConstraints ();
572 protected RelaxngPattern ()
576 internal abstract RdpPattern Compile (RelaxngGrammar grammar);
578 internal RdpPattern StartPattern {
579 get { return startRelaxngPattern; }
583 public class RelaxngPatternList : CollectionBase
585 public RelaxngPatternList ()
589 public void Add (RelaxngPattern p)
591 List.Add (p);
594 public RelaxngPattern this [int i] {
595 get { return this.List [i] as RelaxngPattern; }
596 set { this.List [i] = value; }
599 public void Insert (int pos, RelaxngPattern p)
601 List.Insert (pos, p);
604 public void Remove (RelaxngPattern p)
606 List.Remove (p);
610 public class RelaxngGrammarContentList : CollectionBase
612 public RelaxngGrammarContentList ()
616 public void Add (IGrammarContent p)
618 List.Add (p);
621 public IGrammarContent this [int i] {
622 get { return this.List [i] as IGrammarContent; }
623 set { this.List [i] = value; }
626 public void Insert (int pos, IGrammarContent p)
628 List.Insert (pos, p);
631 public void Remove (IGrammarContent p)
633 List.Remove (p);
637 // strict to say, it's not a pattern ;)
638 public class RelaxngNotAllowed : RelaxngPattern
640 public RelaxngNotAllowed ()
644 public override RelaxngPatternType PatternType {
645 get { return RelaxngPatternType.NotAllowed; }
648 public override void Write (XmlWriter writer)
650 writer.WriteStartElement ("", "notAllowed", RelaxngGrammar.NamespaceURI);
651 writer.WriteEndElement ();
654 internal override void WriteRnc (RncWriter writer)
656 writer.WriteNotAllowed (this);
659 internal override RdpPattern Compile (RelaxngGrammar grammar)
661 return RdpNotAllowed.Instance;
664 internal override void CheckConstraints ()
666 // nothing to check
670 public class RelaxngEmpty : RelaxngPattern
672 public RelaxngEmpty ()
676 public override RelaxngPatternType PatternType {
677 get { return RelaxngPatternType.Empty; }
680 public override void Write (XmlWriter writer)
682 writer.WriteStartElement ("", "empty", RelaxngGrammar.NamespaceURI);
683 writer.WriteEndElement ();
686 internal override void WriteRnc (RncWriter writer)
688 writer.WriteEmpty (this);
691 internal override RdpPattern Compile (RelaxngGrammar grammar)
693 return RdpEmpty.Instance;
696 internal override void CheckConstraints ()
698 // nothing to check
702 public class RelaxngText : RelaxngPattern
704 public RelaxngText ()
708 public override RelaxngPatternType PatternType {
709 get { return RelaxngPatternType.Text; }
712 public override void Write (XmlWriter writer)
714 writer.WriteStartElement ("", "text", RelaxngGrammar.NamespaceURI);
715 writer.WriteEndElement ();
718 internal override void WriteRnc (RncWriter writer)
720 writer.WriteText (this);
723 internal override RdpPattern Compile (RelaxngGrammar grammar)
725 return RdpText.Instance;
728 internal override void CheckConstraints ()
730 // nothing to check
734 public abstract class RelaxngDataSupport : RelaxngPattern
736 string type;
737 string datatypeLibrary;
739 public string Type {
740 get { return type; }
741 set { type = value; }
744 public string DatatypeLibrary {
745 get { return datatypeLibrary; }
746 set { datatypeLibrary = value; }
749 internal void CheckDatatypeName ()
751 // Data type name check is done in RdpData(Except) derivative creation.
755 public class RelaxngData : RelaxngDataSupport
757 RelaxngParamList paramList = new RelaxngParamList ();
758 RelaxngExcept except;
760 public RelaxngData ()
764 public override RelaxngPatternType PatternType {
765 get { return RelaxngPatternType.Data; }
768 public RelaxngParamList ParamList {
769 get { return paramList; }
772 public RelaxngExcept Except {
773 get { return except; }
774 set { except = value; }
777 public override void Write (XmlWriter writer)
779 writer.WriteStartElement ("", "data", RelaxngGrammar.NamespaceURI);
780 if (DatatypeLibrary != null && DatatypeLibrary != String.Empty)
781 writer.WriteAttributeString ("datatypeLibrary", DatatypeLibrary);
782 writer.WriteAttributeString ("type", Type);
784 foreach (RelaxngParam p in ParamList)
785 p.Write (writer);
787 if (Except != null)
788 Except.Write (writer);
790 writer.WriteEndElement ();
793 internal override void WriteRnc (RncWriter writer)
795 writer.WriteData (this);
798 internal override RdpPattern Compile (RelaxngGrammar grammar)
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));
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));
820 internal override void CheckConstraints ()
822 CheckDatatypeName ();
826 public class RelaxngValue : RelaxngDataSupport
828 string value;
830 public override RelaxngPatternType PatternType {
831 get { return RelaxngPatternType.Value; }
834 public string Value {
835 get { return value; }
836 set { this.value = value; }
839 public override void Write (XmlWriter writer)
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);
848 writer.WriteString (Value);
849 writer.WriteEndElement ();
852 internal override void WriteRnc (RncWriter writer)
854 writer.WriteValue (this);
857 internal override RdpPattern Compile (RelaxngGrammar grammar)
859 IsCompiled = true;
860 return new RdpValue (new RdpDatatype (DatatypeLibrary,
861 Type, null, grammar.Provider), value);
864 internal override void CheckConstraints ()
866 CheckDatatypeName ();
870 public class RelaxngList : RelaxngSingleContentPattern
872 internal RelaxngList ()
876 public override RelaxngPatternType PatternType {
877 get { return RelaxngPatternType.List; }
880 public override void Write (XmlWriter writer)
882 writer.WriteStartElement ("", "list", RelaxngGrammar.NamespaceURI);
883 foreach (RelaxngPattern p in Patterns)
884 p.Write (writer);
885 writer.WriteEndElement ();
888 internal override void WriteRnc (RncWriter writer)
890 writer.WriteList (this);
893 internal override RdpPattern Compile (RelaxngGrammar grammar)
896 IsCompiled = true;
897 return new RdpList (makeSingle (grammar));
900 internal override void CheckConstraints ()
902 // nothing to check
906 public class RelaxngElement : RelaxngSingleContentPattern
908 RelaxngNameClass nc;
910 public RelaxngElement ()
914 public RelaxngNameClass NameClass {
915 get { return nc; }
916 set { nc = value; }
919 public override RelaxngPatternType PatternType {
920 get { return RelaxngPatternType.Element; }
923 public override void Write (XmlWriter writer)
925 writer.WriteStartElement ("", "element", RelaxngGrammar.NamespaceURI);
926 nc.Write (writer);
927 foreach (RelaxngPattern p in Patterns)
928 p.Write (writer);
929 writer.WriteEndElement ();
932 internal override void WriteRnc (RncWriter writer)
934 writer.WriteElement (this);
937 internal override RdpPattern Compile (RelaxngGrammar grammar)
939 return new RdpElement (
940 nc.Compile (grammar), this.makeSingle (grammar));
943 internal override void CheckConstraints ()
945 NameClass.CheckConstraints (false, false);
947 foreach (RelaxngPattern p in Patterns)
948 p.CheckConstraints ();
952 public class RelaxngAttribute : RelaxngPattern
954 RelaxngNameClass nc;
955 RelaxngPattern p;
957 public RelaxngAttribute ()
961 public RelaxngPattern Pattern {
962 get { return p; }
963 set { p = value; }
966 public RelaxngNameClass NameClass {
967 get { return nc; }
968 set { nc = value; }
971 public override RelaxngPatternType PatternType {
972 get { return RelaxngPatternType.Attribute; }
975 public override void Write (XmlWriter writer)
977 writer.WriteStartElement ("", "attribute", RelaxngGrammar.NamespaceURI);
978 nc.Write (writer);
979 if (p != null)
980 p.Write (writer);
981 writer.WriteEndElement ();
984 internal override void WriteRnc (RncWriter writer)
986 writer.WriteAttribute (this);
989 private void checkInvalidAttrNameClass (RdpNameClass nc)
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;
998 RdpAnyNameExcept except = nc as RdpAnyNameExcept;
999 if (except != null) {
1000 checkInvalidAttrNameClass (except.ExceptNameClass);
1001 return;
1003 if (nc is RdpAnyName)
1004 return;
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);
1022 internal override RdpPattern Compile (RelaxngGrammar grammar)
1024 IsCompiled = true;
1025 RdpNameClass cnc = nc.Compile (grammar);
1026 this.checkInvalidAttrNameClass (cnc);
1028 return new RdpAttribute (cnc,
1029 (p != null) ?
1030 p.Compile (grammar) :
1031 RdpText.Instance);
1034 internal override void CheckConstraints ()
1036 NameClass.CheckConstraints (false, false);
1038 if (p != null)
1039 p.CheckConstraints ();
1043 internal class RdpUnresolvedRef : RdpPattern
1045 string name;
1046 // bool parentRef;
1047 RelaxngGrammar targetGrammar;
1048 RdpPattern referencedPattern;
1050 public RdpUnresolvedRef (string name, RelaxngGrammar g)
1052 this.name = name;
1053 // this.parentRef = parentRef;
1054 targetGrammar = g;
1057 public string Name {
1058 get { return name; }
1059 set { name = value; }
1062 public RdpPattern RefPattern {
1063 get { return referencedPattern; }
1064 set { referencedPattern = value; }
1067 // public bool IsParentRef {
1068 // get { return parentRef; }
1069 // }
1071 public RelaxngGrammar TargetGrammar {
1072 get { return targetGrammar; }
1075 public override RelaxngPatternType PatternType {
1076 get { return RelaxngPatternType.Ref; }
1079 public override RdpContentType ContentType {
1080 get { return RdpContentType.Empty; }
1084 public override bool Nullable {
1085 get {
1086 throw new InvalidOperationException ("Internal error: should not reach.");
1090 public override void GetLabels (Hashtable elements, Hashtable attributes, bool collectNameClass)
1092 // Now it could reach (CheckNameOverlap) so comment out here.
1093 // throw new InvalidOperationException ("Internal error: should not reach.");
1096 internal override RdpPattern ExpandRef (Hashtable defs)
1098 return referencedPattern.ExpandRef (defs);
1101 internal override void MarkReachableDefs ()
1103 TargetGrammar.MarkReacheableDefine (this.name);
1106 internal override RdpPattern ReduceEmptyAndNotAllowed (ref bool result, Hashtable visited)
1108 referencedPattern =
1109 referencedPattern.ReduceEmptyAndNotAllowed (
1110 ref result, visited);
1111 return this;
1114 internal override void CheckConstraints (bool attribute, bool oneOrMore, bool oneOrMoreGroup, bool oneOrMoreInterleave, bool list, bool dataExcept)
1116 // throw new InvalidOperationException ();
1119 internal override bool ContainsText ()
1121 return false;
1122 // throw new InvalidOperationException ();
1126 public class RelaxngRef : RelaxngPattern
1128 string name;
1130 public RelaxngRef ()
1134 public string Name {
1135 get { return name; }
1136 set { name = value; }
1139 public override RelaxngPatternType PatternType {
1140 get { return RelaxngPatternType.Ref; }
1143 public override void Write (XmlWriter writer)
1145 writer.WriteStartElement ("", "ref", RelaxngGrammar.NamespaceURI);
1146 writer.WriteAttributeString ("name", name);
1147 writer.WriteEndElement ();
1150 internal override void WriteRnc (RncWriter writer)
1152 writer.WriteRef (this);
1155 internal override RdpPattern Compile (RelaxngGrammar grammar)
1157 // Important!! This compile method only generates stub.
1158 IsCompiled = false;
1159 return new RdpUnresolvedRef (name, grammar);
1162 internal override void CheckConstraints ()
1164 // nothing to check
1168 public class RelaxngParentRef : RelaxngPattern
1170 string name;
1172 public RelaxngParentRef ()
1176 public string Name {
1177 get { return name; }
1178 set { name = value; }
1181 public override RelaxngPatternType PatternType {
1182 get { return RelaxngPatternType.ParentRef; }
1185 public override void Write (XmlWriter writer)
1187 writer.WriteStartElement ("", "parentRef", RelaxngGrammar.NamespaceURI);
1188 writer.WriteAttributeString ("name", name);
1189 writer.WriteEndElement ();
1192 internal override void WriteRnc (RncWriter writer)
1194 writer.WriteParentRef (this);
1197 internal override RdpPattern Compile (RelaxngGrammar grammar)
1199 IsCompiled = false;
1200 return new RdpUnresolvedRef (name, grammar.ParentGrammar);
1203 internal override void CheckConstraints ()
1205 // nothing to check
1209 public class RelaxngExternalRef : RelaxngPattern
1211 string href;
1212 string ns;
1214 public RelaxngExternalRef ()
1218 public string Href {
1219 get { return href; }
1220 set { href = value; }
1223 public string NSContext {
1224 get { return ns; }
1225 set { ns = value; }
1228 public override RelaxngPatternType PatternType {
1229 get { return RelaxngPatternType.ExternalRef; }
1232 public override void Write (XmlWriter writer)
1234 writer.WriteStartElement ("", "externalRef", RelaxngGrammar.NamespaceURI);
1235 writer.WriteAttributeString ("href", Href);
1236 writer.WriteEndElement ();
1239 internal override void WriteRnc (RncWriter writer)
1241 writer.WriteExternalRef (this);
1244 internal override RdpPattern Compile (RelaxngGrammar grammar)
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);
1253 p.DataProvider = grammar.Provider;
1254 RdpPattern ret = p.Compile (grammar);
1256 grammar.IncludedUris.Remove (Href);
1258 return ret;
1262 internal override void CheckConstraints ()
1264 // nothing to check
1268 public class RelaxngOneOrMore : RelaxngSingleContentPattern
1270 public RelaxngOneOrMore ()
1274 public override RelaxngPatternType PatternType {
1275 get { return RelaxngPatternType.OneOrMore; }
1278 public override void Write (XmlWriter writer)
1280 writer.WriteStartElement ("", "oneOrMore", RelaxngGrammar.NamespaceURI);
1281 foreach (RelaxngPattern p in Patterns)
1282 p.Write (writer);
1283 writer.WriteEndElement ();
1286 internal override void WriteRnc (RncWriter writer)
1288 writer.WriteOneOrMore (this);
1291 internal override RdpPattern Compile (RelaxngGrammar grammar)
1293 IsCompiled = true;
1294 return new RdpOneOrMore (makeSingle (grammar));
1298 public class RelaxngZeroOrMore : RelaxngSingleContentPattern
1300 public RelaxngZeroOrMore ()
1304 public override RelaxngPatternType PatternType {
1305 get { return RelaxngPatternType.ZeroOrMore; }
1308 public override void Write (XmlWriter writer)
1310 writer.WriteStartElement ("", "zeroOrMore", RelaxngGrammar.NamespaceURI);
1311 foreach (RelaxngPattern p in Patterns)
1312 p.Write (writer);
1313 writer.WriteEndElement ();
1316 internal override void WriteRnc (RncWriter writer)
1318 writer.WriteZeroOrMore (this);
1321 internal override RdpPattern Compile (RelaxngGrammar grammar)
1323 IsCompiled = true;
1324 return new RdpChoice (
1325 new RdpOneOrMore (makeSingle (grammar)),
1326 RdpEmpty.Instance);
1330 public class RelaxngOptional : RelaxngSingleContentPattern
1332 public RelaxngOptional ()
1336 public override RelaxngPatternType PatternType {
1337 get { return RelaxngPatternType.Optional; }
1340 public override void Write (XmlWriter writer)
1342 writer.WriteStartElement ("", "optional", RelaxngGrammar.NamespaceURI);
1343 foreach (RelaxngPattern p in Patterns)
1344 p.Write (writer);
1345 writer.WriteEndElement ();
1348 internal override void WriteRnc (RncWriter writer)
1350 writer.WriteOptional (this);
1353 internal override RdpPattern Compile (RelaxngGrammar grammar)
1355 IsCompiled = true;
1356 return new RdpChoice (
1357 makeSingle (grammar), RdpEmpty.Instance);
1361 public class RelaxngMixed : RelaxngSingleContentPattern
1363 public RelaxngMixed ()
1367 public override RelaxngPatternType PatternType {
1368 get { return RelaxngPatternType.Mixed; }
1371 public override void Write (XmlWriter writer)
1373 writer.WriteStartElement ("", "mixed", RelaxngGrammar.NamespaceURI);
1374 foreach (RelaxngPattern p in Patterns)
1375 p.Write (writer);
1376 writer.WriteEndElement ();
1379 internal override void WriteRnc (RncWriter writer)
1381 writer.WriteMixed (this);
1384 internal override RdpPattern Compile (RelaxngGrammar grammar)
1386 IsCompiled = true;
1387 return new RdpInterleave (makeSingle (grammar), RdpText.Instance);
1391 public class RelaxngChoice : RelaxngBinaryContentPattern
1393 public RelaxngChoice ()
1397 public override RelaxngPatternType PatternType {
1398 get { return RelaxngPatternType.Choice; }
1401 public override void Write (XmlWriter writer)
1403 writer.WriteStartElement ("", "choice", RelaxngGrammar.NamespaceURI);
1404 foreach (RelaxngPattern p in Patterns)
1405 p.Write (writer);
1406 writer.WriteEndElement ();
1409 internal override void WriteRnc (RncWriter writer)
1411 writer.WriteChoice (this);
1414 internal override RdpPattern Compile (RelaxngGrammar grammar)
1416 IsCompiled = true;
1417 return makeBinary (grammar);
1421 public class RelaxngGroup : RelaxngBinaryContentPattern
1423 public RelaxngGroup ()
1427 public override RelaxngPatternType PatternType {
1428 get { return RelaxngPatternType.Group; }
1431 public override void Write (XmlWriter writer)
1433 writer.WriteStartElement ("", "group", RelaxngGrammar.NamespaceURI);
1434 foreach (RelaxngPattern p in Patterns)
1435 p.Write (writer);
1436 writer.WriteEndElement ();
1439 internal override void WriteRnc (RncWriter writer)
1441 writer.WriteGroup (this);
1444 internal override RdpPattern Compile (RelaxngGrammar grammar)
1446 IsCompiled = true;
1447 return makeBinary (grammar);
1451 public class RelaxngInterleave : RelaxngBinaryContentPattern
1453 public RelaxngInterleave ()
1457 public override RelaxngPatternType PatternType {
1458 get { return RelaxngPatternType.Interleave; }
1461 public override void Write (XmlWriter writer)
1463 writer.WriteStartElement ("", "interleave", RelaxngGrammar.NamespaceURI);
1464 foreach (RelaxngPattern p in Patterns)
1465 p.Write (writer);
1466 writer.WriteEndElement ();
1469 internal override void WriteRnc (RncWriter writer)
1471 writer.WriteInterleave (this);
1474 internal override RdpPattern Compile (RelaxngGrammar grammar)
1476 IsCompiled = true;
1477 return makeBinary (grammar);
1481 public class RelaxngParam : RelaxngElementBase
1483 string name;
1484 string value;
1486 public RelaxngParam ()
1490 public RelaxngParam (string name, string value)
1492 this.name = name;
1493 this.value = value;
1496 public string Name {
1497 get { return name; }
1498 set { name = value; }
1501 public string Value {
1502 get { return value; }
1503 set { this.value = value; }
1506 public override void Write (XmlWriter writer)
1508 writer.WriteStartElement ("", "param", RelaxngGrammar.NamespaceURI);
1509 writer.WriteAttributeString ("name", name);
1510 writer.WriteString (Value);
1511 writer.WriteEndElement ();
1514 internal override void WriteRnc (RncWriter writer)
1516 writer.WriteParam (this);
1519 internal RdpParam Compile (RelaxngGrammar grammar)
1521 IsCompiled = true;
1522 return new RdpParam (name, value);
1526 public class RelaxngParamList : CollectionBase
1528 public RelaxngParamList ()
1532 public void Add (RelaxngParam p)
1534 List.Add (p);
1537 public RelaxngParam this [int i] {
1538 get { return this.List [i] as RelaxngParam; }
1539 set { this.List [i] = value; }
1542 public void Insert (int pos, RelaxngParam p)
1544 List.Insert (pos, p);
1547 public void Remove (RelaxngParam p)
1549 List.Remove (p);
1553 public class RelaxngExcept : RelaxngElementBase
1555 RelaxngPatternList patterns = new RelaxngPatternList ();
1557 public RelaxngExcept ()
1561 public RelaxngPatternList Patterns {
1562 get { return patterns; }
1565 public override void Write (XmlWriter writer)
1567 writer.WriteStartElement ("", "except", RelaxngGrammar.NamespaceURI);
1568 foreach (RelaxngPattern p in Patterns)
1569 p.Write (writer);
1570 writer.WriteEndElement ();
1573 internal override void WriteRnc (RncWriter writer)
1575 writer.WriteDataExcept (this);
1579 internal class RelaxngRefPattern
1581 RelaxngPattern patternRef;
1582 string name;
1584 // When we found ref, use it.
1585 public RelaxngRefPattern (string name)
1587 this.name = name;
1590 // When we found define, use it.
1591 public RelaxngRefPattern (RelaxngPattern patternRef)
1593 this.patternRef = patternRef;
1596 public string Name {
1597 get { return name; }
1600 public RelaxngPattern PatternRef {
1601 get { return patternRef; }
1602 set { patternRef = value; }
1605 #endregion