2003-11-02 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
[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]=>XmlSpace\r
42                 Hashtable parameters = new Hashtable ();\r
43                 \r
44                 MSXslScriptManager msScripts = new MSXslScriptManager ();\r
45                 XslTemplateTable templates;\r
46 \r
47                 // stylesheet attributes\r
48                 string version;\r
49                 XmlQualifiedName [] extensionElementPrefixes;\r
50                 XmlQualifiedName [] excludeResultPrefixes;\r
51                 StringDictionary stylesheetNamespaces = new StringDictionary ();\r
52 \r
53                 // below are newly introduced in XSLT 2.0\r
54                 //  elements::\r
55                 // xsl:import-schema should be interpreted into it.\r
56                 XmlSchemaCollection schemas = new XmlSchemaCollection ();\r
57                 // [QName]=>XslCharacterMap\r
58                 Hashtable characterMap = new Hashtable ();\r
59                 // [QName]=>XslDateFormat\r
60                 Hashtable dateFormats = new Hashtable ();\r
61                 // [QName]=>XslFunction\r
62                 Hashtable functions = new Hashtable ();\r
63                 // [QName]=>XslSortKey\r
64                 Hashtable sortKeys = new Hashtable ();\r
65                 //  attributes::\r
66                 string xpathDefaultNamespace = "";\r
67                 XslDefaultValidation defaultValidation = XslDefaultValidation.Lax;\r
68 \r
69                 public XmlQualifiedName [] ExtensionElementPrefixes {\r
70                         get { return extensionElementPrefixes; }\r
71                 }\r
72 \r
73                 public XmlQualifiedName [] ExcludeResultPrefixes {\r
74                         get { return excludeResultPrefixes; }\r
75                 }\r
76 \r
77                 public StringDictionary StylesheetNamespaces {\r
78                         get { return stylesheetNamespaces; }\r
79                 }\r
80 \r
81                 public ArrayList Imports {\r
82                         get { return imports; }\r
83                 }\r
84 \r
85                 public Hashtable SpaceControls {\r
86                         get { return spaceControls; }\r
87                 }\r
88 \r
89                 public Hashtable NamespaceAliases {\r
90                         get { return namespaceAliases; }\r
91                 }\r
92
93                 public Hashtable Parameters {\r
94                         get { return parameters; }\r
95                 }
96 \r
97                 public MSXslScriptManager ScriptManager{\r
98                         get { return msScripts; }\r
99                 }\r
100 \r
101                 public XslTemplateTable Templates {\r
102                         get { return templates; }\r
103                 }\r
104
105 \r
106                 public XslStylesheet (Compiler c)\r
107                 {
108                         this.c = c;
109                         c.PushStylesheet (this);
110                         
111                         templates = new XslTemplateTable (this);\r
112                         if (c.Input.NamespaceURI != XsltNamespace) {\r
113                                 // then it is simplified stylesheet.\r
114                                 Templates.Add (new XslTemplate (c));\r
115                         } else {\r
116                                 version = c.Input.GetAttribute ("version", "");\r
117                                 extensionElementPrefixes = c.ParseQNameListAttribute ("extension-element-prefixes");\r
118                                 excludeResultPrefixes = c.ParseQNameListAttribute ("exclude-result-prefixes");\r
119                                 if (c.Input.MoveToFirstNamespace (XPathNamespaceScope.Local)) {
120                                         do {
121                                                 if (c.Input.Value == XsltNamespace)
122                                                         continue;
123                                                 this.stylesheetNamespaces.Add (c.Input.Name, c.Input.Value);
124                                         } while (c.Input.MoveToNextNamespace (XPathNamespaceScope.Local));
125                                         c.Input.MoveToParent ();
126                                 }
127                                 ProcessTopLevelElements ();\r
128                         }
129                         
130                         c.PopStylesheet ();\r
131                 }
132                 
133                 private XslStylesheet (Compiler c, XslStylesheet importer) : this (c)
134                 {
135                         this.importer = importer;
136                 }
137                 
138                 private void HandleInclude (string href)
139                 {
140                         c.PushInputDocument (href);
141                         ProcessTopLevelElements ();
142                         c.PopInputDocument ();
143                 }
144                 
145                 private void HandleImport (string href)
146                 {
147                         c.PushInputDocument (href);
148                         imports.Add (new XslStylesheet (c, this));
149                         c.PopInputDocument ();
150                 }
151                 
152                 private void HandleTopLevelElement ()
153                 {
154                         XPathNavigator n = c.Input;
155                         switch (n.NamespaceURI)
156                         {
157                         case XsltNamespace:
158                                 
159                                 switch (n.LocalName)
160                                 {
161                                 case "include":
162                                         HandleInclude (c.GetAttribute ("href"));
163                                         break;
164                                 case "import":
165                                         HandleImport (c.GetAttribute ("href"));
166                                         break;
167                                 case "preserve-space":
168                                         AddSpaceControls (c.ParseQNameListAttribute ("elements"), XmlSpace.Preserve, n);
169                                         break;
170                                 
171                                 case "strip-space":
172                                         AddSpaceControls (c.ParseQNameListAttribute ("elements"), XmlSpace.Default, n);
173                                         break;
174                                 
175                                 case "namespace-alias":
176                                         namespaceAliases.Add (c.GetAttribute ("stylesheet-prefix", ""), c.GetAttribute ("result-prefix", ""));
177                                         break;
178                                 
179                                 case "attribute-set":
180                                         c.AddAttributeSet (new XslAttributeSet (c));
181                                         break;
182
183                                 case "key":
184                                         c.AddKeyPattern (new XslKey (c));
185                                         break;
186                                         
187                                 case "output":
188                                         c.CompileOutput ();
189                                         break;
190                                 
191                                 case "decimal-format":
192                                         c.CompileDecimalFormat ();
193                                         break;
194                                         
195                                 case "template":
196                                         templates.Add (new XslTemplate (c));    
197                                         break;
198                                 case "variable":
199                                         c.AddGlobalVariable (new XslGlobalVariable (c));
200                                         break;
201                                 case "param":
202                                         c.AddGlobalVariable (new XslGlobalParam (c));
203                                         break;
204                                 }
205                                 break;
206                         case MSXsltNamespace:
207                                 switch (n.LocalName)
208                                 {
209                                 case "script":
210                                         msScripts.AddScript (n);
211                                         break;
212                                 }
213                                 break;
214                         }
215                 }
216                 \r
217                 private void ProcessTopLevelElements ()\r
218                 {
219                         if (c.Input.MoveToFirstChild ()) {\r
220                                 do {
221                                         if (c.Input.NodeType == XPathNodeType.Element) {                                        
222                                                 Debug.EnterNavigator (c);
223                                                 this.HandleTopLevelElement();
224                                                 Debug.ExitNavigator (c);
225                                         }
226                                 } while (c.Input.MoveToNext ());
227                                 
228                                 c.Input.MoveToParent ();
229                         }\r
230                 }\r
231 \r
232                 private void AddSpaceControls (QName [] names, XmlSpace result, XPathNavigator styleElem)\r
233                 {\r
234                         foreach (QName name in names)\r
235                                 spaceControls.Add (name, result);\r
236                 }\r
237 \r
238         }\r
239 \r
240         \r
241         public enum XslDefaultValidation\r
242         {\r
243                 Strict,\r
244                 Lax,\r
245                 Preserve,\r
246                 Strip\r
247         }\r
248 }\r