1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle
.MonoRail
.Views
.IronView
18 using System
.Collections
.Generic
;
23 public class IronPythonTemplateParser
: ITemplateParser
25 private IElementProcessor
[] processors
;
26 private Stack
<IElementProcessor
> processorStack
= new Stack
<IElementProcessor
>();
29 /// Initializes a new instance of the <see cref="IronPythonTemplateParser"/> class.
31 /// <param name="processors">The processors.</param>
32 public IronPythonTemplateParser(IElementProcessor
[] processors
)
34 this.processors
= processors
;
37 public String
CreateScriptBlock(TextReader reader
, String viewName
,
38 IServiceProvider serviceProvider
, ITemplateEngine engine
)
40 XmlTextReader xmlReader
= new XmlTextReader(reader
);
41 xmlReader
.Namespaces
= false;
42 xmlReader
.WhitespaceHandling
= WhitespaceHandling
.All
;
44 DefaultContext context
= new DefaultContext(viewName
, xmlReader
, serviceProvider
, engine
);
46 ProcessReader(context
, 0);
48 return context
.Script
.ToString();
51 public string CreateFunctionScriptBlock(StreamReader reader
, string partialViewName
, string methodName
,
52 IServiceProvider provider
, ITemplateEngine engine
, params String
[] parameters
)
54 XmlTextReader xmlReader
= new XmlTextReader(reader
);
55 xmlReader
.Namespaces
= false;
56 xmlReader
.WhitespaceHandling
= WhitespaceHandling
.All
;
58 DefaultContext context
= new DefaultContext(partialViewName
, xmlReader
, provider
, engine
);
60 context
.Script
.Append("def ");
61 context
.Script
.Append(methodName
);
62 context
.Script
.Append('(');
63 context
.Script
.Append("controller, context, request, response, session, output, flash, siteroot");
64 // context.Script.Append("output");
65 foreach(String param
in parameters
)
67 context
.Script
.Append(',');
68 context
.Script
.Append(param
);
70 context
.Script
.Append(')');
71 context
.Script
.AppendLine(":");
73 context
.IncreaseIndentation();
75 // context.AppendLineIndented("print 'hello'");
77 ProcessReader(context
, 0);
79 context
.DecreaseIndentation();
81 context
.Script
.AppendLine();
83 return context
.Script
.ToString();
86 #region ITemplateParser
88 public void ProcessReader(ITemplateContext context
, int levelToStop
)
90 XmlReader reader
= context
.Reader
;
94 switch(reader
.NodeType
)
96 case XmlNodeType
.Comment
:
99 case XmlNodeType
.ProcessingInstruction
:
101 if (IsCustomPI(context
))
107 OutputCurrentElementAsContent(context
);
111 case XmlNodeType
.Element
:
113 context
.IncreaseDepth();
115 if (IsCustomElement(reader
))
117 ProcessCustomTag(context
);
121 OutputCurrentElementAsContent(context
);
124 if (!reader
.IsEmptyElement
)
126 context
.DecreaseDepth();
131 case XmlNodeType
.EndElement
:
133 OutputCurrentElementAsContent(context
);
135 context
.DecreaseDepth();
137 if (context
.CurrentElementDepth
== levelToStop
)
144 case XmlNodeType
.Text
:
145 case XmlNodeType
.Whitespace
:
146 OutputCurrentElementAsContent(context
);
149 case XmlNodeType
.DocumentType
:
150 OutputCurrentElementAsContent(context
);
156 public void OutputCurrentElementAsContent(ITemplateContext context
)
158 OutputCurrentElementAsContent(context
, null);
161 public void OutputCurrentElementAsContent(ITemplateContext context
, FilterAttribute filter
)
163 context
.AppendIndented("output.Write('");
165 XmlReader reader
= context
.Reader
;
166 StringBuilder script
= context
.Script
;
168 if (reader
.NodeType
== XmlNodeType
.Element
)
170 if (reader
.IsEmptyElement
)
172 script
.Append("<" + reader
.LocalName
);
173 OutputAttributes(reader
, script
, filter
);
174 script
.Append(" />");
179 script
.Append(reader
.LocalName
);
180 OutputAttributes(reader
, script
, filter
);
184 else if (reader
.NodeType
== XmlNodeType
.EndElement
)
187 script
.Append(reader
.LocalName
);
190 else if (reader
.NodeType
== XmlNodeType
.ProcessingInstruction
)
193 script
.Append(reader
.LocalName
);
195 script
.Append(reader
.Value
);
196 script
.Append(" ?>");
198 else if (reader
.NodeType
== XmlNodeType
.Text
||
199 reader
.NodeType
== XmlNodeType
.Whitespace
)
201 script
.Append(ConvertEscapes(reader
.Value
));
204 script
.AppendLine("')");
209 private bool IsCustomPI(ITemplateContext context
)
211 foreach(IElementProcessor processor
in processors
)
213 if (processor
.CanHandlePI(context
.Reader
.LocalName
, context
.Reader
.Value
))
215 processorStack
.Push(processor
);
224 private void ProcessPI(ITemplateContext context
)
226 processorStack
.Pop().ProcessPI(this, context
);
229 private bool IsCustomElement(XmlReader reader
)
231 foreach(IElementProcessor processor
in processors
)
233 if (processor
.CanHandleElement(this, reader
))
235 processorStack
.Push(processor
);
244 private void ProcessCustomTag(ITemplateContext context
)
246 processorStack
.Pop().ProcessElement(this, context
);
249 private void OutputAttributes(XmlReader reader
, StringBuilder script
, FilterAttribute filter
)
251 if (!reader
.HasAttributes
) return;
253 if (!reader
.MoveToFirstAttribute()) return;
257 String name
= reader
.LocalName
;
259 if (filter
!= null && !filter(name
))
268 script
.Append(reader
.Value
);
271 } while(reader
.MoveToNextAttribute());
274 private string ConvertEscapes(string value)
276 if (value == null || value == String
.Empty
) return String
.Empty
;
278 // TODO: This can be greatly optimized
280 return value.Replace("\t", "\\t").Replace("\n", "\\n").Replace("\r", "\\r");