2003-08-19 Ben Maurer <bmaurer@users.sourceforge.net>
[mono.git] / mcs / class / System.XML / Mono.Xml.Xsl / XslStylesheet.cs
1 //
2 // XslStylesheet.cs
3 //
4 // Authors:
5 //      Ben Maurer (bmaurer@users.sourceforge.net)
6 //      Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
7 //      
8 // (C) 2003 Ben Maurer
9 // (C) 2003 Atsushi Enomoto
10 //
11 \r
12 using System;\r
13 using System.CodeDom;\r
14 using System.Collections;
15 using System.Collections.Specialized;\r
16 using System.Xml;\r
17 using System.Xml.Schema;\r
18 using System.Xml.XPath;\r
19 using System.Xml.Xsl;
20 using System.IO;
21
22 using Mono.Xml.Xsl.Operations;
23 \r
24 using QName = System.Xml.XmlQualifiedName;\r
25
26 namespace Mono.Xml.Xsl {\r
27 \r
28         public class XslStylesheet {\r
29                 public const string XsltNamespace = "http://www.w3.org/1999/XSL/Transform";\r
30                 public const string MSXsltNamespace = "urn:schemas-microsoft-com:xslt::script";\r
31                 
32                 Compiler c;\r
33
34                 XslStylesheet importer;\r
35                 // Top-level elements\r
36                 ArrayList imports = new ArrayList ();\r
37                 // [QName]=>XmlSpace\r
38                 Hashtable spaceControls = new Hashtable ();\r
39                 // [string stylesheet-prefix]=>string result-prefix\r
40                 Hashtable namespaceAliases = new Hashtable ();\r
41                 // [QName]=>XslDecimalFormat\r
42                 Hashtable decimalFormats = new Hashtable ();\r
43                 // [QName]=>XmlSpace\r
44                 Hashtable parameters = new Hashtable ();\r
45                 \r
46                 MSXslScriptManager msScripts = new MSXslScriptManager ();\r
47                 XslTemplateTable templates;\r
48 \r
49                 // stylesheet attributes\r
50                 string version;\r
51                 XmlQualifiedName [] extensionElementPrefixes;\r
52                 XmlQualifiedName [] excludeResultPrefixes;\r
53 \r
54                 // below are newly introduced in XSLT 2.0\r
55                 //  elements::\r
56                 // xsl:import-schema should be interpreted into it.\r
57                 XmlSchemaCollection schemas = new XmlSchemaCollection ();\r
58                 // [QName]=>XslCharacterMap\r
59                 Hashtable characterMap = new Hashtable ();\r
60                 // [QName]=>XslDateFormat\r
61                 Hashtable dateFormats = new Hashtable ();\r
62                 // [QName]=>XslFunction\r
63                 Hashtable functions = new Hashtable ();\r
64                 // [QName]=>XslSortKey\r
65                 Hashtable sortKeys = new Hashtable ();\r
66                 //  attributes::\r
67                 string xpathDefaultNamespace = "";\r
68                 XslDefaultValidation defaultValidation = XslDefaultValidation.Lax;\r
69 \r
70                 public ArrayList Imports {\r
71                         get { return imports; }\r
72                 }\r
73 \r
74                 public Hashtable SpaceControls {\r
75                         get { return spaceControls; }\r
76                 }\r
77 \r
78                 public Hashtable NamespaceAliases {\r
79                         get { return namespaceAliases; }\r
80                 }\r
81 \r
82                 public Hashtable DecimalFormats {\r
83                         get { return decimalFormats; }\r
84                 }\r
85 \r
86                 public Hashtable Parameters {\r
87                         get { return parameters; }\r
88                 }
89 \r
90                 public MSXslScriptManager ScriptManager{\r
91                         get { return msScripts; }\r
92                 }\r
93 \r
94                 public XslTemplateTable Templates {\r
95                         get { return templates; }\r
96                 }\r
97
98 \r
99                 public XslStylesheet (Compiler c)\r
100                 {
101                         this.c = c;
102                         c.PushStylesheet (this);
103                         
104                         templates = new XslTemplateTable (this);\r
105                         if (c.Input.NamespaceURI != XsltNamespace) {\r
106                                 // then it is simplified stylesheet.\r
107                                 Templates.Add (new XslTemplate (c));\r
108                         } else {\r
109                                 version = c.Input.GetAttribute ("version", "");\r
110                                 extensionElementPrefixes = c.ParseQNameListAttribute ("extension-element-prefixes");\r
111                                 excludeResultPrefixes = c.ParseQNameListAttribute ("exclude-result-prefixes");\r
112                                 
113                                 ProcessTopLevelElements ();\r
114                         }
115                         
116                         c.PopStylesheet ();\r
117                 }
118                 
119                 private XslStylesheet (Compiler c, XslStylesheet importer) : this (c)
120                 {
121                         this.importer = importer;
122                 }
123                 
124                 private void HandleInclude (string href)
125                 {
126                         c.PushInputDocument (href);
127                         ProcessTopLevelElements ();
128                         c.PopInputDocument ();
129                 }
130                 
131                 private void HandleImport (string href)
132                 {
133                         c.PushInputDocument (href);
134                         imports.Add (new XslStylesheet (c, this));
135                         c.PopInputDocument ();
136                 }
137                 
138                 private void HandleTopLevelElement ()
139                 {
140                         XPathNavigator n = c.Input;
141                         switch (n.NamespaceURI)
142                         {
143                         case XsltNamespace:
144                                 
145                                 switch (n.LocalName)
146                                 {
147                                 case "include":
148                                         HandleInclude (c.GetAttribute ("href"));
149                                         break;
150                                 case "import":
151                                         HandleImport (c.GetAttribute ("href"));
152                                         break;
153                                 case "preserve-space":
154                                         AddSpaceControls (c.ParseQNameListAttribute ("elements"), XmlSpace.Preserve, n);
155                                         break;
156                                 
157                                 case "strip-space":
158                                         AddSpaceControls (c.ParseQNameListAttribute ("elements"), XmlSpace.Default, n);
159                                         break;
160                                 
161                                 case "namespace-alias":
162                                         namespaceAliases.Add (c.GetAttribute ("stylesheet-prefix", ""), c.GetAttribute ("result-prefix", ""));
163                                         break;
164                                 
165                                 case "attribute-set":
166                                         c.AddAttributeSet (new XslAttributeSet (c));
167                                         break;
168
169                                 case "key":
170                                         c.AddKeyPattern (new XslKey (c));
171                                         break;
172                                         
173                                 case "output":
174                                         c.CompileOutput ();
175                                         break;
176                                         
177                                 case "template":
178                                         templates.Add (new XslTemplate (c));    
179                                         break;
180                                 case "variable":
181                                         c.AddGlobalVariable (new XslGlobalVariable (c));
182                                         break;
183                                 case "param":
184                                         c.AddGlobalVariable (new XslGlobalParam (c));
185                                         break;
186                                 }
187                                 break;
188                         case MSXsltNamespace:
189                                 switch (n.LocalName)
190                                 {
191                                 case "script":
192                                         msScripts.AddScript (n);
193                                         break;
194                                 }
195                                 break;
196                         }
197                 }
198                 \r
199                 private void ProcessTopLevelElements ()\r
200                 {
201                         if (c.Input.MoveToFirstChild ()) {\r
202                                 do {
203                                         if (c.Input.NodeType == XPathNodeType.Element) {                                        
204                                                 Debug.EnterNavigator (c);
205                                                 this.HandleTopLevelElement();
206                                                 Debug.ExitNavigator (c);
207                                         }
208                                 } while (c.Input.MoveToNext ());
209                                 
210                                 c.Input.MoveToParent ();
211                         }\r
212                 }\r
213 \r
214                 private void AddSpaceControls (QName [] names, XmlSpace result, XPathNavigator styleElem)\r
215                 {\r
216                         foreach (QName name in names)\r
217                                 spaceControls.Add (name, result);\r
218                 }\r
219 \r
220         }\r
221 \r
222         \r
223         public enum XslDefaultValidation\r
224         {\r
225                 Strict,\r
226                 Lax,\r
227                 Preserve,\r
228                 Strip\r
229         }\r
230 }\r