2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / Commons.Xml.Relaxng / Commons.Xml.Relaxng / RelaxngPattern.cs
index 35561b53efba1cbd8eede659592d5120309660b0..99f5892a50d37e5a61ea467030c17a71009cc1cf 100644 (file)
@@ -6,12 +6,43 @@
 //\r
 // 2003 Atsushi Enomoto "No rights reserved."\r
 //\r
+// Copyright (c) 2004 Novell Inc.\r
+// All rights reserved\r
+//\r
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
 \r
 using System;\r
 using System.Collections;\r
 using System.IO;\r
 using System.Xml;\r
 using Commons.Xml.Relaxng.Derivative;\r
+using Commons.Xml.Relaxng.Rnc;\r
+\r
+#if NET_2_0\r
+using NSResolver = System.Xml.IXmlNamespaceResolver;\r
+#else\r
+using NSResolver = System.Xml.XmlNamespaceManager;\r
+#endif\r
 \r
 namespace Commons.Xml.Relaxng\r
 {\r
@@ -41,6 +72,10 @@ namespace Commons.Xml.Relaxng
                        get { return baseUri; }\r
                        set { baseUri = value; }\r
                }\r
+\r
+               public abstract void Write (XmlWriter writer);\r
+\r
+               internal abstract void WriteRnc (RncWriter writer);\r
        }\r
 \r
        public abstract class RelaxngSingleContentPattern : RelaxngPattern\r
@@ -55,7 +90,7 @@ namespace Commons.Xml.Relaxng
                {\r
                        // Flatten patterns into RdpGroup. See 4.12.\r
                        if (patterns.Count == 0)\r
-                               throw new RelaxngException ("No pattern contents.");\r
+                               throw new RelaxngException (this, "No pattern contents.");\r
                        RdpPattern p = ((RelaxngPattern) patterns [0]).Compile (g);\r
                        if (patterns.Count == 1)\r
                                return p;\r
@@ -85,7 +120,7 @@ namespace Commons.Xml.Relaxng
                {\r
                        // Flatten patterns. See 4.12.\r
                        if (patterns.Count == 0)\r
-                               throw new RelaxngException ("No pattern contents.");\r
+                               throw new RelaxngException (this, "No pattern contents.");\r
 \r
                        RdpPattern p = ((RelaxngPattern) patterns [0]).Compile (g);\r
                        if (patterns.Count == 1)\r
@@ -119,7 +154,11 @@ namespace Commons.Xml.Relaxng
        #endregion\r
 \r
        #region Grammatical elements\r
-       public class RelaxngStart : RelaxngElementBase\r
+       public interface IGrammarContent\r
+       {\r
+       }\r
+\r
+       public class RelaxngStart : RelaxngElementBase, IGrammarContent\r
        {\r
                RelaxngPattern p;\r
                string combine;\r
@@ -138,18 +177,36 @@ namespace Commons.Xml.Relaxng
                        set { p = value; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "start", RelaxngGrammar.NamespaceURI);\r
+                       if (combine != null)\r
+                               writer.WriteAttributeString ("combine", combine);\r
+                       p.Write (writer);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteStart (this);\r
+               }\r
+\r
                internal RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        return p.Compile (grammar);\r
                }\r
        }\r
 \r
-       public class RelaxngDefine : RelaxngElementBase\r
+       public class RelaxngDefine : RelaxngElementBase, IGrammarContent\r
        {\r
                string name;\r
                private RelaxngPatternList patterns = new RelaxngPatternList ();\r
                string combine;\r
 \r
+               public RelaxngDefine ()\r
+               {\r
+               }\r
+\r
                public RelaxngPatternList Patterns {\r
                        get { return patterns; }\r
                }\r
@@ -159,11 +216,37 @@ namespace Commons.Xml.Relaxng
                        set { combine = value; }\r
                }\r
 \r
+               public string Name {\r
+                       get { return name; }\r
+                       set { name = value; }\r
+               }\r
+\r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "define", RelaxngGrammar.NamespaceURI);\r
+                       writer.WriteAttributeString ("name", name);\r
+                       if (combine != null)\r
+                               writer.WriteAttributeString ("combine", combine);\r
+                       foreach (RelaxngPattern p in Patterns)\r
+                               p.Write (writer);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteDefine (this);\r
+               }\r
+\r
+               internal RdpPattern Compile (RelaxngGrammar grammar)\r
+               {\r
+                       return makeSingle (grammar);\r
+               }\r
+\r
                private RdpPattern makeSingle (RelaxngGrammar g)\r
                {\r
                        // Flatten patterns into RdpGroup. See 4.12.\r
                        if (patterns.Count == 0)\r
-                               throw new RelaxngException ("No pattern contents.");\r
+                               throw new RelaxngException (this, "No pattern contents.");\r
                        RdpPattern p = ((RelaxngPattern) patterns [0]).Compile (g);\r
                        if (patterns.Count == 1)\r
                                return p;\r
@@ -173,28 +256,14 @@ namespace Commons.Xml.Relaxng
                        }\r
                        return p;\r
                }\r
-\r
-               public RelaxngDefine ()\r
-               {\r
-               }\r
-\r
-               public string Name {\r
-                       get { return name; }\r
-                       set { name = value; }\r
-               }\r
-\r
-               internal RdpPattern Compile (RelaxngGrammar grammar)\r
-               {\r
-                       return makeSingle (grammar);\r
-               }\r
        }\r
 \r
-       public class RelaxngInclude : RelaxngElementBase\r
+       public class RelaxngInclude : RelaxngElementBase, IGrammarContent\r
        {\r
                string href;\r
-               IList starts = new ArrayList ();\r
-               IList defines = new ArrayList ();\r
-               IList divs = new ArrayList ();\r
+               RelaxngGrammarContentList starts = new RelaxngGrammarContentList ();\r
+               RelaxngGrammarContentList defines = new RelaxngGrammarContentList ();\r
+               RelaxngGrammarContentList divs = new RelaxngGrammarContentList ();\r
                string ns;\r
 \r
                public RelaxngInclude ()\r
@@ -206,15 +275,15 @@ namespace Commons.Xml.Relaxng
                        set { href = value; }\r
                }\r
 \r
-               public IList Starts {\r
+               public RelaxngGrammarContentList Starts {\r
                        get { return starts; }\r
                }\r
 \r
-               public IList Defines {\r
+               public RelaxngGrammarContentList Defines {\r
                        get { return defines; }\r
                }\r
 \r
-               public IList Divs {\r
+               public RelaxngGrammarContentList Divs {\r
                        get { return divs; }\r
                }\r
 \r
@@ -223,15 +292,36 @@ namespace Commons.Xml.Relaxng
                        set { ns = value; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "include", RelaxngGrammar.NamespaceURI);\r
+                       writer.WriteAttributeString ("href", href);\r
+                       foreach (RelaxngStart start in Starts)\r
+                               start.Write (writer);\r
+                       foreach (RelaxngDefine define in Defines)\r
+                               define.Write (writer);\r
+                       foreach (RelaxngDiv div in Divs)\r
+                               div.Write (writer);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteInclude (this);\r
+               }\r
+\r
                // compile into div\r
                internal RelaxngDiv Compile (RelaxngGrammar grammar)\r
                {\r
                        grammar.CheckIncludeRecursion (Href);\r
                        grammar.IncludedUris.Add (Href, Href);\r
-                       string url = Util.ResolveUri (BaseUri, href);\r
-                       XmlTextReader xtr = new XmlTextReader (url);\r
+                       if (grammar.Resolver == null)\r
+                               throw new RelaxngException (this, "To compile 'include' element, XmlResolver is required.");\r
+                       Uri uri = grammar.Resolver.ResolveUri (BaseUri != String.Empty ? new Uri (BaseUri) : null, Href);\r
+                       XmlTextReader xtr = null;\r
                        RelaxngGrammar g = null;\r
                        try {\r
+                               xtr = new XmlTextReader (uri.AbsoluteUri, (Stream) grammar.Resolver.GetEntity (uri, null, typeof (Stream)));\r
                                RelaxngReader r = new RelaxngReader (xtr, ns);\r
                                r.MoveToContent ();\r
                                g = r.ReadPattern () as RelaxngGrammar;\r
@@ -239,7 +329,7 @@ namespace Commons.Xml.Relaxng
                                xtr.Close ();\r
                        }\r
                        if (g == null)\r
-                               throw new RelaxngException ("Included syntax must start with \"grammar\" element.");\r
+                               throw new RelaxngException (this, "Included syntax must start with \"grammar\" element.");\r
                        g.DataProvider = grammar.Provider;\r
 \r
                        // process recursive inclusions.\r
@@ -256,8 +346,8 @@ namespace Commons.Xml.Relaxng
                        // replace redifinitions into div.\r
                        // starts.\r
                        if (this.Starts.Count > 0 && g.Starts.Count == 0)\r
-                               throw new RelaxngException ("When the included grammar does not contain start components, this include component must not contain start components.");\r
-                       IList appliedStarts = (this.starts.Count > 0) ?\r
+                               throw new RelaxngException (this, "When the included grammar does not contain start components, this include component must not contain start components.");\r
+                       RelaxngGrammarContentList appliedStarts = (this.starts.Count > 0) ?\r
                                this.starts : g.Starts;\r
 \r
                        RelaxngDiv div = new RelaxngDiv ();\r
@@ -276,47 +366,68 @@ namespace Commons.Xml.Relaxng
                                div.Defines.Add (def);\r
                        }\r
                        foreach (RelaxngDefine def in g.Defines) {\r
-                               originalDefs.Add (def.Name, def.Name);\r
-                               if (overrides [def.Name] == null)\r
+                               originalDefs [def.Name] = def.Name;\r
+                               if (!overrides.ContainsKey (def.Name)) {\r
                                        div.Defines.Add (def);\r
+                               }\r
                                // else discard.\r
                        }\r
+\r
                        foreach (string name in overrides.Values)\r
-                               if (!originalDefs.Contains (name))\r
-                                       throw new RelaxngException ("The include component must not contain define components whose name does not appear in the included grammar component.");\r
+                               if (!originalDefs.ContainsKey (name))\r
+                                       throw new RelaxngException (this, "The include component must not contain define components whose name does not appear in the included grammar component.");\r
 \r
                        grammar.IncludedUris.Remove (Href);\r
                        return div;\r
                }\r
        }\r
 \r
-       public class RelaxngDiv : RelaxngElementBase\r
+       public class RelaxngDiv : RelaxngElementBase, IGrammarContent\r
        {\r
-               IList starts = new ArrayList ();\r
-               IList defines = new ArrayList ();\r
-               IList includes = new ArrayList ();\r
-               IList divs = new ArrayList ();\r
+               RelaxngGrammarContentList starts = new RelaxngGrammarContentList ();\r
+               RelaxngGrammarContentList defines = new RelaxngGrammarContentList ();\r
+               RelaxngGrammarContentList includes = new RelaxngGrammarContentList ();\r
+               RelaxngGrammarContentList divs = new RelaxngGrammarContentList ();\r
 \r
                public RelaxngDiv ()\r
                {\r
                }\r
 \r
-               public IList Starts {\r
+               public RelaxngGrammarContentList Starts {\r
                        get { return starts; }\r
                }\r
 \r
-               public IList Defines {\r
+               public RelaxngGrammarContentList Defines {\r
                        get { return defines; }\r
                }\r
 \r
-               public IList Includes {\r
+               public RelaxngGrammarContentList Includes {\r
                        get { return includes; }\r
                }\r
 \r
-               public IList Divs {\r
+               public RelaxngGrammarContentList Divs {\r
                        get { return divs; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "div", RelaxngGrammar.NamespaceURI);\r
+                       foreach (RelaxngStart start in Starts)\r
+                               start.Write (writer);\r
+                       foreach (RelaxngDefine define in Defines)\r
+                               define.Write (writer);\r
+                       foreach (RelaxngInclude include in Includes)\r
+                               include.Write (writer);\r
+                       foreach (RelaxngDiv div in Divs)\r
+                               div.Write (writer);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteDiv (this);\r
+               }\r
+\r
                internal void Compile (RelaxngGrammar grammar)\r
                {\r
                        foreach (RelaxngDiv div in divs)\r
@@ -355,8 +466,17 @@ namespace Commons.Xml.Relaxng
                // Private Fields\r
                RdpPattern startRelaxngPattern;\r
                RelaxngDatatypeProvider provider;\r
+               XmlResolver resolver;\r
+               bool nullResolver;\r
 \r
                // Public\r
+               public XmlResolver XmlResolver {\r
+                       set {\r
+                               nullResolver = value == null;\r
+                               resolver = value;\r
+                       }\r
+               }\r
+\r
                public abstract RelaxngPatternType PatternType { get; }\r
                public RelaxngDatatypeProvider DataProvider {\r
                        get {\r
@@ -374,6 +494,7 @@ namespace Commons.Xml.Relaxng
                                g = (RelaxngGrammar) this;\r
                        else {\r
                                g = new RelaxngGrammar ();\r
+                               g.XmlResolver = this.Resolver;\r
                                g.BaseUri = this.BaseUri;\r
                                g.LineNumber = this.LineNumber;\r
                                g.LinePosition = this.LinePosition;\r
@@ -389,8 +510,27 @@ namespace Commons.Xml.Relaxng
                        this.IsCompiled = true;\r
                }\r
 \r
+               public void WriteCompact (TextWriter writer)\r
+               {\r
+                       WriteRnc (new RncWriter (writer));\r
+               }\r
+\r
+               public void WriteCompact (TextWriter writer, NSResolver res)\r
+               {\r
+                       WriteRnc (new RncWriter (writer, res));\r
+               }\r
 \r
                // Internal\r
+               internal XmlResolver Resolver {\r
+                       get {\r
+                               if (nullResolver)\r
+                                       return null;\r
+                               if (resolver == null)\r
+                                       resolver = new XmlUrlResolver ();\r
+                               return resolver;\r
+                       }\r
+               }\r
+\r
                internal abstract void CheckConstraints ();\r
 \r
                protected RelaxngPattern () \r
@@ -420,12 +560,44 @@ namespace Commons.Xml.Relaxng
                        set { this.List [i] = value; }\r
                }\r
 \r
+               public void Insert (int pos, RelaxngPattern p)\r
+               {\r
+                       List.Insert (pos, p);\r
+               }\r
+\r
                public void Remove (RelaxngPattern p)\r
                {\r
                        List.Remove (p);\r
                }\r
        }\r
 \r
+       public class RelaxngGrammarContentList : CollectionBase\r
+       {\r
+               public RelaxngGrammarContentList ()\r
+               {\r
+               }\r
+\r
+               public void Add (IGrammarContent p)\r
+               {\r
+                       List.Add (p);\r
+               }\r
+\r
+               public IGrammarContent this [int i] {\r
+                       get { return this.List [i] as IGrammarContent; }\r
+                       set { this.List [i] = value; }\r
+               }\r
+\r
+               public void Insert (int pos, IGrammarContent p)\r
+               {\r
+                       List.Insert (pos, p);\r
+               }\r
+\r
+               public void Remove (IGrammarContent p)\r
+               {\r
+                       List.Remove (p);\r
+               }\r
+       }\r
+\r
        // strict to say, it's not a pattern ;)\r
        public class RelaxngNotAllowed : RelaxngPattern\r
        {\r
@@ -437,6 +609,17 @@ namespace Commons.Xml.Relaxng
                        get { return RelaxngPatternType.NotAllowed; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "notAllowed", RelaxngGrammar.NamespaceURI);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteNotAllowed (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        return RdpNotAllowed.Instance;\r
@@ -458,6 +641,17 @@ namespace Commons.Xml.Relaxng
                        get { return RelaxngPatternType.Empty; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "empty", RelaxngGrammar.NamespaceURI);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteEmpty (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        return RdpEmpty.Instance;\r
@@ -479,6 +673,17 @@ namespace Commons.Xml.Relaxng
                        get { return RelaxngPatternType.Text; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "text", RelaxngGrammar.NamespaceURI);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteText (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        return RdpText.Instance;\r
@@ -524,6 +729,38 @@ namespace Commons.Xml.Relaxng
                        get { return RelaxngPatternType.Data; }\r
                }\r
 \r
+               public RelaxngParamList ParamList {\r
+                       get { return paramList; }\r
+               }\r
+\r
+               public RelaxngExcept Except {\r
+                       get { return except; }\r
+                       set { except = value; }\r
+               }\r
+\r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "data", RelaxngGrammar.NamespaceURI);\r
+                       if (DatatypeLibrary != null && DatatypeLibrary != String.Empty)\r
+                               writer.WriteAttributeString ("xmlns", "data", "http://www.w3.org/2000/xmlns/", DatatypeLibrary);\r
+                       writer.WriteStartAttribute ("type", String.Empty);\r
+                       writer.WriteQualifiedName (Type, DatatypeLibrary);\r
+                       writer.WriteEndAttribute ();\r
+\r
+                       foreach (RelaxngParam p in ParamList)\r
+                               p.Write (writer);\r
+\r
+                       if (Except != null)\r
+                               Except.Write (writer);\r
+\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteData (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
 //                     RdpParamList rdpl = new RdpParamList ();\r
@@ -532,7 +769,7 @@ namespace Commons.Xml.Relaxng
                        RdpPattern p = null;\r
                        if (this.except != null) {\r
                                if (except.Patterns.Count == 0)\r
-                                       throw new RelaxngException ("data except pattern have no children.");\r
+                                       throw new RelaxngException (this, "data except pattern have no children.");\r
                                p = except.Patterns [0].Compile (grammar);\r
                                for (int i=1; i<except.Patterns.Count; i++)\r
                                        p = new RdpChoice (p,\r
@@ -546,15 +783,6 @@ namespace Commons.Xml.Relaxng
                                return new RdpData (new RdpDatatype (DatatypeLibrary, Type, ParamList, grammar.Provider));\r
                }\r
 \r
-               public RelaxngParamList ParamList {\r
-                       get { return paramList; }\r
-               }\r
-\r
-               public RelaxngExcept Except {\r
-                       get { return except; }\r
-                       set { except = value; }\r
-               }\r
-\r
                internal override void CheckConstraints () \r
                {\r
                        CheckDatatypeName ();\r
@@ -569,6 +797,30 @@ namespace Commons.Xml.Relaxng
                        get { return RelaxngPatternType.Value; }\r
                }\r
 \r
+               public string Value {\r
+                       get { return value; }\r
+                       set { this.value = value; }\r
+               }\r
+\r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "value", RelaxngGrammar.NamespaceURI);\r
+                       if (Type != null) {\r
+                               writer.WriteStartAttribute ("type", String.Empty);\r
+                               if (DatatypeLibrary != null && DatatypeLibrary != String.Empty)\r
+                                       writer.WriteAttributeString ("xmlns", "data", "http://www.w3.org/2000/xmlns/", DatatypeLibrary);\r
+                               writer.WriteQualifiedName (Type, DatatypeLibrary);\r
+                               writer.WriteEndAttribute ();\r
+                       }\r
+                       writer.WriteString (Value);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteValue (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -576,11 +828,6 @@ namespace Commons.Xml.Relaxng
                                Type, null, grammar.Provider), value);\r
                }\r
 \r
-               public string Value {\r
-                       get { return value; }\r
-                       set { this.value = value; }\r
-               }\r
-\r
                internal override void CheckConstraints () \r
                {\r
                        CheckDatatypeName ();\r
@@ -589,8 +836,6 @@ namespace Commons.Xml.Relaxng
 \r
        public class RelaxngList : RelaxngSingleContentPattern\r
        {\r
-               IList patterns = new ArrayList ();\r
-\r
                internal RelaxngList ()\r
                {\r
                }\r
@@ -599,6 +844,19 @@ namespace Commons.Xml.Relaxng
                        get { return RelaxngPatternType.List; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "list", RelaxngGrammar.NamespaceURI);\r
+                       foreach (RelaxngPattern p in Patterns)\r
+                               p.Write (writer);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteList (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
 \r
@@ -615,7 +873,6 @@ namespace Commons.Xml.Relaxng
        public class RelaxngElement : RelaxngSingleContentPattern\r
        {\r
                RelaxngNameClass nc;\r
-               ArrayList patterns = new ArrayList ();\r
 \r
                public RelaxngElement ()\r
                {\r
@@ -630,6 +887,20 @@ namespace Commons.Xml.Relaxng
                        get { return RelaxngPatternType.Element; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "element", RelaxngGrammar.NamespaceURI);\r
+                       nc.Write (writer);\r
+                       foreach (RelaxngPattern p in Patterns)\r
+                               p.Write (writer);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteElement (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        return new RdpElement (\r
@@ -654,10 +925,34 @@ namespace Commons.Xml.Relaxng
                {\r
                }\r
 \r
+               public RelaxngPattern Pattern {\r
+                       get { return p; }\r
+                       set { p = value; }\r
+               }\r
+\r
+               public RelaxngNameClass NameClass {\r
+                       get { return nc; }\r
+                       set { nc = value; }\r
+               }\r
+\r
                public override RelaxngPatternType PatternType {\r
                        get { return RelaxngPatternType.Attribute; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "attribute", RelaxngGrammar.NamespaceURI);\r
+                       nc.Write (writer);\r
+                       if (p != null)\r
+                               p.Write (writer);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteAttribute (this);\r
+               }\r
+\r
                private void checkInvalidAttrNameClass (RdpNameClass nc)\r
                {\r
                        string xmlnsNS = "http://www.w3.org/2000/xmlns";\r
@@ -678,13 +973,13 @@ namespace Commons.Xml.Relaxng
                        RdpName n = nc as RdpName;\r
                        if (n != null) {\r
                                if (n.NamespaceURI == xmlnsNS)\r
-                                       throw new RelaxngException ("cannot specify \"" + xmlnsNS + "\" for name of attribute.");\r
+                                       throw new RelaxngException (this, "cannot specify \"" + xmlnsNS + "\" for name of attribute.");\r
                                if (n.LocalName == "xmlns" && n.NamespaceURI == "")\r
-                                       throw new RelaxngException ("cannot specify \"xmlns\" inside empty ns context.");\r
+                                       throw new RelaxngException (this, "cannot specify \"xmlns\" inside empty ns context.");\r
                        } else {\r
                                RdpNsName nn = nc as RdpNsName;\r
                                if (nn.NamespaceURI == "http://www.w3.org/2000/xmlns")\r
-                                       throw new RelaxngException ("cannot specify \"" + xmlnsNS + "\" for name of attribute.");\r
+                                       throw new RelaxngException (this, "cannot specify \"" + xmlnsNS + "\" for name of attribute.");\r
                                RdpNsNameExcept x = nc as RdpNsNameExcept;\r
                                if (x != null)\r
                                        checkInvalidAttrNameClass (x.ExceptNameClass);\r
@@ -703,16 +998,6 @@ namespace Commons.Xml.Relaxng
                                        RdpText.Instance);\r
                }\r
 \r
-               public RelaxngPattern Pattern {\r
-                       get { return p; }\r
-                       set { p = value; }\r
-               }\r
-\r
-               public RelaxngNameClass NameClass {\r
-                       get { return nc; }\r
-                       set { nc = value; }\r
-               }\r
-\r
                internal override void CheckConstraints () \r
                {\r
                        NameClass.CheckConstraints (false, false);\r
@@ -759,26 +1044,24 @@ namespace Commons.Xml.Relaxng
                }\r
 \r
                public override RdpContentType ContentType {\r
-#if REPLACE_IN_ADVANCE\r
-                       get { throw new InvalidOperationException (); }\r
-#else\r
                        get { return RdpContentType.Empty; }\r
-#endif\r
                }\r
 \r
 \r
                public override bool Nullable {\r
                        get {\r
-                               throw new InvalidOperationException ();\r
+                               throw new InvalidOperationException ("Internal error: should not reach.");\r
                        }\r
                }\r
 \r
+               public override void GetLabels (Hashtable elements, Hashtable attributes)\r
+               {\r
+                       throw new InvalidOperationException ("Internal error: should not reach.");\r
+               }\r
+\r
                internal override RdpPattern ExpandRef (Hashtable defs)\r
                {\r
-                       RdpPattern target = (RdpPattern) defs [this.name];\r
-                       if (target == null)\r
-                               throw new RelaxngException ("Target definition " + name + " not found.");\r
-                       return target.ExpandRef (defs);\r
+                       return referencedPattern.ExpandRef (defs);\r
                }\r
 \r
                internal override void MarkReachableDefs () \r
@@ -806,10 +1089,27 @@ namespace Commons.Xml.Relaxng
                {\r
                }\r
 \r
+               public string Name {\r
+                       get { return name; }\r
+                       set { name = value; }\r
+               }\r
+\r
                public override RelaxngPatternType PatternType {\r
                        get { return RelaxngPatternType.Ref; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "ref", RelaxngGrammar.NamespaceURI);\r
+                       writer.WriteAttributeString ("name", name);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteRef (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        // Important!! This compile method only generates stub.\r
@@ -817,11 +1117,6 @@ namespace Commons.Xml.Relaxng
                        return new RdpUnresolvedRef (name, grammar);\r
                }\r
 \r
-               public string Name {\r
-                       get { return name; }\r
-                       set { name = value; }\r
-               }\r
-\r
                internal override void CheckConstraints () \r
                {\r
                        // nothing to check\r
@@ -836,21 +1131,33 @@ namespace Commons.Xml.Relaxng
                {\r
                }\r
 \r
+               public string Name {\r
+                       get { return name; }\r
+                       set { name = value; }\r
+               }\r
+\r
                public override RelaxngPatternType PatternType {\r
                        get { return RelaxngPatternType.ParentRef; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "parentRef", RelaxngGrammar.NamespaceURI);\r
+                       writer.WriteAttributeString ("name", name);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteParentRef (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = false;\r
                        return new RdpUnresolvedRef (name, grammar.ParentGrammar);\r
                }\r
 \r
-               public string Name {\r
-                       get { return name; }\r
-                       set { name = value; }\r
-               }\r
-\r
                internal override void CheckConstraints () \r
                {\r
                        // nothing to check\r
@@ -866,35 +1173,57 @@ namespace Commons.Xml.Relaxng
                {\r
                }\r
 \r
+               public string Href {\r
+                       get { return href; }\r
+                       set { href = value; }\r
+               }\r
+\r
+               public string NSContext {\r
+                       get { return ns; }\r
+                       set { ns = value; }\r
+               }\r
+\r
                public override RelaxngPatternType PatternType {\r
                        get { return RelaxngPatternType.ExternalRef; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "externalRef", RelaxngGrammar.NamespaceURI);\r
+                       writer.WriteAttributeString ("href", Href);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteExternalRef (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        grammar.CheckIncludeRecursion (Href);\r
                        grammar.IncludedUris.Add (Href, Href);\r
-                       string uri = Util.ResolveUri (this.BaseUri, href);\r
-                       RelaxngReader r = new RelaxngReader (new XmlTextReader (uri), ns);\r
-                       r.MoveToContent ();\r
-                       RelaxngPattern p = r.ReadPattern ();\r
-                       p.DataProvider = grammar.Provider;\r
-\r
-                       RdpPattern ret = p.Compile (grammar);\r
+                       if (grammar.Resolver == null)\r
+                               throw new RelaxngException (this, "To compile 'include' element, XmlResolver is required.");\r
+                       Uri uri = grammar.Resolver.ResolveUri (BaseUri != String.Empty ? new Uri (BaseUri) : null, Href);\r
+                       XmlTextReader xtr = null;\r
+                       try {\r
+                               xtr = new XmlTextReader (uri.AbsoluteUri, (Stream) grammar.Resolver.GetEntity (uri, null, typeof (Stream)));\r
+                               RelaxngReader r = new RelaxngReader (xtr, ns);\r
+                               r.MoveToContent ();\r
+                               RelaxngPattern p = r.ReadPattern ();\r
+                               p.DataProvider = grammar.Provider;\r
 \r
-                       grammar.IncludedUris.Remove (Href);\r
+                               RdpPattern ret = p.Compile (grammar);\r
 \r
-                       return ret;\r
-               }\r
+                               grammar.IncludedUris.Remove (Href);\r
 \r
-               public string Href {\r
-                       get { return href; }\r
-                       set { href = value; }\r
-               }\r
+                               return ret;\r
+                       } finally {\r
+                               if (xtr != null)\r
+                                       xtr.Close ();\r
+                       }\r
 \r
-               public string NSContext {\r
-                       get { return ns; }\r
-                       set { ns = value; }\r
                }\r
 \r
                internal override void CheckConstraints () \r
@@ -913,6 +1242,19 @@ namespace Commons.Xml.Relaxng
                        get { return RelaxngPatternType.OneOrMore; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "oneOrMore", RelaxngGrammar.NamespaceURI);\r
+                       foreach (RelaxngPattern p in Patterns)\r
+                               p.Write (writer);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteOneOrMore (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -930,6 +1272,19 @@ namespace Commons.Xml.Relaxng
                        get { return RelaxngPatternType.ZeroOrMore; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "zeroOrMore", RelaxngGrammar.NamespaceURI);\r
+                       foreach (RelaxngPattern p in Patterns)\r
+                               p.Write (writer);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteZeroOrMore (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -949,6 +1304,19 @@ namespace Commons.Xml.Relaxng
                        get { return RelaxngPatternType.Optional; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "optional", RelaxngGrammar.NamespaceURI);\r
+                       foreach (RelaxngPattern p in Patterns)\r
+                               p.Write (writer);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteOptional (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -967,6 +1335,19 @@ namespace Commons.Xml.Relaxng
                        get { return RelaxngPatternType.Mixed; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "mixed", RelaxngGrammar.NamespaceURI);\r
+                       foreach (RelaxngPattern p in Patterns)\r
+                               p.Write (writer);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteMixed (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -984,6 +1365,19 @@ namespace Commons.Xml.Relaxng
                        get { return RelaxngPatternType.Choice; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "choice", RelaxngGrammar.NamespaceURI);\r
+                       foreach (RelaxngPattern p in Patterns)\r
+                               p.Write (writer);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteChoice (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -1001,6 +1395,19 @@ namespace Commons.Xml.Relaxng
                        get { return RelaxngPatternType.Group; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "group", RelaxngGrammar.NamespaceURI);\r
+                       foreach (RelaxngPattern p in Patterns)\r
+                               p.Write (writer);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteGroup (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -1018,6 +1425,19 @@ namespace Commons.Xml.Relaxng
                        get { return RelaxngPatternType.Interleave; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "interleave", RelaxngGrammar.NamespaceURI);\r
+                       foreach (RelaxngPattern p in Patterns)\r
+                               p.Write (writer);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteInterleave (this);\r
+               }\r
+\r
                internal override RdpPattern Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -1050,6 +1470,19 @@ namespace Commons.Xml.Relaxng
                        set { this.value = value; }\r
                }\r
 \r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "param", RelaxngGrammar.NamespaceURI);\r
+                       writer.WriteAttributeString ("name", name);\r
+                       writer.WriteString (Value);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteParam (this);\r
+               }\r
+\r
                internal RdpParam Compile (RelaxngGrammar grammar)\r
                {\r
                        IsCompiled = true;\r
@@ -1073,6 +1506,11 @@ namespace Commons.Xml.Relaxng
                        set { this.List [i] = value; }\r
                }\r
 \r
+               public void Insert (int pos, RelaxngParam p)\r
+               {\r
+                       List.Insert (pos, p);\r
+               }\r
+\r
                public void Remove (RelaxngParam p)\r
                {\r
                        List.Remove (p);\r
@@ -1090,9 +1528,22 @@ namespace Commons.Xml.Relaxng
                public RelaxngPatternList Patterns {\r
                        get { return patterns; }\r
                }\r
+\r
+               public override void Write (XmlWriter writer)\r
+               {\r
+                       writer.WriteStartElement ("", "except", RelaxngGrammar.NamespaceURI);\r
+                       foreach (RelaxngPattern p in Patterns)\r
+                               p.Write (writer);\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               internal override void WriteRnc (RncWriter writer)\r
+               {\r
+                       writer.WriteDataExcept (this);\r
+               }\r
        }\r
 \r
-       public class RelaxngRefPattern\r
+       internal class RelaxngRefPattern\r
        {\r
                RelaxngPattern patternRef;\r
                string name;\r