1 //------------------------------------------------------------------------------
2 // <copyright file="Compiler.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
8 namespace System.Xml.Xsl.XsltOld {
9 using Res = System.Xml.Utils.Res;
11 using System.Diagnostics;
12 using System.Globalization;
14 using System.Xml.XPath;
15 using System.Xml.Xsl.Runtime;
16 using MS.Internal.Xml.XPath;
17 using System.Xml.Xsl.XsltOld.Debugger;
19 using System.Collections;
20 using System.Collections.Generic;
21 using System.Collections.Specialized;
24 using System.CodeDom.Compiler;
25 using System.Reflection;
26 using System.Security;
27 using System.Security.Policy;
28 using System.Security.Permissions;
29 using Keywords = System.Xml.Xsl.Xslt.KeywordsTable;
30 using System.Runtime.Versioning;
35 internal XmlDataType dataType;
36 internal XmlSortOrder order;
37 internal XmlCaseOrder caseOrder;
39 public Sort(int sortkey, String xmllang, XmlDataType datatype, XmlSortOrder xmlorder, XmlCaseOrder xmlcaseorder) {
44 caseOrder = xmlcaseorder;
48 internal enum ScriptingLanguage {
50 #if !FEATURE_PAL // visualbasic
52 #endif // !FEATURE_PAL
56 internal class Compiler {
57 internal const int InvalidQueryKey = -1;
59 internal const double RootPriority = 0.5;
61 // cached StringBuilder for AVT parseing
62 internal StringBuilder AvtStringBuilder = new StringBuilder();
64 private int stylesheetid; // Root stylesheet has id=0. We are using this in CompileImports to compile BuiltIns
65 private InputScope rootScope;
69 private XmlResolver xmlResolver;
72 // Template being currently compiled
73 private TemplateBaseAction currentTemplate;
74 private XmlQualifiedName currentMode;
75 private Hashtable globalNamespaceAliasTable;
78 // Current import stack
79 private Stack stylesheets;
81 private HybridDictionary documentURIs = new HybridDictionary();
83 // import/include documents, who is here has its URI in this.documentURIs
84 private NavigatorInput input;
86 // Atom table & InputScopeManager - cached top of the this.input stack
87 private Keywords atoms;
88 private InputScopeManager scopeManager;
91 // Compiled stylesheet state
92 internal Stylesheet stylesheet;
93 internal Stylesheet rootStylesheet;
94 private RootAction rootAction;
95 private List<TheQuery> queryStore;
96 private QueryBuilder queryBuilder = new QueryBuilder();
97 private int rtfCount = 0;
99 // Used to load Built In templates
100 public bool AllowBuiltInMode;
101 public static XmlQualifiedName BuiltInMode = new XmlQualifiedName("*", string.Empty);
103 internal Keywords Atoms {
105 Debug.Assert(this.atoms != null);
110 internal int Stylesheetid {
111 get{ return this.stylesheetid; }
112 set { this.stylesheetid = value; }
115 internal NavigatorInput Document {
116 get { return this.input; }
119 internal NavigatorInput Input {
120 get { return this.input; }
123 internal bool Advance() {
124 Debug.Assert(Document != null);
125 return Document.Advance();
128 internal bool Recurse() {
129 Debug.Assert(Document != null);
130 return Document.Recurse();
133 internal bool ToParent() {
134 Debug.Assert(Document != null);
135 return Document.ToParent();
138 internal Stylesheet CompiledStylesheet {
139 get { return this.stylesheet; }
142 internal RootAction RootAction {
143 get { return this.rootAction; }
145 Debug.Assert(this.rootAction == null);
146 this.rootAction = value;
147 Debug.Assert(this.currentTemplate == null);
148 this.currentTemplate = this.rootAction;
152 internal List<TheQuery> QueryStore {
153 get { return this.queryStore; }
156 public virtual IXsltDebugger Debugger { get { return null; } }
158 internal string GetUnicRtfId() {
160 return this.rtfCount.ToString(CultureInfo.InvariantCulture);
164 // The World of Compile
166 internal void Compile(NavigatorInput input, XmlResolver xmlResolver, Evidence evidence) {
170 Debug.Assert(input != null);
171 Debug.Assert(xmlResolver != null);
172 // Debug.Assert(evidence != null); -- default evidence is null now
173 Debug.Assert(this.input == null && this.atoms == null);
174 this.xmlResolver = xmlResolver;
176 PushInputDocument(input);
177 this.rootScope = this.scopeManager.PushScope();
178 this.queryStore = new List<TheQuery>();
181 this.rootStylesheet = new Stylesheet();
182 PushStylesheet(this.rootStylesheet);
184 Debug.Assert(this.input != null && this.atoms != null);
187 this.CreateRootAction();
189 catch (XsltCompileException) {
192 catch (Exception e) {
193 throw new XsltCompileException(e, this.Input.BaseURI, this.Input.LineNumber, this.Input.LinePosition);
196 this.stylesheet.ProcessTemplates();
197 this.rootAction.PorcessAttributeSets(this.rootStylesheet);
198 this.stylesheet.SortWhiteSpace();
199 #if !DISABLE_XSLT_SCRIPT
200 CompileScript(evidence);
202 if (evidence != null) {
203 this.rootAction.permissions = SecurityManager.GetStandardSandbox(evidence);
206 if (this.globalNamespaceAliasTable != null) {
207 this.stylesheet.ReplaceNamespaceAlias(this);
208 this.rootAction.ReplaceNamespaceAlias(this);
215 Debug.Assert(this.rootAction != null);
216 Debug.Assert(this.stylesheet != null);
217 Debug.Assert(this.queryStore != null);
218 Debug.Assert(this.input == null && this.atoms == null);
222 // Input scope compiler's support
225 internal bool ForwardCompatibility {
226 get { return this.scopeManager.CurrentScope.ForwardCompatibility; }
227 set { this.scopeManager.CurrentScope.ForwardCompatibility = value; }
230 internal bool CanHaveApplyImports {
231 get { return this.scopeManager.CurrentScope.CanHaveApplyImports; }
232 set { this.scopeManager.CurrentScope.CanHaveApplyImports = value; }
235 internal void InsertExtensionNamespace(string value) {
236 string[] nsList = ResolvePrefixes(value);
237 if (nsList != null) {
238 scopeManager.InsertExtensionNamespaces(nsList);
242 internal void InsertExcludedNamespace(string value) {
243 string[] nsList = ResolvePrefixes(value);
244 if (nsList != null) {
245 scopeManager.InsertExcludedNamespaces(nsList);
249 internal void InsertExtensionNamespace() {
250 InsertExtensionNamespace(Input.Navigator.GetAttribute(Input.Atoms.ExtensionElementPrefixes, Input.Atoms.UriXsl));
253 internal void InsertExcludedNamespace() {
254 InsertExcludedNamespace(Input.Navigator.GetAttribute(Input.Atoms.ExcludeResultPrefixes, Input.Atoms.UriXsl));
257 internal bool IsExtensionNamespace(String nspace) {
258 return this.scopeManager.IsExtensionNamespace(nspace);
261 internal bool IsExcludedNamespace(String nspace) {
262 return this.scopeManager.IsExcludedNamespace(nspace);
265 internal void PushLiteralScope() {
266 PushNamespaceScope();
267 string value = Input.Navigator.GetAttribute(Atoms.Version, Atoms.UriXsl);
268 if (value.Length != 0) {
269 ForwardCompatibility = (value != "1.0");
273 internal void PushNamespaceScope() {
274 this.scopeManager.PushScope();
275 NavigatorInput input = Input;
277 if (input.MoveToFirstNamespace()) {
279 this.scopeManager.PushNamespace(input.LocalName, input.Value);
281 while(input.MoveToNextNamespace());
286 protected InputScopeManager ScopeManager {
287 get { return this.scopeManager; }
290 internal virtual void PopScope() {
291 this.currentTemplate.ReleaseVariableSlots(this.scopeManager.CurrentScope.GetVeriablesCount());
292 this.scopeManager.PopScope();
295 internal InputScopeManager CloneScopeManager() {
296 return this.scopeManager.Clone();
303 internal int InsertVariable(VariableAction variable) {
305 if (variable.IsGlobal) {
306 Debug.Assert(this.rootAction != null);
307 varScope = this.rootScope;
310 Debug.Assert(this.currentTemplate != null);
311 Debug.Assert(variable.VarType == VariableType.LocalVariable || variable.VarType == VariableType.LocalParameter || variable.VarType == VariableType.WithParameter);
312 varScope = this.scopeManager.VariableScope;
315 VariableAction oldVar = varScope.ResolveVariable(variable.Name);
316 if (oldVar != null) {
317 // Other variable with this name is visible in this scope
318 if (oldVar.IsGlobal) {
319 if (variable.IsGlobal) {
320 // Global Vars replace each other base on import presidens odred
321 if (variable.Stylesheetid == oldVar.Stylesheetid) {
322 // Both vars are in the same stylesheet
323 throw XsltException.Create(Res.Xslt_DupVarName, variable.NameStr);
325 else if (variable.Stylesheetid < oldVar.Stylesheetid) {
326 // newly defined var is more importent
327 varScope.InsertVariable(variable);
328 return oldVar.VarKey;
331 // we egnore new variable
332 return InvalidQueryKey; // We didn't add this var, so doesn't matter what VarKey we return;
336 // local variable can shadow global
340 // Local variable never can be "shadowed"
341 throw XsltException.Create(Res.Xslt_DupVarName, variable.NameStr);
345 varScope.InsertVariable(variable);
346 return this.currentTemplate.AllocateVariableSlot();
349 internal void AddNamespaceAlias(String StylesheetURI, NamespaceInfo AliasInfo){
350 if (this.globalNamespaceAliasTable == null) {
351 this.globalNamespaceAliasTable = new Hashtable();
353 NamespaceInfo duplicate = this.globalNamespaceAliasTable[StylesheetURI] as NamespaceInfo;
354 if (duplicate == null || AliasInfo.stylesheetId <= duplicate.stylesheetId) {
355 this.globalNamespaceAliasTable[StylesheetURI] = AliasInfo;
359 internal bool IsNamespaceAlias(String StylesheetURI){
360 if (this.globalNamespaceAliasTable == null) {
363 return this.globalNamespaceAliasTable.Contains(StylesheetURI);
366 internal NamespaceInfo FindNamespaceAlias(String StylesheetURI) {
367 if (this.globalNamespaceAliasTable != null) {
368 return (NamespaceInfo)this.globalNamespaceAliasTable[StylesheetURI];
373 internal String ResolveXmlNamespace(String prefix) {
374 return this.scopeManager.ResolveXmlNamespace(prefix);
377 internal String ResolveXPathNamespace(String prefix) {
378 return this.scopeManager.ResolveXPathNamespace(prefix);
381 internal String DefaultNamespace {
382 get{ return this.scopeManager.DefaultNamespace; }
385 internal void InsertKey(XmlQualifiedName name, int MatchKey, int UseKey) {
386 this.rootAction.InsertKey(name, MatchKey, UseKey);
389 internal void AddDecimalFormat(XmlQualifiedName name, DecimalFormat formatinfo) {
390 this.rootAction.AddDecimalFormat(name, formatinfo);
394 // Attribute parsing support
397 // This function is for processing optional attributes only. In case of error
398 // the value is ignored iff forwards-compatible mode is on.
399 private string[] ResolvePrefixes(string tokens) {
400 if (tokens == null || tokens.Length == 0) {
403 string[] nsList = XmlConvert.SplitString(tokens);
406 for (int idx = 0; idx < nsList.Length; idx++) {
407 string prefix = nsList[idx];
408 nsList[idx] = scopeManager.ResolveXmlNamespace(prefix == "#default" ? string.Empty : prefix);
411 catch (XsltException) {
412 // The only exception here might be Res.Xslt_InvalidPrefix
413 if (!ForwardCompatibility) {
414 // Rethrow the exception if we're not in forwards-compatible mode
417 // Ignore the whole list in forwards-compatible mode
423 internal bool GetYesNo(string value) {
424 Debug.Assert(value != null);
425 Debug.Assert((object)value == (object)Input.Value); // this is always true. Why we passing value to this function.
426 if (value == "yes") {
432 throw XsltException.Create(Res.Xslt_InvalidAttrValue, Input.LocalName, value);
435 internal string GetSingleAttribute(string attributeAtom) {
436 NavigatorInput input = Input;
437 string element = input.LocalName;
440 if (input.MoveToFirstAttribute()) {
442 string nspace = input.NamespaceURI;
443 string name = input.LocalName;
445 if (nspace.Length != 0) continue;
447 if (Ref.Equal(name, attributeAtom)) {
451 if (! this.ForwardCompatibility) {
452 throw XsltException.Create(Res.Xslt_InvalidAttribute, name, element);
456 while (input.MoveToNextAttribute());
461 throw XsltException.Create(Res.Xslt_MissingAttribute, attributeAtom);
466 internal XmlQualifiedName CreateXPathQName(string qname) {
467 string prefix, local;
468 PrefixQName.ParseQualifiedName(qname, out prefix, out local);
470 return new XmlQualifiedName(local, this.scopeManager.ResolveXPathNamespace(prefix));
473 internal XmlQualifiedName CreateXmlQName(string qname) {
474 string prefix, local;
475 PrefixQName.ParseQualifiedName(qname, out prefix, out local);
477 return new XmlQualifiedName(local, this.scopeManager.ResolveXmlNamespace(prefix));
481 // Input documents management
484 internal static XPathDocument LoadDocument(XmlTextReaderImpl reader) {
485 reader.EntityHandling = EntityHandling.ExpandEntities;
486 reader.XmlValidatingReaderCompatibilityMode = true;
488 return new XPathDocument(reader, XmlSpace.Preserve);
495 private void AddDocumentURI(string href) {
496 Debug.Assert(!this.documentURIs.Contains(href), "Circular references must be checked while processing xsl:include and xsl:import");
497 this.documentURIs.Add(href, null);
500 private void RemoveDocumentURI(string href) {
501 Debug.Assert(this.documentURIs.Contains(href), "Attempt to remove href that was not added");
502 this.documentURIs.Remove(href);
505 internal bool IsCircularReference(string href) {
506 return this.documentURIs.Contains(href);
509 [ResourceConsumption(ResourceScope.Machine)]
510 [ResourceExposure(ResourceScope.Machine)]
511 internal Uri ResolveUri(string relativeUri) {
512 Debug.Assert(this.xmlResolver != null);
513 string baseUri = this.Input.BaseURI;
514 Uri uri = this.xmlResolver.ResolveUri((baseUri.Length != 0) ? this.xmlResolver.ResolveUri(null, baseUri) : null, relativeUri);
516 throw XsltException.Create(Res.Xslt_CantResolve, relativeUri);
521 internal NavigatorInput ResolveDocument(Uri absoluteUri) {
522 Debug.Assert(this.xmlResolver != null);
523 object input = this.xmlResolver.GetEntity(absoluteUri, null, null);
524 string resolved = absoluteUri.ToString();
526 if (input is Stream) {
527 XmlTextReaderImpl tr = new XmlTextReaderImpl(resolved, (Stream) input); {
528 tr.XmlResolver = this.xmlResolver;
530 // reader is closed by Compiler.LoadDocument()
531 return new NavigatorInput(Compiler.LoadDocument(tr).CreateNavigator(), resolved, rootScope);
533 else if (input is XPathNavigator) {
534 return new NavigatorInput((XPathNavigator) input, resolved, rootScope);
537 throw XsltException.Create(Res.Xslt_CantResolve, resolved);
541 internal void PushInputDocument(NavigatorInput newInput) {
542 Debug.Assert(newInput != null);
543 string inputUri = newInput.Href;
545 AddDocumentURI(inputUri);
547 newInput.Next = this.input;
548 this.input = newInput;
549 this.atoms = this.input.Atoms;
550 this.scopeManager = this.input.InputScopeManager;
553 internal void PopInputDocument() {
554 Debug.Assert(this.input != null);
555 Debug.Assert(this.input.Atoms == this.atoms);
557 NavigatorInput lastInput = this.input;
559 this.input = lastInput.Next;
560 lastInput.Next = null;
562 if (this.input != null) {
563 this.atoms = this.input.Atoms;
564 this.scopeManager = this.input.InputScopeManager;
568 this.scopeManager = null;
571 RemoveDocumentURI(lastInput.Href);
576 // Stylesheet management
579 internal void PushStylesheet(Stylesheet stylesheet) {
580 if (this.stylesheets == null) {
581 this.stylesheets = new Stack();
583 Debug.Assert(this.stylesheets != null);
585 this.stylesheets.Push(stylesheet);
586 this.stylesheet = stylesheet;
589 internal Stylesheet PopStylesheet() {
590 Debug.Assert(this.stylesheet == this.stylesheets.Peek());
591 Stylesheet stylesheet = (Stylesheet) this.stylesheets.Pop();
592 this.stylesheet = (Stylesheet) this.stylesheets.Peek();
597 // Attribute-Set management
600 internal void AddAttributeSet(AttributeSetAction attributeSet) {
601 Debug.Assert(this.stylesheet == this.stylesheets.Peek());
602 this.stylesheet.AddAttributeSet(attributeSet);
606 // Template management
609 internal void AddTemplate(TemplateAction template) {
610 Debug.Assert(this.stylesheet == this.stylesheets.Peek());
611 this.stylesheet.AddTemplate(template);
614 internal void BeginTemplate(TemplateAction template) {
615 Debug.Assert(this.currentTemplate != null);
616 this.currentTemplate = template;
617 this.currentMode = template.Mode;
618 this.CanHaveApplyImports = template.MatchKey != Compiler.InvalidQueryKey;
621 internal void EndTemplate() {
622 Debug.Assert(this.currentTemplate != null);
623 this.currentTemplate = this.rootAction;
626 internal XmlQualifiedName CurrentMode {
627 get { return this.currentMode; }
633 internal int AddQuery(string xpathQuery) {
634 return AddQuery(xpathQuery, /*allowVars:*/true, /*allowKey*/true, false);
637 internal int AddQuery(string xpathQuery, bool allowVar, bool allowKey, bool isPattern) {
638 Debug.Assert(this.queryStore != null);
640 CompiledXpathExpr expr;
642 expr = new CompiledXpathExpr(
644 ? this.queryBuilder.BuildPatternQuery(xpathQuery, allowVar, allowKey)
645 : this.queryBuilder.Build( xpathQuery, allowVar, allowKey)
650 } catch (XPathException e) {
651 if (! ForwardCompatibility) {
652 throw XsltException.Create(Res.Xslt_InvalidXPath, new string[] { xpathQuery }, e);
654 expr = new ErrorXPathExpression(xpathQuery, this.Input.BaseURI, this.Input.LineNumber, this.Input.LinePosition);
656 this.queryStore.Add(new TheQuery(expr, this.scopeManager));
657 return this.queryStore.Count - 1;
660 internal int AddStringQuery(string xpathQuery) {
661 string modifiedQuery = XmlCharType.Instance.IsOnlyWhitespace(xpathQuery) ? xpathQuery : "string(" + xpathQuery + ")";
662 return AddQuery(modifiedQuery);
665 internal int AddBooleanQuery(string xpathQuery) {
666 string modifiedQuery = XmlCharType.Instance.IsOnlyWhitespace(xpathQuery) ? xpathQuery : "boolean(" + xpathQuery + ")";
667 return AddQuery(modifiedQuery);
673 Hashtable[] _typeDeclsByLang = new Hashtable[] { new Hashtable(), new Hashtable(), new Hashtable() };
674 ArrayList scriptFiles = new ArrayList();
675 // Namespaces we always import when compiling
676 private static string[] _defaultNamespaces = new string[] {
678 "System.Collections",
680 "System.Text.RegularExpressions",
686 private static int scriptClassCounter = 0;
687 private static string GenerateUniqueClassName() {
688 return "ScriptClass_" + System.Threading.Interlocked.Increment(ref scriptClassCounter);
691 #if !DISABLE_XSLT_SCRIPT
692 internal void AddScript(string source, ScriptingLanguage lang, string ns, string fileName, int lineNumber) {
693 ValidateExtensionNamespace(ns);
695 for (ScriptingLanguage langTmp = ScriptingLanguage.JScript; langTmp <= ScriptingLanguage.CSharp; langTmp ++) {
696 Hashtable typeDecls = _typeDeclsByLang[(int)langTmp];
697 if (lang == langTmp) {
698 CodeTypeDeclaration scriptClass = (CodeTypeDeclaration)typeDecls[ns];
699 if (scriptClass == null) {
700 scriptClass = new CodeTypeDeclaration(GenerateUniqueClassName());
701 scriptClass.TypeAttributes = TypeAttributes.Public;
702 typeDecls.Add(ns, scriptClass);
704 CodeSnippetTypeMember scriptSnippet = new CodeSnippetTypeMember(source);
705 if (lineNumber > 0) {
706 scriptSnippet.LinePragma = new CodeLinePragma(fileName, lineNumber);
707 scriptFiles.Add(fileName);
709 scriptClass.Members.Add(scriptSnippet);
711 else if (typeDecls.Contains(ns)) {
712 throw XsltException.Create(Res.Xslt_ScriptMixedLanguages, ns);
718 private static void ValidateExtensionNamespace(string nsUri) {
719 if (nsUri.Length == 0 || nsUri == XmlReservedNs.NsXslt) {
720 throw XsltException.Create(Res.Xslt_InvalidExtensionNamespace);
722 XmlConvert.ToUri(nsUri);
725 #if !DISABLE_XSLT_SCRIPT
726 private void FixCompilerError(CompilerError e) {
727 foreach(string scriptFile in this.scriptFiles) {
728 if (e.FileName == scriptFile) {
729 return; // Yes! this error is in our code sippet.
732 e.FileName = string.Empty;
735 CodeDomProvider ChooseCodeDomProvider(ScriptingLanguage lang) {
737 lang == ScriptingLanguage.JScript ? (CodeDomProvider) Activator.CreateInstance(Type.GetType("Microsoft.JScript.JScriptCodeProvider, " + AssemblyRef.MicrosoftJScript), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, null, null) :
738 #if !FEATURE_PAL // visualbasic
739 lang == ScriptingLanguage.VisualBasic ? (CodeDomProvider) new Microsoft.VisualBasic.VBCodeProvider() :
741 /*CSharp | default */ (CodeDomProvider) new Microsoft.CSharp.CSharpCodeProvider()
745 private void CompileScript(Evidence evidence) {
746 for (ScriptingLanguage lang = ScriptingLanguage.JScript; lang <= ScriptingLanguage.CSharp; lang ++) {
748 if (_typeDeclsByLang[idx].Count > 0) {
749 CompileAssembly(lang, _typeDeclsByLang[idx], lang.ToString(), evidence);
754 [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
755 // SxS: This method does not take any resource name and does not expose any resources to the caller.
756 // It's OK to suppress the SxS warning.
757 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
758 [ResourceExposure(ResourceScope.None)]
759 private void CompileAssembly(ScriptingLanguage lang, Hashtable typeDecls, string nsName, Evidence evidence) {
760 nsName = "Microsoft.Xslt.CompiledScripts." + nsName;
761 CodeNamespace msXslt = new CodeNamespace(nsName);
763 // Add all the default namespaces
764 foreach(string ns in _defaultNamespaces) {
765 msXslt.Imports.Add(new CodeNamespaceImport(ns));
768 #if !FEATURE_PAL // visualbasic
769 if (lang == ScriptingLanguage.VisualBasic) {
770 msXslt.Imports.Add(new CodeNamespaceImport("Microsoft.VisualBasic"));
772 #endif //!FEATURE_PAL
774 foreach(CodeTypeDeclaration scriptClass in typeDecls.Values) {
775 msXslt.Types.Add(scriptClass);
778 CodeCompileUnit unit = new CodeCompileUnit(); {
779 unit.Namespaces.Add(msXslt);
780 // This settings have sense for Visual Basic only.
781 // We can consider in future to allow user set them in <xsl:script option="???"> attribute.
782 unit.UserData["AllowLateBound"] = true; // Allow variables to be undeclared
783 unit.UserData["RequireVariableDeclaration"] = false; // Allow variables to be declared untyped
786 // We want the assemblies generated for scripts to stick to the old security model
787 unit.AssemblyCustomAttributes.Add(
788 new CodeAttributeDeclaration(
789 new CodeTypeReference(typeof(System.Security.SecurityRulesAttribute)),
790 new CodeAttributeArgument(
791 new CodeFieldReferenceExpression(
792 new CodeTypeReferenceExpression(typeof(System.Security.SecurityRuleSet)), "Level1"))));
794 CompilerParameters compilParams = new CompilerParameters(); {
796 new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Assert();
798 compilParams.GenerateInMemory = true;
799 #pragma warning disable 618
800 compilParams.Evidence = evidence;
801 #pragma warning restore 618
802 compilParams.ReferencedAssemblies.Add(typeof(XPathNavigator).Module.FullyQualifiedName);
803 compilParams.ReferencedAssemblies.Add("system.dll");
804 #if !FEATURE_PAL // visualbasic
805 if (lang == ScriptingLanguage.VisualBasic) {
806 compilParams.ReferencedAssemblies.Add("microsoft.visualbasic.dll");
808 #endif // !FEATURE_PAL
811 CodeAccessPermission.RevertAssert();
816 CompilerResults results = ChooseCodeDomProvider(lang).CompileAssemblyFromDom(compilParams, unit);
817 if (results.Errors.HasErrors) {
818 StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
819 foreach (CompilerError e in results.Errors) {
821 stringWriter.WriteLine(e.ToString());
823 throw XsltException.Create(Res.Xslt_ScriptCompileErrors, stringWriter.ToString());
825 Assembly assembly = results.CompiledAssembly;
826 foreach(DictionaryEntry entry in typeDecls) {
827 string ns = (string)entry.Key;
828 CodeTypeDeclaration scriptClass = (CodeTypeDeclaration)entry.Value;
829 this.stylesheet.ScriptObjectTypes.Add(ns, assembly.GetType(nsName + "." + scriptClass.Name));
834 public string GetNsAlias(ref string prefix) {
836 Ref.Equal(this.input.LocalName, this.input.Atoms.StylesheetPrefix) ||
837 Ref.Equal(this.input.LocalName, this.input.Atoms.ResultPrefix)
839 if (prefix == "#default") {
840 prefix = string.Empty;
841 return this.DefaultNamespace;
844 if (! PrefixQName.ValidatePrefix(prefix)) {
845 throw XsltException.Create(Res.Xslt_InvalidAttrValue, this.input.LocalName, prefix);
847 return this.ResolveXPathNamespace(prefix);
851 // AVT's compilation.
852 // CompileAvt() returns ArrayList of TextEvent & AvtEvent
854 private static void getTextLex(string avt, ref int start, StringBuilder lex) {
855 Debug.Assert(avt.Length != start, "Empty string not supposed here");
856 Debug.Assert(lex.Length == 0 , "Builder shoud to be reset here");
857 int avtLength = avt.Length;
859 for (i = start; i < avtLength; i ++) {
862 if (i + 1 < avtLength && avt[i + 1] == '{') { // "{{"
869 else if (ch == '}') {
870 if (i + 1 < avtLength && avt[i + 1] == '}') { // "}}"
874 throw XsltException.Create(Res.Xslt_SingleRightAvt, avt);
882 private static void getXPathLex(string avt, ref int start, StringBuilder lex) {
884 const int InExp = 0; // Inside AVT expression
885 const int InLiteralA = 1; // Inside literal in expression, apostrophe delimited
886 const int InLiteralQ = 2; // Inside literal in expression, quote delimited
887 Debug.Assert(avt.Length != start, "Empty string not supposed here");
888 Debug.Assert(lex.Length == 0 , "Builder shoud to be reset here");
889 Debug.Assert(avt[start] == '{' , "We calling getXPathLex() only after we realy meet {");
890 int avtLength = avt.Length;
892 for (int i = start + 1; i < avtLength; i ++) {
898 throw XsltException.Create(Res.Xslt_NestedAvt, avt);
901 if (i == start + 2) { // empty XPathExpresion
902 throw XsltException.Create(Res.Xslt_EmptyAvtExpr, avt);
904 lex.Append(avt, start + 1, i - start - 2); // avt without {}
928 // if we meet end of string before } we have an error
929 throw XsltException.Create(state == InExp ? Res.Xslt_OpenBracesAvt : Res.Xslt_OpenLiteralAvt, avt);
932 private static bool GetNextAvtLex(string avt, ref int start, StringBuilder lex, out bool isAvt) {
933 Debug.Assert(start <= avt.Length);
935 int saveStart = start;
938 if (start == avt.Length) {
942 getTextLex(avt, ref start, lex);
943 if (lex.Length == 0) {
945 getXPathLex(avt, ref start, lex);
948 Debug.Assert(saveStart < start, "We have to read something. Otherwise it's dead loop.");
953 internal ArrayList CompileAvt(string avtText, out bool constant) {
954 Debug.Assert(avtText != null);
955 ArrayList list = new ArrayList();
958 /* Parse input.Value as AVT */ {
961 while (GetNextAvtLex(avtText, ref pos, this.AvtStringBuilder, out isAvt)) {
962 string lex = this.AvtStringBuilder.ToString();
964 list.Add(new AvtEvent(this.AddStringQuery(lex)));
968 list.Add(new TextEvent(lex));
972 Debug.Assert(!constant || list.Count <= 1, "We can't have more then 1 text event if now {avt} found");
976 internal ArrayList CompileAvt(string avtText) {
978 return CompileAvt(avtText, out constant);
981 // Compiler is a class factory for some actions:
982 // CompilerDbg override all this methods:
984 public virtual ApplyImportsAction CreateApplyImportsAction() {
985 ApplyImportsAction action = new ApplyImportsAction();
986 action.Compile(this);
990 public virtual ApplyTemplatesAction CreateApplyTemplatesAction() {
991 ApplyTemplatesAction action = new ApplyTemplatesAction();
992 action.Compile(this);
996 public virtual AttributeAction CreateAttributeAction() {
997 AttributeAction action = new AttributeAction();
998 action.Compile(this);
1002 public virtual AttributeSetAction CreateAttributeSetAction() {
1003 AttributeSetAction action = new AttributeSetAction();
1004 action.Compile(this);
1008 public virtual CallTemplateAction CreateCallTemplateAction() {
1009 CallTemplateAction action = new CallTemplateAction();
1010 action.Compile(this);
1014 public virtual ChooseAction CreateChooseAction() {//!!! don't need to be here
1015 ChooseAction action = new ChooseAction();
1016 action.Compile(this);
1020 public virtual CommentAction CreateCommentAction() {
1021 CommentAction action = new CommentAction();
1022 action.Compile(this);
1026 public virtual CopyAction CreateCopyAction() {
1027 CopyAction action = new CopyAction();
1028 action.Compile(this);
1032 public virtual CopyOfAction CreateCopyOfAction() {
1033 CopyOfAction action = new CopyOfAction();
1034 action.Compile(this);
1038 public virtual ElementAction CreateElementAction() {
1039 ElementAction action = new ElementAction();
1040 action.Compile(this);
1044 public virtual ForEachAction CreateForEachAction() {
1045 ForEachAction action = new ForEachAction();
1046 action.Compile(this);
1050 public virtual IfAction CreateIfAction(IfAction.ConditionType type) {
1051 IfAction action = new IfAction(type);
1052 action.Compile(this);
1056 public virtual MessageAction CreateMessageAction() {
1057 MessageAction action = new MessageAction();
1058 action.Compile(this);
1062 public virtual NewInstructionAction CreateNewInstructionAction() {
1063 NewInstructionAction action = new NewInstructionAction();
1064 action.Compile(this);
1068 public virtual NumberAction CreateNumberAction() {
1069 NumberAction action = new NumberAction();
1070 action.Compile(this);
1074 public virtual ProcessingInstructionAction CreateProcessingInstructionAction() {
1075 ProcessingInstructionAction action = new ProcessingInstructionAction();
1076 action.Compile(this);
1080 public virtual void CreateRootAction() {
1081 this.RootAction = new RootAction();
1082 this.RootAction.Compile(this);
1085 public virtual SortAction CreateSortAction() {
1086 SortAction action = new SortAction();
1087 action.Compile(this);
1091 public virtual TemplateAction CreateTemplateAction() {
1092 TemplateAction action = new TemplateAction();
1093 action.Compile(this);
1097 public virtual TemplateAction CreateSingleTemplateAction() {
1098 TemplateAction action = new TemplateAction();
1099 action.CompileSingle(this);
1103 public virtual TextAction CreateTextAction() {
1104 TextAction action = new TextAction();
1105 action.Compile(this);
1109 public virtual UseAttributeSetsAction CreateUseAttributeSetsAction() {
1110 UseAttributeSetsAction action = new UseAttributeSetsAction();
1111 action.Compile(this);
1115 public virtual ValueOfAction CreateValueOfAction() {
1116 ValueOfAction action = new ValueOfAction();
1117 action.Compile(this);
1121 public virtual VariableAction CreateVariableAction(VariableType type) {
1122 VariableAction action = new VariableAction(type);
1123 action.Compile(this);
1124 if (action.VarKey != InvalidQueryKey) {
1132 public virtual WithParamAction CreateWithParamAction() {
1133 WithParamAction action = new WithParamAction();
1134 action.Compile(this);
1138 // Compiler is a class factory for some events:
1139 // CompilerDbg override all this methods:
1141 public virtual BeginEvent CreateBeginEvent() {
1142 return new BeginEvent(this);
1145 public virtual TextEvent CreateTextEvent() {
1146 return new TextEvent(this);
1149 public XsltException UnexpectedKeyword() {
1150 XPathNavigator nav = this.Input.Navigator.Clone();
1151 string thisName = nav.Name;
1153 string parentName = nav.Name;
1154 return XsltException.Create(Res.Xslt_UnexpectedKeyword, thisName, parentName);
1157 internal class ErrorXPathExpression : CompiledXpathExpr {
1158 private string baseUri;
1159 private int lineNumber, linePosition;
1160 public ErrorXPathExpression(string expression, string baseUri, int lineNumber, int linePosition)
1161 : base(null, expression, false)
1163 this.baseUri = baseUri;
1164 this.lineNumber = lineNumber;
1165 this.linePosition = linePosition;
1168 public override XPathExpression Clone() { return this; }
1169 public override void CheckErrors() {
1170 throw new XsltException(Res.Xslt_InvalidXPath, new string[] { Expression }, baseUri, linePosition, lineNumber, null);