2 // XslTransformProcessor.cs
5 // Ben Maurer (bmaurer@users.sourceforge.net)
6 // Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
9 // (C) 2003 Atsushi Enomoto
13 using System.Collections;
15 using System.Xml.XPath;
17 using Mono.Xml.Xsl.Operations;
19 using QName = System.Xml.XmlQualifiedName;
21 namespace Mono.Xml.Xsl {
22 public class XslTransformProcessor {
23 CompiledStylesheet compiledStyle;
27 Stack currentTemplateStack = new Stack ();
31 XsltArgumentList args;
33 // Store the values of global params
34 internal Hashtable globalVariableTable = new Hashtable ();
36 public XslTransformProcessor (CompiledStylesheet style)
38 this.compiledStyle = style;
39 this.style = style.Style;
42 public void Process (XPathNavigator root, XmlWriter output, XsltArgumentList args)
44 foreach (XslGlobalVariable v in CompiledStyle.Variables.Values) {
45 if (v is XslGlobalParam) {
46 object p = args.GetParam(v.Name.Name, v.Name.Namespace);
48 ((XslGlobalParam)v).Override (this, p);
54 this.outputStack.Push (output);
55 this.ApplyTemplates (root.Select ("."), QName.Empty, null);
58 public XsltContext Context { get { return ctx; }}
59 public CompiledStylesheet CompiledStyle { get { return compiledStyle; }}
60 public XsltArgumentList Arguments {get{return args;}}
63 Stack outputStack = new Stack ();
65 public XmlWriter Out { get { return (XmlWriter)outputStack.Peek(); }}
67 public void PushOutput (XmlWriter newOutput)
69 this.outputStack.Push (newOutput);
72 public XmlWriter PopOutput ()
74 return (XmlWriter)this.outputStack.Pop ();
78 #region Templates -- Apply/Call
79 public void ApplyTemplates (XPathNodeIterator nodes, QName mode, Hashtable withParams)
82 while (NodesetMoveNext ()) {
83 XslTemplate t = FindTemplate (CurrentNode, mode);
84 currentTemplateStack.Push (t);
85 t.Evaluate (this, withParams);
86 currentTemplateStack.Pop ();
92 public void CallTemplate (QName name, Hashtable withParams)
94 XslTemplate t = FindTemplate (name);
95 currentTemplateStack.Push (null);
96 t.Evaluate (this, withParams);
97 currentTemplateStack.Pop ();
100 public void ApplyImports ()
103 XslTemplate currentTemplate = (XslTemplate)currentTemplateStack.Peek();
104 if (currentTemplate == null) throw new Exception ("Invalid context for apply-imports");
107 for (int i = currentTemplate.Parent.Imports.Count - 1; i >= 0; i--) {
108 XslStylesheet s = (XslStylesheet)currentTemplate.Parent.Imports [i];
109 t = s.Templates.FindMatch (CurrentNode, currentTemplate.Mode);
111 currentTemplateStack.Push (t);
113 currentTemplateStack.Pop ();
118 switch (CurrentNode.NodeType) {
119 case XPathNodeType.Root:
120 case XPathNodeType.Element:
121 if (currentTemplate.Mode == QName.Empty)
122 t = XslDefaultNodeTemplate.Instance;
124 t = new XslDefaultNodeTemplate(currentTemplate.Mode);
127 case XPathNodeType.Attribute:
128 case XPathNodeType.SignificantWhitespace:
129 case XPathNodeType.Text:
130 case XPathNodeType.Whitespace:
131 t = XslDefaultTextTemplate.Instance;
134 case XPathNodeType.Comment:
135 case XPathNodeType.ProcessingInstruction:
136 t = XslEmptyTemplate.Instance;
140 t = XslEmptyTemplate.Instance;
143 currentTemplateStack.Push (t);
145 currentTemplateStack.Pop ();
148 XslTemplate FindTemplate (XPathNavigator node, QName mode)
150 XslTemplate ret = style.Templates.FindMatch (CurrentNode, mode);
152 if (ret != null) return ret;
154 switch (node.NodeType) {
155 case XPathNodeType.Root:
156 case XPathNodeType.Element:
157 if (mode == QName.Empty)
158 return XslDefaultNodeTemplate.Instance;
160 return new XslDefaultNodeTemplate(mode);
162 case XPathNodeType.Attribute:
163 case XPathNodeType.SignificantWhitespace:
164 case XPathNodeType.Text:
165 case XPathNodeType.Whitespace:
166 return XslDefaultTextTemplate.Instance;
168 case XPathNodeType.Comment:
169 case XPathNodeType.ProcessingInstruction:
170 return XslEmptyTemplate.Instance;
173 return XslEmptyTemplate.Instance;
177 XslTemplate FindTemplate (QName name)
179 XslTemplate ret = style.Templates.FindTemplate (name);
180 if (ret != null) return ret;
182 throw new Exception ("Could not resolve named template " + name);
188 public void PushForEachContext ()
190 currentTemplateStack.Push (null);
193 public void PopForEachContext ()
195 currentTemplateStack.Pop ();
199 #region Nodeset Context
200 Stack nodesetStack = new Stack ();
202 public XPathNodeIterator CurrentNodeset {
203 get { return (XPathNodeIterator)nodesetStack.Peek (); }
206 public XPathNavigator CurrentNode {
207 get { return CurrentNodeset.Current; }
210 public bool NodesetMoveNext ()
212 return CurrentNodeset.MoveNext ();
215 public void PushNodeset (XPathNodeIterator itr)
217 nodesetStack.Push (itr.Clone ());
220 public void PopNodeset ()
227 public object Evaluate (XPathExpression expr)
229 expr = CompiledStyle.ExpressionStore.PrepForExecution (expr, this);
231 XPathNodeIterator itr = CurrentNodeset;
232 return itr.Current.Evaluate (expr, itr);
235 public string EvaluateString (XPathExpression expr)
237 expr = CompiledStyle.ExpressionStore.PrepForExecution (expr, this);
239 XPathNodeIterator itr = CurrentNodeset;
240 return itr.Current.EvaluateString (expr, itr);
243 public bool EvaluateBoolean (XPathExpression expr)
245 expr = CompiledStyle.ExpressionStore.PrepForExecution (expr, this);
247 XPathNodeIterator itr = CurrentNodeset;
248 return itr.Current.EvaluateBoolean (expr, itr);
251 public XPathNodeIterator Select (XPathExpression expr)
253 expr = CompiledStyle.ExpressionStore.PrepForExecution (expr, this);
254 return CurrentNodeset.Current.Select (expr);
259 public XslAttributeSet ResolveAttributeSet (QName name)
261 return CompiledStyle.ResolveAttributeSet (name);
264 #region Variable Stack
265 Stack variableStack = new Stack ();
266 object [] currentStack;
268 public object GetStackItem (int slot)
270 return currentStack [slot];
273 public void SetStackItem (int slot, object o)
275 currentStack [slot] = o;
278 public void PushStack (int stackSize)
280 variableStack.Push (currentStack);
281 currentStack = new object [stackSize];
284 public void PopStack ()
286 currentStack = (object[])variableStack.Pop();