The Labs \ Source Viewer \ SSCLI \ System.Xml.Xsl.Xslt \ InstructionFlags

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XsltLoader.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. using System.Collections;
  16. using System.Collections.Generic;
  17. using System.Collections.Specialized;
  18. using System.Diagnostics;
  19. using System.Reflection;
  20. using System.Text;
  21. using System.IO;
  22. using System.Xml.XPath;
  23. using System.Xml.Xsl.Qil;
  24. namespace System.Xml.Xsl.Xslt
  25. {
  26.     using ContextInfo = XsltInput.ContextInfo;
  27.     using f = AstFactory;
  28.     using Res = System.Xml.Utils.Res;
  29.     using TypeFactory = XmlQueryTypeFactory;
  30.    
  31.     internal class XsltLoader : IErrorHelper
  32.     {
  33.         private Compiler compiler;
  34.         private XmlResolver xmlResolver;
  35.         private QueryReaderSettings readerSettings;
  36.         private XsltInput input;
  37.         // Current input stream
  38.         private Stylesheet curStylesheet;
  39.         // Current stylesheet
  40.         private Template curTemplate;
  41.         // Current template; used in XslApplyImports() only
  42.         private static QilName nullMode = f.QName(string.Empty);
  43.        
  44.         public void Load(Compiler compiler, object stylesheet, XmlResolver xmlResolver)
  45.         {
  46.             Debug.Assert(compiler != null);
  47.             this.compiler = compiler;
  48.             this.xmlResolver = xmlResolver ?? XmlNullResolver.Singleton;
  49.            
  50.             XmlReader reader = stylesheet as XmlReader;
  51.             if (reader != null) {
  52.                 readerSettings = new QueryReaderSettings(reader);
  53.                     /*include:*/                LoadStylesheet(reader, false);
  54.             }
  55.             else {
  56.                 // We should take DefaultReaderSettings from Compiler.Settings.DefaultReaderSettings.
  57.                
  58.                 string uri = stylesheet as string;
  59.                 if (uri != null) {
  60.                     // If xmlResolver == null, then the original uri will be resolved using XmlUrlResolver
  61.                     XmlResolver origResolver = xmlResolver ?? new XmlUrlResolver();
  62.                     Uri resolvedUri = origResolver.ResolveUri(null, uri);
  63.                     if (resolvedUri == null) {
  64.                         throw new XslLoadException(Res.Xslt_CantResolve, uri);
  65.                     }
  66.                    
  67.                     readerSettings = new QueryReaderSettings(new NameTable());
  68.                     using (reader = CreateReader(resolvedUri, origResolver)) {
  69.                             /*include:*/                        LoadStylesheet(reader, false);
  70.                     }
  71.                 }
  72.                 else {
  73.                     IXPathNavigable navigable = stylesheet as IXPathNavigable;
  74.                     if (navigable != null) {
  75.                         reader = XPathNavigatorReader.Create(navigable.CreateNavigator());
  76.                         readerSettings = new QueryReaderSettings(reader.NameTable);
  77.                             /*include:*/                        LoadStylesheet(reader, false);
  78.                     }
  79.                     else {
  80.                         Debug.Fail("Should never get here");
  81.                     }
  82.                 }
  83.             }
  84.             Process();
  85.         }
  86.        
  87.         private void Process()
  88.         {
  89.             Debug.Assert(compiler.PrincipalStylesheet != null);
  90.             compiler.StartApplyTemplates = f.ApplyTemplates(nullMode);
  91.             ProcessOutputSettings();
  92.             ProcessAttributeSets();
  93.         }
  94.        
  95.         // Import/Include XsltInput management
  96.        
  97.         private HybridDictionary documentUriInUse = new HybridDictionary();
  98.        
  99.         private Uri ResolveUri(string relativeUri, string baseUri)
  100.         {
  101.             Uri resolvedBaseUri = (baseUri.Length != 0) ? xmlResolver.ResolveUri(null, baseUri) : null;
  102.             Uri resolvedUri = xmlResolver.ResolveUri(resolvedBaseUri, relativeUri);
  103.             if (resolvedUri == null) {
  104.                 throw new XslLoadException(Res.Xslt_CantResolve, relativeUri);
  105.             }
  106.             return resolvedUri;
  107.         }
  108.        
  109.         private XmlReader CreateReader(Uri uri, XmlResolver xmlResolver)
  110.         {
  111.             object input = xmlResolver.GetEntity(uri, null, null);
  112.            
  113.             Stream stream = input as Stream;
  114.             if (stream != null) {
  115.                 return readerSettings.CreateReader(stream, uri.ToString());
  116.             }
  117.            
  118.             XmlReader reader = input as XmlReader;
  119.             if (reader != null) {
  120.                 return reader;
  121.             }
  122.            
  123.             IXPathNavigable navigable = input as IXPathNavigable;
  124.             if (navigable != null) {
  125.                 return XPathNavigatorReader.Create(navigable.CreateNavigator());
  126.             }
  127.            
  128.             throw new XslLoadException(Res.Xslt_CannotLoadStylesheet, uri.ToString(), input == null ? "null" : input.GetType().ToString());
  129.         }
  130.        
  131.         private Stylesheet LoadStylesheet(Uri uri, bool include)
  132.         {
  133.             using (XmlReader reader = CreateReader(uri, this.xmlResolver)) {
  134.                 return LoadStylesheet(reader, include);
  135.             }
  136.         }
  137.        
  138.         private Stylesheet LoadStylesheet(XmlReader reader, bool include)
  139.         {
  140.             string baseUri = reader.BaseURI;
  141.             Debug.Assert(!documentUriInUse.Contains(baseUri), "Circular references must be checked while processing xsl:include and xsl:import");
  142.             documentUriInUse.Add(baseUri, null);
  143.            
  144.             Stylesheet prevStylesheet = curStylesheet;
  145.             XsltInput prevInput = input;
  146.             Stylesheet thisStylesheet = include ? curStylesheet : compiler.CreateStylesheet();
  147.            
  148.             input = new XsltInput(reader, compiler);
  149.             curStylesheet = thisStylesheet;
  150.            
  151.             try {
  152.                 LoadDocument();
  153.                 if (!include) {
  154.                     compiler.MergeWithStylesheet(curStylesheet);
  155.                    
  156.                     List<Uri> importHrefs = curStylesheet.ImportHrefs;
  157.                     curStylesheet.Imports = new Stylesheet[importHrefs.Count];
  158.                     // We can't reverce imports order. Template lookup relies on it after compilation
  159.                     // Imports should be compiled in the reverse order
  160.                     for (int i = importHrefs.Count - 1; 0 <= i; i--) {
  161.                             /*include:*/                        curStylesheet.Imports[i] = LoadStylesheet(importHrefs[i], false);
  162.                     }
  163.                 }
  164.             }
  165.             catch (XslLoadException) {
  166.                 throw;
  167.             }
  168.             catch (Exception e) {
  169.                 if (!XmlException.IsCatchableException(e)) {
  170.                     throw;
  171.                 }
  172.                 XmlException ex = e as XmlException;
  173.                 if (ex != null) {
  174.                     SourceLineInfo lineInfo = new SourceLineInfo(input.Uri, ex.LineNumber, ex.LinePosition, ex.LineNumber, ex.LinePosition);
  175.                     throw new XslLoadException(ex, lineInfo);
  176.                 }
  177.                 input.FixLastLineInfo();
  178.                 throw new XslLoadException(e, input.BuildLineInfo());
  179.             }
  180.             finally {
  181.                 documentUriInUse.Remove(baseUri);
  182.                 input = prevInput;
  183.                 curStylesheet = prevStylesheet;
  184.             }
  185.             return thisStylesheet;
  186.         }
  187.        
  188.         private void LoadDocument()
  189.         {
  190.             if (!input.Start()) {
  191.                     /*[XT_002]*/                ReportError(Res.Xslt_WrongStylesheetElement);
  192.                 return;
  193.             }
  194.             Debug.Assert(input.NodeType == XPathNodeType.Element);
  195.             if (input.IsXsltNamespace()) {
  196.                 if (input.IsKeyword(input.Atoms.Stylesheet) || input.IsKeyword(input.Atoms.Transform)) {
  197.                     LoadRealStylesheet();
  198.                 }
  199.                 else {
  200.                         /*[XT_002]*/                    ReportError(Res.Xslt_WrongStylesheetElement);
  201.                     input.SkipNode();
  202.                 }
  203.             }
  204.             else {
  205.                 LoadSimplifiedStylesheet();
  206.             }
  207.             input.Finish();
  208.         }
  209.        
  210.         private void LoadSimplifiedStylesheet()
  211.         {
  212.             Debug.Assert(!input.IsXsltNamespace());
  213.             Debug.Assert(curTemplate == null);
  214.            
  215.             // Prefix will be fixed later in LoadLiteralResultElement()
  216.                 /*name:*/                /*match:*/                /*mode:*/                /*priority:*/            curTemplate = f.Template(null, "/", nullMode, double.NaN, input.XslVersion);
  217.            
  218.             // This template has mode=null match="/" and no imports
  219.             input.CanHaveApplyImports = true;
  220.                 /*asStylesheet:*/            XslNode lre = LoadLiteralResultElement(true);
  221.             if (lre != null) {
  222.                 SetLineInfo(curTemplate, lre.SourceLine);
  223.                
  224.                 List<XslNode> content = new List<XslNode>();
  225.                 content.Add(lre);
  226.                 SetContent(curTemplate, content);
  227.                 if (!curStylesheet.AddTemplate(curTemplate)) {
  228.                     Debug.Fail("AddTemplate() returned false for simplified stylesheet");
  229.                 }
  230.             }
  231.             curTemplate = null;
  232.         }
  233.        
  234.         private void InsertExNamespaces(string value, ref NsDecl nsList, bool extensions)
  235.         {
  236.             if (value != null && value.Length != 0) {
  237.                 compiler.EnterForwardsCompatible();
  238.                
  239.                 string[] list = XmlConvert.SplitString(value);
  240.                 for (int idx = 0; idx < list.Length; idx++) {
  241.                     list[idx] = input.LookupXmlNamespace(list[idx] == "#default" ? string.Empty : list[idx]);
  242.                 }
  243.                
  244.                 if (!compiler.ExitForwardsCompatible(input.ForwardCompatibility)) {
  245.                     // There were errors in the list, ignore the whole list
  246.                     return;
  247.                 }
  248.                
  249.                 for (int idx = 0; idx < list.Length; idx++) {
  250.                     if (list[idx] != null) {
  251.                             /*prefix:*/                        nsList = new NsDecl(nsList, null, list[idx]);
  252.                         if (extensions) {
  253.                             input.AddExtensionNamespace(list[idx]);
  254.                         }
  255.                     }
  256.                 }
  257.             }
  258.         }
  259.        
  260.         private void LoadRealStylesheet()
  261.         {
  262.             string attVersion;
  263.             string attExtension;
  264.             string attExclude;
  265.             string attId;
  266.            
  267.             Debug.Assert(input.IsXsltNamespace() && (input.IsKeyword(input.Atoms.Stylesheet) || input.IsKeyword(input.Atoms.Transform)));
  268.             Debug.Assert(!input.ForwardCompatibility, "We shouldn't be in FC mode before we parsed stylesheet element");
  269.            
  270.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(1, input.Atoms.Version, out attVersion, input.Atoms.ExtensionElementPrefixes, out attExtension, input.Atoms.ExcludeResultPrefixes, out attExclude, input.Atoms.Id, out attId);
  271.             if (attVersion == null) {
  272.                 input.SetVersion("1.0", input.Atoms.Version);
  273.             }
  274.                 /*extensions:*/            InsertExNamespaces(attExtension, ref ctxInfo.nsList, true);
  275.                 /*extensions:*/            InsertExNamespaces(attExclude, ref ctxInfo.nsList, false);
  276.             if (attId != null) {
  277.                 // Do nothing here.
  278.             }
  279.            
  280.             string elementName = input.QualifiedName;
  281.            
  282.             // Load top level elements:
  283.             if (input.MoveToFirstChild()) {
  284.                 bool atTop = true;
  285.                 do {
  286.                     bool isImport = false;
  287.                     switch (input.NodeType) {
  288.                         case XPathNodeType.Element:
  289.                             if (input.IsXsltNamespace()) {
  290.                                 if (input.IsKeyword(input.Atoms.Import)) {
  291.                                     if (!atTop) {
  292.                                             /*[XT0200]*/                                        ReportError(Res.Xslt_NotAtTop, input.QualifiedName, elementName);
  293.                                         input.SkipNode();
  294.                                     }
  295.                                     else {
  296.                                         isImport = true;
  297.                                         LoadImport();
  298.                                     }
  299.                                 }
  300.                                 else {
  301.                                     if (input.IsKeyword(input.Atoms.Include)) {
  302.                                         LoadInclude();
  303.                                     }
  304.                                     else if (input.IsKeyword(input.Atoms.StripSpace)) {
  305.                                         LoadStripSpace(ctxInfo.nsList);
  306.                                     }
  307.                                     else if (input.IsKeyword(input.Atoms.PreserveSpace)) {
  308.                                         LoadPreserveSpace(ctxInfo.nsList);
  309.                                     }
  310.                                     else if (input.IsKeyword(input.Atoms.Output)) {
  311.                                         LoadOutput();
  312.                                     }
  313.                                     else if (input.IsKeyword(input.Atoms.Key)) {
  314.                                         LoadKey(ctxInfo.nsList);
  315.                                     }
  316.                                     else if (input.IsKeyword(input.Atoms.DecimalFormat)) {
  317.                                         LoadDecimalFormat(ctxInfo.nsList);
  318.                                     }
  319.                                     else if (input.IsKeyword(input.Atoms.NamespaceAlias)) {
  320.                                         LoadNamespaceAlias(ctxInfo.nsList);
  321.                                     }
  322.                                     else if (input.IsKeyword(input.Atoms.AttributeSet)) {
  323.                                         LoadAttributeSet(ctxInfo.nsList);
  324.                                     }
  325.                                     else if (input.IsKeyword(input.Atoms.Variable)) {
  326.                                         LoadGlobalVariableOrParameter(ctxInfo.nsList, XslNodeType.Variable);
  327.                                     }
  328.                                     else if (input.IsKeyword(input.Atoms.Param)) {
  329.                                         LoadGlobalVariableOrParameter(ctxInfo.nsList, XslNodeType.Param);
  330.                                     }
  331.                                     else if (input.IsKeyword(input.Atoms.Template)) {
  332.                                         LoadTemplate(ctxInfo.nsList);
  333.                                     }
  334.                                     else {
  335.                                         if (!input.ForwardCompatibility) {
  336.                                                 /*[XT_003]*/                                            ReportError(Res.Xslt_UnexpectedElementQ, input.QualifiedName, elementName);
  337.                                         }
  338.                                         input.SkipNode();
  339.                                     }
  340.                                 }
  341.                             }
  342.                             else if (input.IsNs(input.Atoms.UrnMsxsl) && input.IsKeyword(input.Atoms.Script)) {
  343.                                 LoadScript(ctxInfo.nsList);
  344.                             }
  345.                             else if (input.IsNullNamespace()) {
  346.                                     /*[XT0130]*/                                ReportError(Res.Xslt_NullNsAtTopLevel, input.LocalName);
  347.                                 input.SkipNode();
  348.                             }
  349.                             else {
  350.                                 // Ignoring non-recognized namespace per XSLT spec 2.2
  351.                                 input.SkipNode();
  352.                             }
  353.                             atTop = isImport;
  354.                             break;
  355.                         case XPathNodeType.Whitespace:
  356.                         case XPathNodeType.SignificantWhitespace:
  357.                            
  358.                             break;
  359.                         default:
  360.                             Debug.Assert(input.NodeType == XPathNodeType.Text);
  361.                                 /*[XT0120]*/                            ReportError(Res.Xslt_TextNodesNotAllowed, input.Atoms.Stylesheet);
  362.                             break;
  363.                     }
  364.                 }
  365.                 while (input.MoveToNextSibling());
  366.                 input.MoveToParent();
  367.             }
  368.         }
  369.        
  370.         private void LoadImport()
  371.         {
  372.             string attHref;
  373.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(1, input.Atoms.Href, out attHref);
  374.             CheckNoContent();
  375.            
  376.             if (attHref == null) {
  377.                 return;
  378.             }
  379.            
  380.             // Resolve href right away using the current BaseUri (it might change later)
  381.             Uri uri = ResolveUri(attHref, input.BaseUri);
  382.            
  383.             // Check for circular references
  384.             if (documentUriInUse.Contains(uri.ToString())) {
  385.                     /*[XT0210]*/                ReportError(Res.Xslt_CircularInclude, attHref);
  386.             }
  387.             else {
  388.                 curStylesheet.ImportHrefs.Add(uri);
  389.             }
  390.         }
  391.        
  392.         private void LoadInclude()
  393.         {
  394.             string attHref;
  395.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(1, input.Atoms.Href, out attHref);
  396.             CheckNoContent();
  397.            
  398.             if (attHref == null) {
  399.                 return;
  400.             }
  401.            
  402.             Uri uri = ResolveUri(attHref, input.BaseUri);
  403.            
  404.             // Check for circular references
  405.             if (documentUriInUse.Contains(uri.ToString())) {
  406.                     /*[XT0180]*/                ReportError(Res.Xslt_CircularInclude, attHref);
  407.             }
  408.             else {
  409.                     /*include:*/                LoadStylesheet(uri, true);
  410.             }
  411.         }
  412.        
  413.         private void LoadStripSpace(NsDecl stylesheetNsList)
  414.         {
  415.             string attElements;
  416.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(1, input.Atoms.Elements, out attElements);
  417.             ctxInfo.nsList = MergeNamespaces(ctxInfo.nsList, stylesheetNsList);
  418.            
  419.             ParseWhitespaceRules(attElements, false);
  420.             CheckNoContent();
  421.         }
  422.        
  423.         private void LoadPreserveSpace(NsDecl stylesheetNsList)
  424.         {
  425.             string attElements;
  426.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(1, input.Atoms.Elements, out attElements);
  427.             ctxInfo.nsList = MergeNamespaces(ctxInfo.nsList, stylesheetNsList);
  428.            
  429.             ParseWhitespaceRules(attElements, true);
  430.             CheckNoContent();
  431.         }
  432.        
  433.         private void LoadOutput()
  434.         {
  435.             string attMethod;
  436.             string attVersion;
  437.             string attEncoding;
  438.             string attOmitXmlDeclaration;
  439.             string attStandalone;
  440.             string attDocTypePublic;
  441.             string attDocTypeSystem;
  442.             string attCDataSectionElements;
  443.             string attIndent;
  444.             string attMediaType;
  445.            
  446.             ContextInfo ctxInfo = input.GetAttributes(0, input.Atoms.Method, out attMethod, input.Atoms.Version, out attVersion, input.Atoms.Encoding, out attEncoding, input.Atoms.OmitXmlDeclaration, out attOmitXmlDeclaration, input.Atoms.Standalone,
  447.             out attStandalone, input.Atoms.DocTypePublic, out attDocTypePublic, input.Atoms.DocTypeSystem, out attDocTypeSystem, input.Atoms.CDataSectionElements, out attCDataSectionElements, input.Atoms.Indent, out attIndent, input.Atoms.MediaType,
  448.                 /*required:*/            out attMediaType);
  449.            
  450.             Output output = compiler.Output;
  451.             XmlWriterSettings settings = output.Settings;
  452.             int currentPrec = compiler.CurrentPrecedence;
  453.             TriState triState;
  454.            
  455.             if (attMethod != null && currentPrec >= output.MethodPrec) {
  456.                 compiler.EnterForwardsCompatible();
  457.                 XmlOutputMethod outputMethod;
  458.                 XmlQualifiedName method = ParseOutputMethod(attMethod, out outputMethod);
  459.                 if (compiler.ExitForwardsCompatible(input.ForwardCompatibility) && method != null) {
  460.                     if (currentPrec == output.MethodPrec && !output.Method.Equals(method)) {
  461.                             /*[XT1560]*/                        ReportWarning(Res.Xslt_AttributeRedefinition, input.Atoms.Method);
  462.                     }
  463.                     settings.OutputMethod = outputMethod;
  464.                     output.Method = method;
  465.                     output.MethodPrec = currentPrec;
  466.                 }
  467.             }
  468.            
  469.             if (attVersion != null && currentPrec >= output.VersionPrec) {
  470.                 if (currentPrec == output.VersionPrec && output.Version != attVersion) {
  471.                         /*[XT1560]*/                    ReportWarning(Res.Xslt_AttributeRedefinition, input.Atoms.Version);
  472.                 }
  473.                 output.Version = attVersion;
  474.                 output.VersionPrec = currentPrec;
  475.             }
  476.            
  477.             if (attEncoding != null && currentPrec >= output.EncodingPrec) {
  478.                 try {
  479.                     // Encoding.GetEncoding() should never throw NotSupportedException, only ArgumentException
  480.                     Encoding encoding = Encoding.GetEncoding(attEncoding);
  481.                     if (currentPrec == output.EncodingPrec && output.Encoding != attEncoding) {
  482.                             /*[XT1560]*/                        ReportWarning(Res.Xslt_AttributeRedefinition, input.Atoms.Encoding);
  483.                     }
  484.                     settings.Encoding = encoding;
  485.                     output.Encoding = attEncoding;
  486.                     output.EncodingPrec = currentPrec;
  487.                 }
  488.                 catch (ArgumentException) {
  489.                     if (!input.ForwardCompatibility) {
  490.                             /*[XT_004]*/                        ReportWarning(Res.Xslt_InvalidEncoding, attEncoding);
  491.                     }
  492.                 }
  493.             }
  494.            
  495.             if (attOmitXmlDeclaration != null && currentPrec >= output.OmitXmlDeclarationPrec) {
  496.                 triState = ParseYesNo(attOmitXmlDeclaration, input.Atoms.OmitXmlDeclaration);
  497.                 if (triState != TriState.Unknown) {
  498.                     bool omitXmlDeclaration = (triState == TriState.True);
  499.                     if (currentPrec == output.OmitXmlDeclarationPrec && settings.OmitXmlDeclaration != omitXmlDeclaration) {
  500.                             /*[XT1560]*/                        ReportWarning(Res.Xslt_AttributeRedefinition, input.Atoms.OmitXmlDeclaration);
  501.                     }
  502.                     settings.OmitXmlDeclaration = omitXmlDeclaration;
  503.                     output.OmitXmlDeclarationPrec = currentPrec;
  504.                 }
  505.             }
  506.            
  507.             if (attStandalone != null && currentPrec >= output.StandalonePrec) {
  508.                 triState = ParseYesNo(attStandalone, input.Atoms.Standalone);
  509.                 if (triState != TriState.Unknown) {
  510.                     XmlStandalone standalone = (triState == TriState.True) ? XmlStandalone.Yes : XmlStandalone.No;
  511.                     if (currentPrec == output.StandalonePrec && settings.Standalone != standalone) {
  512.                             /*[XT1560]*/                        ReportWarning(Res.Xslt_AttributeRedefinition, input.Atoms.Standalone);
  513.                     }
  514.                     settings.Standalone = standalone;
  515.                     output.StandalonePrec = currentPrec;
  516.                 }
  517.             }
  518.            
  519.             if (attDocTypePublic != null && currentPrec >= output.DocTypePublicPrec) {
  520.                 if (currentPrec == output.DocTypePublicPrec && settings.DocTypePublic != attDocTypePublic) {
  521.                         /*[XT1560]*/                    ReportWarning(Res.Xslt_AttributeRedefinition, input.Atoms.DocTypePublic);
  522.                 }
  523.                 settings.DocTypePublic = attDocTypePublic;
  524.                 output.DocTypePublicPrec = currentPrec;
  525.             }
  526.            
  527.             if (attDocTypeSystem != null && currentPrec >= output.DocTypeSystemPrec) {
  528.                 if (currentPrec == output.DocTypeSystemPrec && settings.DocTypeSystem != attDocTypeSystem) {
  529.                         /*[XT1560]*/                    ReportWarning(Res.Xslt_AttributeRedefinition, input.Atoms.DocTypeSystem);
  530.                 }
  531.                 settings.DocTypeSystem = attDocTypeSystem;
  532.                 output.DocTypeSystemPrec = currentPrec;
  533.             }
  534.            
  535.             if (attCDataSectionElements != null && attCDataSectionElements.Length != 0) {
  536.                 // Do not check the import precedence, the effective value is the union of all specified values
  537.                 compiler.EnterForwardsCompatible();
  538.                 string[] qnames = XmlConvert.SplitString(attCDataSectionElements);
  539.                 List<XmlQualifiedName> list = new List<XmlQualifiedName>();
  540.                 for (int i = 0; i < qnames.Length; i++) {
  541.                         /*ignoreDefaultNs:*/                    list.Add(ResolveQName(false, qnames[i]));
  542.                 }
  543.                 if (compiler.ExitForwardsCompatible(input.ForwardCompatibility)) {
  544.                     output.CDataSectionElements.AddRange(list);
  545.                 }
  546.             }
  547.            
  548.             if (attIndent != null && currentPrec >= output.IndentPrec) {
  549.                 triState = ParseYesNo(attIndent, input.Atoms.Indent);
  550.                 if (triState != TriState.Unknown) {
  551.                     bool indent = (triState == TriState.True);
  552.                     if (currentPrec == output.IndentPrec && settings.Indent != indent) {
  553.                             /*[XT1560]*/                        ReportWarning(Res.Xslt_AttributeRedefinition, input.Atoms.Indent);
  554.                     }
  555.                     settings.Indent = indent;
  556.                     output.IndentPrec = currentPrec;
  557.                 }
  558.             }
  559.            
  560.             if (attMediaType != null && currentPrec >= output.MediaTypePrec) {
  561.                 if (currentPrec == output.MediaTypePrec && settings.MediaType != attMediaType) {
  562.                         /*[XT1560]*/                    ReportWarning(Res.Xslt_AttributeRedefinition, input.Atoms.MediaType);
  563.                 }
  564.                 settings.MediaType = attMediaType;
  565.                 output.MediaTypePrec = currentPrec;
  566.             }
  567.            
  568.             CheckNoContent();
  569.         }
  570.        
  571. /*
  572.             Default values for method="xml" :  version="1.0"  indent="no"    media-type="text/xml"
  573.             Default values for method="html":  version="4.0"  indent="yes"    media-type="text/html"
  574.             Default values for method="text":                                  media-type="text/plain"
  575.         */       
  576.         private void ProcessOutputSettings()
  577.         {
  578.             Output output = compiler.Output;
  579.             XmlWriterSettings settings = output.Settings;
  580.             settings.CDataSectionElements = output.CDataSectionElements;
  581.            
  582.             // version is ignored, indent="no" by default
  583.             if (settings.OutputMethod == XmlOutputMethod.Html && output.IndentPrec == Output.NeverDeclaredPrec) {
  584.                 settings.Indent = true;
  585.             }
  586.             if (output.MediaTypePrec == Output.NeverDeclaredPrec) {
  587.                 settings.MediaType = settings.OutputMethod == XmlOutputMethod.Xml ? "text/xml" : settings.OutputMethod == XmlOutputMethod.Html ? "text/html" : settings.OutputMethod == XmlOutputMethod.Text ? "text/plain" : null;
  588.             }
  589.         }
  590.        
  591.         private void AttributeSetsDfs(AttributeSet attSet)
  592.         {
  593.             Debug.Assert(attSet != null);
  594.             switch (attSet.CycleCheck) {
  595.                 case CycleCheck.NotStarted:
  596.                     attSet.CycleCheck = CycleCheck.Processing;
  597.                     foreach (QilName qname in attSet.UsedAttributeSets) {
  598.                         AttributeSet usedAttSet;
  599.                         if (!compiler.AttributeSets.TryGetValue(qname, out usedAttSet)) {
  600.                             // Prevent reporting the same error twice. The error will be reported in QilGenerator
  601.                             // while compiling this attribute set.
  602.                             //Debug.Assert(attSet.Content[0].SourceLine != null);
  603.                             //compiler.ReportError(/*[XT0710]*/attSet.Content[0].SourceLine, Res.Xslt_NoAttributeSet, qname.QualifiedName);
  604.                         }
  605.                         else {
  606.                             AttributeSetsDfs(usedAttSet);
  607.                         }
  608.                     }
  609.                     attSet.CycleCheck = CycleCheck.Completed;
  610.                     break;
  611.                 case CycleCheck.Completed:
  612.                     break;
  613.                 default:
  614.                     Debug.Assert(attSet.CycleCheck == CycleCheck.Processing);
  615.                     Debug.Assert(attSet.Content[0].SourceLine != null);
  616.                         /*[XT0720]*/                    compiler.ReportError(attSet.Content[0].SourceLine, Res.Xslt_CircularAttributeSet, attSet.Name.QualifiedName);
  617.                     break;
  618.             }
  619.         }
  620.        
  621.         private void ProcessAttributeSets()
  622.         {
  623.             // Check attribute sets for circular references using dfs marking method
  624.             foreach (AttributeSet attSet in compiler.AttributeSets.Values) {
  625.                 AttributeSetsDfs(attSet);
  626.             }
  627.         }
  628.        
  629.         private void LoadKey(NsDecl stylesheetNsList)
  630.         {
  631.             string attName;
  632.             string attMatch;
  633.             string attUse;
  634.            
  635.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(3, input.Atoms.Name, out attName, input.Atoms.Match, out attMatch, input.Atoms.Use, out attUse);
  636.             ctxInfo.nsList = MergeNamespaces(ctxInfo.nsList, stylesheetNsList);
  637.             CheckNoContent();
  638.            
  639.             QilName keyName = CreateXPathQName(attName);
  640.             Key key = (Key)SetInfo(f.Key(keyName, attMatch, attUse, input.XslVersion), null, ctxInfo);
  641.            
  642.             if (compiler.Keys.Contains(keyName)) {
  643.                 // Add to the list of previous definitions
  644.                 compiler.Keys[keyName].Add(key);
  645.             }
  646.             else {
  647.                 // First definition of key with that name
  648.                 List<Key> defList = new List<Key>();
  649.                 defList.Add(key);
  650.                 compiler.Keys.Add(defList);
  651.             }
  652.         }
  653.        
  654.         private void LoadDecimalFormat(NsDecl stylesheetNsList)
  655.         {
  656.             const int NumAttrs = 11;
  657.             const int NumCharAttrs = 8;
  658.             const int NumSignAttrs = 7;
  659.            
  660.             string[] attValues = new string[NumAttrs];
  661.             string[] attNames = new string[NumAttrs] {input.Atoms.DecimalSeparator, input.Atoms.GroupingSeparator, input.Atoms.Percent, input.Atoms.PerMille, input.Atoms.ZeroDigit, input.Atoms.Digit, input.Atoms.PatternSeparator, input.Atoms.MinusSign, input.Atoms.Infinity, input.Atoms.NaN,
  662.             input.Atoms.Name};
  663.            
  664.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(0, NumAttrs, attNames, attValues);
  665.             ctxInfo.nsList = MergeNamespaces(ctxInfo.nsList, stylesheetNsList);
  666.            
  667.             // Apply default values
  668.             char[] DefaultValues = DecimalFormatDecl.Default.Characters;
  669.             char[] characters = new char[NumCharAttrs];
  670.             Debug.Assert(NumCharAttrs == DefaultValues.Length);
  671.             int idx;
  672.            
  673.             for (idx = 0; idx < NumCharAttrs; idx++) {
  674.                 characters[idx] = ParseCharAttribute(attValues[idx], DefaultValues[idx], attNames[idx]);
  675.             }
  676.            
  677.             string attInfinity = attValues[idx++];
  678.             string attNaN = attValues[idx++];
  679.             string attName = attValues[idx++];
  680.             Debug.Assert(idx == NumAttrs);
  681.            
  682.             if (attInfinity == null) {
  683.                 attInfinity = DecimalFormatDecl.Default.InfinitySymbol;
  684.             }
  685.             if (attNaN == null) {
  686.                 attNaN = DecimalFormatDecl.Default.NanSymbol;
  687.             }
  688.            
  689.             // Check all NumSignAttrs signs are distinct
  690.             for (int i = 0; i < NumSignAttrs; i++) {
  691.                 for (int j = i + 1; j < NumSignAttrs; j++) {
  692.                     if (characters[i] == characters[j]) {
  693.                             /*[XT1300]*/                        ReportError(Res.Xslt_DecimalFormatSignsNotDistinct, attNames[i], attNames[j]);
  694.                         break;
  695.                     }
  696.                 }
  697.             }
  698.            
  699.             XmlQualifiedName name;
  700.             if (attName == null) {
  701.                 // Use name="" for the default decimal-format
  702.                 name = new XmlQualifiedName();
  703.             }
  704.             else {
  705.                 compiler.EnterForwardsCompatible();
  706.                     /*ignoreDefaultNs:*/                name = ResolveQName(true, attName);
  707.                 if (!compiler.ExitForwardsCompatible(input.ForwardCompatibility)) {
  708.                     name = new XmlQualifiedName();
  709.                 }
  710.             }
  711.            
  712.             if (compiler.DecimalFormats.Contains(name)) {
  713.                 // Check all attributes have the same values
  714.                 DecimalFormatDecl format = compiler.DecimalFormats[name];
  715.                 for (idx = 0; idx < NumCharAttrs; idx++) {
  716.                     if (characters[idx] != format.Characters[idx]) {
  717.                             /*[XT1290]*/                        ReportError(Res.Xslt_DecimalFormatRedefined, attNames[idx], char.ToString(characters[idx]));
  718.                     }
  719.                 }
  720.                 if (attInfinity != format.InfinitySymbol) {
  721.                         /*[XT1290]*/                    ReportError(Res.Xslt_DecimalFormatRedefined, attNames[idx], attInfinity);
  722.                 }
  723.                 idx++;
  724.                 if (attNaN != format.NanSymbol) {
  725.                         /*[XT1290]*/                    ReportError(Res.Xslt_DecimalFormatRedefined, attNames[idx], attNaN);
  726.                 }
  727.                 idx++;
  728.                 Debug.Assert(name.Equals(format.Name));
  729.                 idx++;
  730.                 Debug.Assert(idx == NumAttrs);
  731.             }
  732.             else {
  733.                 // Add format to the global collection
  734.                 DecimalFormatDecl format = new DecimalFormatDecl(name, attInfinity, attNaN, new string(characters));
  735.                 compiler.DecimalFormats.Add(format);
  736.             }
  737.             CheckNoContent();
  738.         }
  739.        
  740.         private void LoadNamespaceAlias(NsDecl stylesheetNsList)
  741.         {
  742.             string attStylesheetPrefix;
  743.             string attResultPrefix;
  744.            
  745.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(2, input.Atoms.StylesheetPrefix, out attStylesheetPrefix, input.Atoms.ResultPrefix, out attResultPrefix);
  746.             ctxInfo.nsList = MergeNamespaces(ctxInfo.nsList, stylesheetNsList);
  747.             CheckNoContent();
  748.            
  749.             string stylesheetNsUri = null;
  750.             string resultNsUri = null;
  751.            
  752.             if (attStylesheetPrefix == null) {
  753.                 // Attribute is missing
  754.             }
  755.             else if (attStylesheetPrefix.Length == 0) {
  756.                     /*[XT_005]*/                ReportError(Res.Xslt_EmptyNsAlias, input.Atoms.StylesheetPrefix);
  757.             }
  758.             else {
  759.                 if (attStylesheetPrefix == "#default") {
  760.                     attStylesheetPrefix = string.Empty;
  761.                 }
  762.                 stylesheetNsUri = input.LookupXmlNamespace(attStylesheetPrefix);
  763.             }
  764.            
  765.             if (attResultPrefix == null) {
  766.                 // Attribute is missing
  767.             }
  768.             else if (attResultPrefix.Length == 0) {
  769.                     /*[XT_005]*/                ReportError(Res.Xslt_EmptyNsAlias, input.Atoms.ResultPrefix);
  770.             }
  771.             else {
  772.                 if (attResultPrefix == "#default") {
  773.                     attResultPrefix = string.Empty;
  774.                 }
  775.                 resultNsUri = input.LookupXmlNamespace(attResultPrefix);
  776.             }
  777.            
  778.             if (stylesheetNsUri == null || resultNsUri == null) {
  779.                 // At least one of attributes is missing or invalid
  780.                 return;
  781.             }
  782.             if (compiler.SetNsAlias(stylesheetNsUri, resultNsUri, attResultPrefix, curStylesheet.ImportPrecedence)) {
  783.                 // Namespace alias redefinition
  784.                     /*[XT0810]*/                ReportWarning(Res.Xslt_DupNsAlias, stylesheetNsUri);
  785.             }
  786.         }
  787.        
  788.         private void LoadAttributeSet(NsDecl stylesheetNsList)
  789.         {
  790.             string attName;
  791.             string attUseAttributeSets;
  792.            
  793.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(1, input.Atoms.Name, out attName, input.Atoms.UseAttributeSets, out attUseAttributeSets);
  794.             ctxInfo.nsList = MergeNamespaces(ctxInfo.nsList, stylesheetNsList);
  795.            
  796.             QilName attSetName = CreateXPathQName(attName);
  797.             AttributeSet attSet;
  798.             if (!curStylesheet.AttributeSets.TryGetValue(attSetName, out attSet)) {
  799.                 // First definition for attSetName within this stylesheet
  800.                 curStylesheet.AttributeSets[attSetName] = attSet = f.AttributeSet(attSetName);
  801.                 if (!compiler.AttributeSets.ContainsKey(attSetName)) {
  802.                     // First definition for attSetName overall, adding it to the list here
  803.                     // to ensure stable order of prototemplate functions in QilExpression
  804.                     compiler.AllTemplates.Add(attSet);
  805.                 }
  806.             }
  807.            
  808.             List<XslNode> content = ParseUseAttributeSets(attUseAttributeSets, ctxInfo.lineInfo);
  809.             foreach (XslNode useAttSet in content) {
  810.                 Debug.Assert(useAttSet.NodeType == XslNodeType.UseAttributeSet);
  811.                 attSet.UsedAttributeSets.Add(useAttSet.Name);
  812.             }
  813.            
  814.             /* Process children */           
  815. if (input.MoveToFirstChild()) {
  816.                 do {
  817.                     switch (input.NodeType) {
  818.                         case XPathNodeType.Element:
  819.                             // Only xsl:attribute's are allowed here
  820.                             if (input.IsXsltNamespace() && input.IsKeyword(input.Atoms.Attribute)) {
  821.                                 AddInstruction(content, XslAttribute());
  822.                             }
  823.                             else {
  824.                                     /*[XT_006]*/                                ReportError(Res.Xslt_UnexpectedElement, input.QualifiedName, input.Atoms.AttributeSet);
  825.                                 input.SkipNode();
  826.                             }
  827.                             break;
  828.                         case XPathNodeType.Whitespace:
  829.                         case XPathNodeType.SignificantWhitespace:
  830.                             break;
  831.                         default:
  832.                             Debug.Assert(input.NodeType == XPathNodeType.Text);
  833.                                 /*[XT_006]*/                            ReportError(Res.Xslt_TextNodesNotAllowed, input.Atoms.AttributeSet);
  834.                             break;
  835.                     }
  836.                 }
  837.                 while (input.MoveToNextSibling());
  838.                 input.MoveToParent();
  839.             }
  840.             attSet.AddContent(SetInfo(f.List(), LoadEndTag(content), ctxInfo));
  841.         }
  842.        
  843.         private void LoadGlobalVariableOrParameter(NsDecl stylesheetNsList, XslNodeType nodeType)
  844.         {
  845.             VarPar var = XslVarPar(nodeType);
  846.             // Preserving namespaces to parse content later
  847.             var.Namespaces = MergeNamespaces(var.Namespaces, stylesheetNsList);
  848.             if (!curStylesheet.AddVarPar(var)) {
  849.                     /*[XT0630]*/                ReportError(Res.Xslt_DupGlobalVariable, var.Name.QualifiedName);
  850.             }
  851.         }
  852.        
  853.         //: http://www.w3.org/TR/xslt#section-Defining-Template-Rules
  854.         private void LoadTemplate(NsDecl stylesheetNsList)
  855.         {
  856.             Debug.Assert(curTemplate == null);
  857.             string attMatch;
  858.             string attName;
  859.             string attPriority;
  860.             string attMode;
  861.            
  862.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(0, input.Atoms.Match, out attMatch, input.Atoms.Name, out attName, input.Atoms.Priority, out attPriority, input.Atoms.Mode, out attMode);
  863.             ctxInfo.nsList = MergeNamespaces(ctxInfo.nsList, stylesheetNsList);
  864.             if (attMatch == null) {
  865.                 if (attName == null) {
  866.                         /*[XT_007]*/                    ReportError(Res.Xslt_BothMatchNameAbsent);
  867.                 }
  868.                 if (attMode != null) {
  869.                         /*[XT_008]*/                    ReportError(Res.Xslt_ModeWithoutMatch);
  870.                     attMode = null;
  871.                 }
  872.                 if (attPriority != null) {
  873.                     // In XSLT 2.0 this is an error
  874.                         /*[XT_008]*/                    ReportWarning(Res.Xslt_PriorityWithoutMatch);
  875.                 }
  876.             }
  877.            
  878.             QilName tmplName = null;
  879.             if (attName != null) {
  880.                 compiler.EnterForwardsCompatible();
  881.                 tmplName = CreateXPathQName(attName);
  882.                 if (!compiler.ExitForwardsCompatible(input.ForwardCompatibility)) {
  883.                     tmplName = null;
  884.                 }
  885.             }
  886.            
  887.             double priority = double.NaN;
  888.             if (attPriority != null) {
  889.                 priority = XPathConvert.StringToDouble(attPriority);
  890.                 if (double.IsNaN(priority) && !input.ForwardCompatibility) {
  891.                         /*[XT0530]*/                    ReportError(Res.Xslt_InvalidAttrValue, input.Atoms.Priority, attPriority);
  892.                 }
  893.             }
  894.            
  895.             curTemplate = f.Template(tmplName, attMatch, ParseMode(attMode), priority, input.XslVersion);
  896.            
  897.             // Template without match considered to not have mode and can't call xsl:apply-imports
  898.             input.CanHaveApplyImports = (attMatch != null);
  899.            
  900.             SetInfo(curTemplate, LoadEndTag(LoadInstructions(InstructionFlags.AllowParam)), ctxInfo);
  901.            
  902.             if (!curStylesheet.AddTemplate(curTemplate)) {
  903.                     /*[XT0660]*/                ReportError(Res.Xslt_DupTemplateName, curTemplate.Name.QualifiedName);
  904.             }
  905.             curTemplate = null;
  906.         }
  907.        
  908.         private void LoadScript(NsDecl stylesheetNsList)
  909.         {
  910.             string attLanguage;
  911.             string attImplementsPrefix;
  912.            
  913.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(1, input.Atoms.ImplementsPrefix, out attImplementsPrefix, input.Atoms.Language, out attLanguage);
  914.             ctxInfo.nsList = MergeNamespaces(ctxInfo.nsList, stylesheetNsList);
  915.            
  916.             string scriptNs = null;
  917.             if (attImplementsPrefix == null) {
  918.                 // Attribute is missing
  919.             }
  920.             else if (attImplementsPrefix.Length == 0) {
  921.                     /*[XT_009]*/                ReportError(Res.Xslt_EmptyAttrValue, input.Atoms.ImplementsPrefix, attImplementsPrefix);
  922.             }
  923.             else {
  924.                 scriptNs = input.LookupXmlNamespace(attImplementsPrefix);
  925.                 if (scriptNs == XmlReservedNs.NsXslt) {
  926.                         /*[XT_036]*/                    ReportError(Res.Xslt_ScriptXsltNamespace);
  927.                     scriptNs = null;
  928.                 }
  929.             }
  930.            
  931.             if (scriptNs == null) {
  932.                 scriptNs = compiler.CreatePhantomNamespace();
  933.             }
  934.             if (attLanguage == null) {
  935.                 attLanguage = "jscript";
  936.             }
  937.            
  938.             if (!compiler.Settings.EnableScript) {
  939.                 compiler.Scripts.ScriptClasses[scriptNs] = null;
  940.                 input.SkipNode();
  941.                 return;
  942.             }
  943.            
  944.             ScriptClass scriptClass;
  945.             StringBuilder scriptCode = new StringBuilder();
  946.             string uriString = input.Uri;
  947.             int lineNumber = 0;
  948.             int lastEndLine = 0;
  949.            
  950.             scriptClass = compiler.Scripts.GetScriptClass(scriptNs, attLanguage, (IErrorHelper)this);
  951.             if (scriptClass == null) {
  952.                 input.SkipNode();
  953.                 return;
  954.             }
  955.            
  956.             if (input.MoveToFirstChild()) {
  957.                 do {
  958.                     switch (input.NodeType) {
  959.                         case XPathNodeType.Text:
  960.                             int startLine = input.StartLine;
  961.                             int endLine = input.EndLine;
  962.                             if (scriptCode.Length == 0) {
  963.                                 lineNumber = startLine;
  964.                             }
  965.                             else if (lastEndLine < startLine) {
  966.                                 scriptCode.Append('\n', startLine - lastEndLine);
  967.                             }
  968.                             scriptCode.Append(input.Value);
  969.                             lastEndLine = endLine;
  970.                             break;
  971.                         case XPathNodeType.Element:
  972.                             if (input.IsNs(input.Atoms.UrnMsxsl) && (input.IsKeyword(input.Atoms.Assembly) || input.IsKeyword(input.Atoms.Using))) {
  973.                                 if (scriptCode.Length != 0) {
  974.                                         /*[XT_012]*/                                    ReportError(Res.Xslt_ScriptNotAtTop, input.QualifiedName);
  975.                                     input.SkipNode();
  976.                                 }
  977.                                 if (input.IsKeyword(input.Atoms.Assembly)) {
  978.                                     LoadMsAssembly(scriptClass);
  979.                                 }
  980.                                 else if (input.IsKeyword(input.Atoms.Using)) {
  981.                                     LoadMsUsing(scriptClass);
  982.                                 }
  983.                             }
  984.                             else {
  985.                                     /*[XT_012]*/                                ReportError(Res.Xslt_UnexpectedElementQ, input.QualifiedName, "msxsl:script");
  986.                                 input.SkipNode();
  987.                             }
  988.                             break;
  989.                         default:
  990.                             Debug.Assert(input.NodeType == XPathNodeType.SignificantWhitespace || input.NodeType == XPathNodeType.Whitespace);
  991.                             // Skip leading whitespaces
  992.                             if (scriptCode.Length != 0) {
  993.                                 goto case XPathNodeType.Text;
  994.                             }
  995.                             break;
  996.                     }
  997.                 }
  998.                 while (input.MoveToNextSibling());
  999.                 input.MoveToParent();
  1000.             }
  1001.            
  1002.             if (scriptCode.Length == 0) {
  1003.                 lineNumber = input.StartLine;
  1004.             }
  1005.             scriptClass.AddScriptBlock(scriptCode.ToString(), uriString, lineNumber, input.StartLine, input.StartPos);
  1006.         }
  1007.        
  1008.         private void LoadMsAssembly(ScriptClass scriptClass)
  1009.         {
  1010.             string attName;
  1011.             string attHref;
  1012.                 /*required:*/            input.GetAttributes(0, input.Atoms.Name, out attName, input.Atoms.Href, out attHref);
  1013.            
  1014.             string asmLocation = null;
  1015.            
  1016.             if (attName != null) {
  1017.                 if (attHref != null) {
  1018.                         /*[XT_046]*/                    ReportError(Res.Xslt_AssemblyBothNameHrefPresent);
  1019.                 }
  1020.                 else {
  1021.                     try {
  1022.                         asmLocation = Assembly.Load(attName).Location;
  1023.                     }
  1024.                     catch {
  1025.                         AssemblyName asmName = new AssemblyName(attName);
  1026.                        
  1027.                         // If the assembly is simply named, let CodeDomProvider and Fusion resolve it
  1028.                         byte[] publicKeyToken = asmName.GetPublicKeyToken();
  1029.                         if ((publicKeyToken == null || publicKeyToken.Length == 0) && asmName.Version == null) {
  1030.                             asmLocation = asmName.Name + ".dll";
  1031.                         }
  1032.                         else {
  1033.                             throw;
  1034.                         }
  1035.                     }
  1036.                 }
  1037.             }
  1038.             else if (attHref != null) {
  1039.                 asmLocation = Assembly.LoadFrom(ResolveUri(attHref, input.BaseUri).ToString()).Location;
  1040.             }
  1041.             else {
  1042.                     /*[XT_045]*/                ReportError(Res.Xslt_AssemblyBothNameHrefAbsent);
  1043.             }
  1044.            
  1045.             if (asmLocation != null) {
  1046.                 scriptClass.refAssemblies.Add(asmLocation);
  1047.             }
  1048.             CheckNoContent();
  1049.         }
  1050.        
  1051.         private void LoadMsUsing(ScriptClass scriptClass)
  1052.         {
  1053.             string attNamespace;
  1054.                 /*required:*/            input.GetAttributes(1, input.Atoms.Namespace, out attNamespace);
  1055.            
  1056.             if (attNamespace != null) {
  1057.                 scriptClass.nsImports.Add(attNamespace);
  1058.             }
  1059.             CheckNoContent();
  1060.         }
  1061.        
  1062.        
  1063.         private enum InstructionFlags
  1064.         {
  1065.             NoParamNoSort = 0,
  1066.             AllowParam = 1,
  1067.             AllowSort = 2
  1068.         }
  1069.        
  1070.         private List<XslNode> LoadInstructions()
  1071.         {
  1072.             return LoadInstructions(new List<XslNode>(), InstructionFlags.NoParamNoSort);
  1073.         }
  1074.        
  1075.         private List<XslNode> LoadInstructions(InstructionFlags flags)
  1076.         {
  1077.             return LoadInstructions(new List<XslNode>(), flags);
  1078.         }
  1079.        
  1080.         private List<XslNode> LoadInstructions(List<XslNode> content)
  1081.         {
  1082.             return LoadInstructions(content, InstructionFlags.NoParamNoSort);
  1083.         }
  1084.        
  1085.         private List<XslNode> LoadInstructions(List<XslNode> content, InstructionFlags flags)
  1086.         {
  1087.             string parentName = input.QualifiedName;
  1088.            
  1089.             if (input.MoveToFirstChild()) {
  1090.                 bool atTop = true;
  1091.                 XslNode result;
  1092.                
  1093.                 do {
  1094.                     switch (input.NodeType) {
  1095.                         case XPathNodeType.Element:
  1096.                             string nspace = input.NamespaceUri;
  1097.                             string name = input.LocalName;
  1098.                             if (nspace == input.Atoms.UriXsl) {
  1099.                                 bool error = false;
  1100.                                 if (Ref.Equal(name, input.Atoms.Param)) {
  1101.                                     if ((flags & InstructionFlags.AllowParam) == 0) {
  1102.                                             /*[XT_013]*/                                        ReportError(Res.Xslt_UnexpectedElementQ, input.QualifiedName, parentName);
  1103.                                         error = true;
  1104.                                     }
  1105.                                     else if (!atTop) {
  1106.                                         // xsl:param's must precede any other children of xsl:template
  1107.                                             /*[XT_014]*/                                        ReportError(Res.Xslt_NotAtTop, input.QualifiedName, parentName);
  1108.                                         error = true;
  1109.                                     }
  1110.                                 }
  1111.                                 else if (Ref.Equal(name, input.Atoms.Sort)) {
  1112.                                     if ((flags & InstructionFlags.AllowSort) == 0) {
  1113.                                             /*[XT_013]*/                                        ReportError(Res.Xslt_UnexpectedElementQ, input.QualifiedName, parentName);
  1114.                                         error = true;
  1115.                                     }
  1116.                                     else if (!atTop) {
  1117.                                         // xsl:sort's must precede any other children of xsl:for-each
  1118.                                             /*[XT_014]*/                                        ReportError(Res.Xslt_NotAtTop, input.QualifiedName, parentName);
  1119.                                         error = true;
  1120.                                     }
  1121.                                 }
  1122.                                 else {
  1123.                                     atTop = false;
  1124.                                 }
  1125.                                 if (error) {
  1126.                                     atTop = false;
  1127.                                     input.SkipNode();
  1128.                                     continue;
  1129.                                 }
  1130.                                     /*default:*/                                result = (Ref.Equal(name, input.Atoms.ApplyImports) ? XslApplyImports() : Ref.Equal(name, input.Atoms.ApplyTemplates) ? XslApplyTemplates() : Ref.Equal(name, input.Atoms.CallTemplate) ? XslCallTemplate() : Ref.Equal(name, input.Atoms.Copy) ? XslCopy() : Ref.Equal(name, input.Atoms.CopyOf) ? XslCopyOf() : Ref.Equal(name, input.Atoms.Fallback) ? XslFallback() : Ref.Equal(name, input.Atoms.If) ? XslIf() : Ref.Equal(name, input.Atoms.Choose) ? XslChoose() : Ref.Equal(name, input.Atoms.ForEach) ? XslForEach() : Ref.Equal(name, input.Atoms.Message) ? XslMessage() : Ref.Equal(name, input.Atoms.Number) ? XslNumber() : Ref.Equal(name, input.Atoms.ValueOf) ? XslValueOf() : Ref.Equal(name, input.Atoms.Comment) ? XslComment() : Ref.Equal(name, input.Atoms.ProcessingInstruction) ? XslProcessingInstruction() : Ref.Equal(name, input.Atoms.Text) ? XslText() : Ref.Equal(name, input.Atoms.Element) ? XslElement() : Ref.Equal(name, input.Atoms.Attribute) ? XslAttribute() : Ref.Equal(name, input.Atoms.Variable) ? XslVarPar(XslNodeType.Variable) : Ref.Equal(name, input.Atoms.Param) ? XslVarPar(XslNodeType.Param) : Ref.Equal(name, input.Atoms.Sort) ? XslSort() : LoadUnknownXsltInstruction(parentName));
  1131.                             }
  1132.                             else {
  1133.                                 atTop = false;
  1134.                                     /*asStylesheet:*/                                result = LoadLiteralResultElement(false);
  1135.                             }
  1136.                             break;
  1137.                         case XPathNodeType.SignificantWhitespace:
  1138.                             result = SetLineInfo(f.Text(input.Value), input.BuildLineInfo());
  1139.                             break;
  1140.                         case XPathNodeType.Whitespace:
  1141.                             continue;
  1142.                         default:
  1143.                             Debug.Assert(input.NodeType == XPathNodeType.Text);
  1144.                             atTop = false;
  1145.                             goto case XPathNodeType.SignificantWhitespace;
  1146.                             break;
  1147.                     }
  1148.                     AddInstruction(content, result);
  1149.                 }
  1150.                 while (input.MoveToNextSibling());
  1151.                 input.MoveToParent();
  1152.             }
  1153.             return content;
  1154.         }
  1155.        
  1156.         // http://www.w3.org/TR/xslt#apply-imports
  1157.         private XslNode XslApplyImports()
  1158.         {
  1159.             ContextInfo ctxInfo = input.GetAttributes();
  1160.             if (!input.CanHaveApplyImports) {
  1161.                     /*[XT_015]*/                ReportError(Res.Xslt_InvalidApplyImports);
  1162.                 input.SkipNode();
  1163.                 return null;
  1164.             }
  1165.            
  1166.             CheckNoContent();
  1167.                 /*Mode:*/            return SetInfo(f.ApplyImports(curTemplate.Mode, curStylesheet, input.XslVersion), null, ctxInfo);
  1168.         }
  1169.        
  1170.         // http://www.w3.org/TR/xslt#section-Applying-Template-Rules
  1171.         private XslNode XslApplyTemplates()
  1172.         {
  1173.             string attSelect;
  1174.             string attMode;
  1175.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(0, input.Atoms.Select, out attSelect, input.Atoms.Mode, out attMode);
  1176.             if (attSelect == null) {
  1177.                 attSelect = "node()";
  1178.             }
  1179.             QilName mode = ParseMode(attMode);
  1180.            
  1181.             List<XslNode> content = new List<XslNode>();
  1182.             /* Process children */           
  1183. if (input.MoveToFirstChild()) {
  1184.                 do {
  1185.                     switch (input.NodeType) {
  1186.                         case XPathNodeType.Element:
  1187.                             if (input.IsXsltNamespace()) {
  1188.                                 if (input.IsKeyword(input.Atoms.WithParam)) {
  1189.                                     XslNode withParam = XslVarPar(XslNodeType.WithParam);
  1190.                                     CheckWithParam(content, withParam);
  1191.                                     AddInstruction(content, withParam);
  1192.                                     break;
  1193.                                 }
  1194.                                 else if (input.IsKeyword(input.Atoms.Sort)) {
  1195.                                     AddInstruction(content, XslSort());
  1196.                                     break;
  1197.                                 }
  1198.                             }
  1199.                                 /*[XT_016]*/                            ReportError(Res.Xslt_UnexpectedElement, input.QualifiedName, input.Atoms.ApplyTemplates);
  1200.                             input.SkipNode();
  1201.                             break;
  1202.                         case XPathNodeType.Whitespace:
  1203.                         case XPathNodeType.SignificantWhitespace:
  1204.                             break;
  1205.                         default:
  1206.                             Debug.Assert(input.NodeType == XPathNodeType.Text);
  1207.                                 /*[XT_016]*/                            ReportError(Res.Xslt_TextNodesNotAllowed, input.Atoms.ApplyTemplates);
  1208.                             break;
  1209.                     }
  1210.                 }
  1211.                 while (input.MoveToNextSibling());
  1212.                 input.MoveToParent();
  1213.             }
  1214.            
  1215.             ctxInfo.SaveExtendedLineInfo(input);
  1216.             return SetInfo(f.ApplyTemplates(mode, attSelect, ctxInfo, input.XslVersion), content, ctxInfo);
  1217.         }
  1218.        
  1219.         // http://www.w3.org/TR/xslt#named-templates
  1220.         private XslNode XslCallTemplate()
  1221.         {
  1222.             string attName;
  1223.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(1, input.Atoms.Name, out attName);
  1224.            
  1225.             List<XslNode> content = new List<XslNode>();
  1226.             /* Process children */           
  1227. if (input.MoveToFirstChild()) {
  1228.                 do {
  1229.                     switch (input.NodeType) {
  1230.                         case XPathNodeType.Element:
  1231.                             if (input.IsXsltNamespace() && input.IsKeyword(input.Atoms.WithParam)) {
  1232.                                 XslNode withParam = XslVarPar(XslNodeType.WithParam);
  1233.                                 CheckWithParam(content, withParam);
  1234.                                 AddInstruction(content, withParam);
  1235.                             }
  1236.                             else {
  1237.                                     /*[XT_017]*/                                ReportError(Res.Xslt_UnexpectedElement, input.QualifiedName, input.Atoms.CallTemplate);
  1238.                                 input.SkipNode();
  1239.                             }
  1240.                             break;
  1241.                         case XPathNodeType.Whitespace:
  1242.                         case XPathNodeType.SignificantWhitespace:
  1243.                             break;
  1244.                         default:
  1245.                             Debug.Assert(input.NodeType == XPathNodeType.Text);
  1246.                                 /*[XT_017]*/                            ReportError(Res.Xslt_TextNodesNotAllowed, input.Atoms.CallTemplate);
  1247.                             break;
  1248.                     }
  1249.                 }
  1250.                 while (input.MoveToNextSibling());
  1251.                 input.MoveToParent();
  1252.             }
  1253.            
  1254.             ctxInfo.SaveExtendedLineInfo(input);
  1255.             return SetInfo(f.CallTemplate(CreateXPathQName(attName), ctxInfo), content, ctxInfo);
  1256.         }
  1257.        
  1258.         private XslNode XslCopy()
  1259.         {
  1260.             string attUseAttributeSets;
  1261.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(0, input.Atoms.UseAttributeSets, out attUseAttributeSets);
  1262.            
  1263.             List<XslNode> content = ParseUseAttributeSets(attUseAttributeSets, ctxInfo.lineInfo);
  1264.             return SetInfo(f.Copy(), LoadEndTag(LoadInstructions(content)), ctxInfo);
  1265.         }
  1266.        
  1267.         private XslNode XslCopyOf()
  1268.         {
  1269.             string attSelect;
  1270.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(1, input.Atoms.Select, out attSelect);
  1271.            
  1272.             CheckNoContent();
  1273.             return SetInfo(f.CopyOf(attSelect, input.XslVersion), null, ctxInfo);
  1274.         }
  1275.        
  1276.         // http://www.w3.org/TR/xslt#fallback
  1277.         // See LoadFallbacks() for real fallback implementation
  1278.         private XslNode XslFallback()
  1279.         {
  1280.             input.GetAttributes();
  1281.             input.SkipNode();
  1282.             return null;
  1283.         }
  1284.        
  1285.         private XslNode XslIf()
  1286.         {
  1287.             string attTest;
  1288.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(1, input.Atoms.Test, out attTest);
  1289.            
  1290.             return SetInfo(f.If(attTest, input.XslVersion), LoadInstructions(), ctxInfo);
  1291.         }
  1292.        
  1293.         private XslNode XslChoose()
  1294.         {
  1295.             ContextInfo ctxInfo = input.GetAttributes();
  1296.            
  1297.             List<XslNode> content = new List<XslNode>();
  1298.             bool otherwise = false;
  1299.             bool when = false;
  1300.            
  1301.             if (input.MoveToFirstChild()) {
  1302.                 do {
  1303.                     switch (input.NodeType) {
  1304.                         case XPathNodeType.Element:
  1305.                             XslNode node = null;
  1306.                             if (Ref.Equal(input.NamespaceUri, input.Atoms.UriXsl)) {
  1307.                                 if (Ref.Equal(input.LocalName, input.Atoms.When)) {
  1308.                                     if (otherwise) {
  1309.                                             /*[XT_018]*/                                        ReportError(Res.Xslt_WhenAfterOtherwise);
  1310.                                         input.SkipNode();
  1311.                                         continue;
  1312.                                     }
  1313.                                     else {
  1314.                                         when = true;
  1315.                                         node = XslIf();
  1316.                                     }
  1317.                                 }
  1318.                                 else if (Ref.Equal(input.LocalName, input.Atoms.Otherwise)) {
  1319.                                     if (otherwise) {
  1320.                                             /*[XT_019]*/                                        ReportError(Res.Xslt_DupOtherwise);
  1321.                                         input.SkipNode();
  1322.                                         continue;
  1323.                                     }
  1324.                                     else {
  1325.                                         otherwise = true;
  1326.                                         node = XslOtherwise();
  1327.                                     }
  1328.                                 }
  1329.                             }
  1330.                             if (node == null) {
  1331.                                     /*[XT_020]*/                                ReportError(Res.Xslt_UnexpectedElement, input.QualifiedName, input.Atoms.Choose);
  1332.                                 input.SkipNode();
  1333.                                 continue;
  1334.                             }
  1335.                             AddInstruction(content, node);
  1336.                             break;
  1337.                         case XPathNodeType.Whitespace:
  1338.                         case XPathNodeType.SignificantWhitespace:
  1339.                             break;
  1340.                         default:
  1341.                             Debug.Assert(input.NodeType == XPathNodeType.Text);
  1342.                                 /*[XT_020]*/                            ReportError(Res.Xslt_TextNodesNotAllowed, input.Atoms.Choose);
  1343.                             break;
  1344.                     }
  1345.                 }
  1346.                 while (input.MoveToNextSibling());
  1347.                 input.MoveToParent();
  1348.             }
  1349.             if (!when) {
  1350.                     /*[XT_021]*/                ReportError(Res.Xslt_NoWhen);
  1351.             }
  1352.             return SetInfo(f.Choose(), content, ctxInfo);
  1353.         }
  1354.        
  1355.         private XslNode XslOtherwise()
  1356.         {
  1357.             ContextInfo ctxInfo = input.GetAttributes();
  1358.             return SetInfo(f.Otherwise(), LoadInstructions(), ctxInfo);
  1359.         }
  1360.        
  1361.         private XslNode XslForEach()
  1362.         {
  1363.             string attSelect;
  1364.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(1, input.Atoms.Select, out attSelect);
  1365.            
  1366.             // The current template rule becomes null, so we must not allow xsl:apply-import's within this element
  1367.             input.CanHaveApplyImports = false;
  1368.             List<XslNode> content = LoadInstructions(InstructionFlags.AllowSort);
  1369.             ctxInfo.SaveExtendedLineInfo(input);
  1370.            
  1371.             return SetInfo(f.ForEach(attSelect, ctxInfo, input.XslVersion), content, ctxInfo);
  1372.         }
  1373.        
  1374.         // http://www.w3.org/TR/xslt#message
  1375.         private XslNode XslMessage()
  1376.         {
  1377.             string attTerminate;
  1378.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(0, input.Atoms.Terminate, out attTerminate);
  1379.            
  1380.                 /*attName:*/            bool terminate = ParseYesNo(attTerminate, input.Atoms.Terminate) == TriState.True;
  1381.             return SetInfo(f.Message(terminate), LoadEndTag(LoadInstructions()), ctxInfo);
  1382.         }
  1383.        
  1384.         // http://www.w3.org/TR/xslt#number
  1385.         private XslNode XslNumber()
  1386.         {
  1387.             string attLevel;
  1388.             string attCount;
  1389.             string attFrom;
  1390.             string attValue;
  1391.             string attFormat;
  1392.             string attLang;
  1393.             string attLetterValue;
  1394.             string attGroupingSeparator;
  1395.             string attGroupingSize;
  1396.            
  1397.             ContextInfo ctxInfo = input.GetAttributes(0, input.Atoms.Level, out attLevel, input.Atoms.Count, out attCount, input.Atoms.From, out attFrom, input.Atoms.Value, out attValue, input.Atoms.Format,
  1398.                 /*required:*/            out attFormat, input.Atoms.Lang, out attLang, input.Atoms.LetterValue, out attLetterValue, input.Atoms.GroupingSeparator, out attGroupingSeparator, input.Atoms.GroupingSize, out attGroupingSize);
  1399.            
  1400.             // Default values for xsl:number : level="single" format="1"
  1401.             NumberLevel level;
  1402.            
  1403.             switch (attLevel) {
  1404.                 case "single":
  1405.                     level = NumberLevel.Single;
  1406.                     break;
  1407.                 case "multiple":
  1408.                     level = NumberLevel.Multiple;
  1409.                     break;
  1410.                 case "any":
  1411.                     level = NumberLevel.Any;
  1412.                     break;
  1413.                 default:
  1414.                     if (attLevel != null && !input.ForwardCompatibility) {
  1415.                             /*[XT_022]*/                        ReportError(Res.Xslt_InvalidAttrValue, input.Atoms.Level, attLevel);
  1416.                     }
  1417.                     goto case "single";
  1418.                     break;
  1419.             }
  1420.            
  1421.             if (attFormat == null) {
  1422.                 attFormat = "1";
  1423.             }
  1424.            
  1425.             CheckNoContent();
  1426.             return SetInfo(f.Number(level, attCount, attFrom, attValue, attFormat, attLang, attLetterValue, attGroupingSeparator, attGroupingSize, input.XslVersion
  1427.             ), null, ctxInfo);
  1428.         }
  1429.        
  1430.         // http://www.w3.org/TR/xslt#value-of
  1431.         private XslNode XslValueOf()
  1432.         {
  1433.             string attSelect;
  1434.             string attDisableOutputEscaping;
  1435.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(1, input.Atoms.Select, out attSelect, input.Atoms.DisableOutputEscaping, out attDisableOutputEscaping);
  1436.            
  1437.                 /*attName:*/            bool doe = ParseYesNo(attDisableOutputEscaping, input.Atoms.DisableOutputEscaping) == TriState.True;
  1438.            
  1439.             CheckNoContent();
  1440.             return SetInfo(f.XslNode(doe ? XslNodeType.ValueOfDoe : XslNodeType.ValueOf, null, attSelect, input.XslVersion), null, ctxInfo);
  1441.         }
  1442.        
  1443.         // xsl:variable http://www.w3.org/TR/xslt#local-variables
  1444.         // xsl:param http://www.w3.org/TR/xslt#element-param
  1445.         // xsl:with-param http://www.w3.org/TR/xslt#element-with-param
  1446.         private VarPar XslVarPar(XslNodeType nodeType)
  1447.         {
  1448.             Debug.Assert(nodeType == XslNodeType.Variable && input.LocalName == input.Atoms.Variable || nodeType == XslNodeType.Param && input.LocalName == input.Atoms.Param || nodeType == XslNodeType.WithParam && input.LocalName == input.Atoms.WithParam);
  1449.             string attName;
  1450.             string attSelect;
  1451.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(1, input.Atoms.Name, out attName, input.Atoms.Select, out attSelect);
  1452.            
  1453.             List<XslNode> content = LoadInstructions();
  1454.             // Load the end tag only if the content is not empty
  1455.             if (content.Count != 0) {
  1456.                 content = LoadEndTag(content);
  1457.             }
  1458.            
  1459.             if (attSelect != null && content.Count != 0) {
  1460.                     /*[XT0620]*/                ReportError(Res.Xslt_VariableCntSel2, attName);
  1461.             }
  1462.            
  1463.             VarPar result = f.VarPar(nodeType, CreateXPathQName(attName), attSelect, input.XslVersion);
  1464.             SetInfo(result, content, ctxInfo);
  1465.             return result;
  1466.         }
  1467.        
  1468.         // http://www.w3.org/TR/xslt#section-Creating-Comments
  1469.         private XslNode XslComment()
  1470.         {
  1471.             ContextInfo ctxInfo = input.GetAttributes();
  1472.             return SetInfo(f.Comment(), LoadEndTag(LoadInstructions()), ctxInfo);
  1473.         }
  1474.        
  1475.         // http://www.w3.org/TR/xslt#section-Creating-Processing-Instructions
  1476.         private XslNode XslProcessingInstruction()
  1477.         {
  1478.             string attName;
  1479.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(1, input.Atoms.Name, out attName);
  1480.             if (attName == null) {
  1481.                 attName = compiler.PhantomNCName;
  1482.             }
  1483.             return SetInfo(f.PI(attName, input.XslVersion), LoadEndTag(LoadInstructions()), ctxInfo);
  1484.         }
  1485.        
  1486.         // http://www.w3.org/TR/xslt#section-Creating-Text
  1487.         private XslNode XslText()
  1488.         {
  1489.             string attDisableOutputEscaping;
  1490.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(0, input.Atoms.DisableOutputEscaping, out attDisableOutputEscaping);
  1491.            
  1492.                 /*attName:*/            bool doe = ParseYesNo(attDisableOutputEscaping, input.Atoms.DisableOutputEscaping) == TriState.True;
  1493.             SerializationHints hints = doe ? SerializationHints.DisableOutputEscaping : SerializationHints.None;
  1494.            
  1495.             // We are not using StringBuilder here because in most cases there will be just one text node.
  1496.             List<XslNode> content = new List<XslNode>();
  1497.            
  1498.             // xsl:text may contain multiple child text nodes separated by comments and PIs, which are ignored by XsltInput
  1499.             if (input.MoveToFirstChild()) {
  1500.                 do {
  1501.                     switch (input.NodeType) {
  1502.                         case XPathNodeType.Text:
  1503.                         case XPathNodeType.Whitespace:
  1504.                         case XPathNodeType.SignificantWhitespace:
  1505.                             content.Add(f.Text(input.Value, hints));
  1506.                             break;
  1507.                         default:
  1508.                             Debug.Assert(input.NodeType == XPathNodeType.Element);
  1509.                                 /*[XT_023]*/                            ReportError(Res.Xslt_UnexpectedElement, input.QualifiedName, input.Atoms.Text);
  1510.                             input.SkipNode();
  1511.                             break;
  1512.                     }
  1513.                 }
  1514.                 while (input.MoveToNextSibling());
  1515.                 input.MoveToParent();
  1516.             }
  1517.            
  1518.             // Empty xsl:text elements will be ignored
  1519.             return SetInfo(f.List(), content, ctxInfo);
  1520.         }
  1521.        
  1522.         // http://www.w3.org/TR/xslt#section-Creating-Elements-with-xsl:element
  1523.         private XslNode XslElement()
  1524.         {
  1525.             string attName;
  1526.             string attNamespace;
  1527.             string attUseAttributeSets;
  1528.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(1, input.Atoms.Name, out attName, input.Atoms.Namespace, out attNamespace, input.Atoms.UseAttributeSets, out attUseAttributeSets);
  1529.            
  1530.             if (attName == null) {
  1531.                 attName = compiler.PhantomNCName;
  1532.             }
  1533.             if (attNamespace == XmlReservedNs.NsXmlNs) {
  1534.                     /*[XT_024]*/                ReportError(Res.Xslt_ReservedNS, attNamespace);
  1535.             }
  1536.             List<XslNode> content = ParseUseAttributeSets(attUseAttributeSets, ctxInfo.lineInfo);
  1537.             return SetInfo(f.Element(attName, attNamespace, input.XslVersion), LoadEndTag(LoadInstructions(content)), ctxInfo);
  1538.         }
  1539.        
  1540.         // http://www.w3.org/TR/xslt#creating-attributes
  1541.         private XslNode XslAttribute()
  1542.         {
  1543.             string attName;
  1544.             string attNamespace;
  1545.                 /*required:*/            ContextInfo ctxInfo = input.GetAttributes(1, input.Atoms.Name, out attName, input.Atoms.Namespace, out attNamespace);
  1546.            
  1547.             if (attName == null) {
  1548.                 attName = compiler.PhantomNCName;
  1549.             }
  1550.             if (attNamespace == XmlReservedNs.NsXmlNs) {
  1551.                     /*[XT_024]*/                ReportError(Res.Xslt_ReservedNS, attNamespace);
  1552.             }
  1553.             return SetInfo(f.Attribute(attName, attNamespace, input.XslVersion), LoadEndTag(LoadInstructions()), ctxInfo);
  1554.         }
  1555.        
  1556.         // http://www.w3.org/TR/xslt#sorting
  1557.         private XslNode XslSort()
  1558.         {
  1559.             string attSelect;
  1560.             string attLang;
  1561.             string attDataType;
  1562.             string attOrder;
  1563.             string attCaseOrder;
  1564.             ContextInfo ctxInfo = input.GetAttributes(0, input.Atoms.Select, out attSelect, input.Atoms.Lang, out attLang, input.Atoms.DataType, out attDataType, input.Atoms.Order, out attOrder, input.Atoms.CaseOrder,
  1565.                 /*required:*/            out attCaseOrder);
  1566.            
  1567.             if (attSelect == null) {
  1568.                 attSelect = ".";
  1569.             }
  1570.             CheckNoContent();
  1571.             return SetInfo(f.Sort(attSelect, attLang, attDataType, attOrder, attCaseOrder, input.XslVersion), null, ctxInfo);
  1572.         }
  1573.        
  1574.         // http://www.w3.org/TR/xslt#literal-result-element
  1575.         private XslNode LoadLiteralResultElement(bool asStylesheet)
  1576.         {
  1577.             Debug.Assert(input.NodeType == XPathNodeType.Element);
  1578.             string prefix = input.Prefix;
  1579.             string name = input.LocalName;
  1580.             string nsUri = input.NamespaceUri;
  1581.            
  1582.             string version = null;
  1583.             string extPrefixes = null;
  1584.             string exclPrefixes = null;
  1585.             string useAttrSets = null;
  1586.             string versionQName = null;
  1587.            
  1588.             List<XslNode> content = new List<XslNode>();
  1589.             ContextInfo ctxInfo = new ContextInfo(input);
  1590.            
  1591.             /* Process literal attributes */           
  1592. while (input.MoveToNextAttOrNs()) {
  1593.                 if (input.NodeType == XPathNodeType.Namespace) {
  1594.                     ctxInfo.AddNamespace(input);
  1595.                 }
  1596.                 else {
  1597.                     Debug.Assert(input.NodeType == XPathNodeType.Attribute);
  1598.                     ctxInfo.AddAttribute(input);
  1599.                     if (input.IsXsltNamespace()) {
  1600.                         if (input.LocalName == input.Atoms.Version) {
  1601.                             version = input.Value;
  1602.                             versionQName = input.QualifiedName;
  1603.                         }
  1604.                         else if (input.LocalName == input.Atoms.ExtensionElementPrefixes) {
  1605.                             extPrefixes = input.Value;
  1606.                         }
  1607.                         else if (input.LocalName == input.Atoms.ExcludeResultPrefixes) {
  1608.                             exclPrefixes = input.Value;
  1609.                         }
  1610.                         else if (input.LocalName == input.Atoms.UseAttributeSets) {
  1611.                             useAttrSets = input.Value;
  1612.                         }
  1613.                         else {
  1614.                             // just ignore it
  1615.                         }
  1616.                     }
  1617.                     else {
  1618.                         XslNode att = f.LiteralAttribute(f.QName(input.LocalName, input.NamespaceUri, input.Prefix), input.Value, input.XslVersion);
  1619.                         // QilGenerator takes care of AVTs, and needs line info
  1620.                         AddInstruction(content, SetLineInfo(att, ctxInfo.lineInfo));
  1621.                     }
  1622.                 }
  1623.             }
  1624.             ctxInfo.Finish(input);
  1625.            
  1626.             if (version != null) {
  1627.                 // Enable forwards-compatible behavior if version attribute is not "1.0"
  1628.                 input.SetVersion(version, versionQName);
  1629.             }
  1630.             else {
  1631.                 if (asStylesheet) {
  1632.                     if (Ref.Equal(nsUri, input.Atoms.UriWdXsl) && Ref.Equal(name, input.Atoms.Stylesheet)) {
  1633.                             /*[XT_025]*/                        ReportError(Res.Xslt_WdXslNamespace);
  1634.                     }
  1635.                     else {
  1636.                             /*[XT0150]*/                        ReportError(Res.Xslt_WrongStylesheetElement);
  1637.                     }
  1638.                     input.SkipNode();
  1639.                     return null;
  1640.                 }
  1641.             }
  1642.            
  1643.             // Parse xsl:extension-element-prefixes attribute (now that forwards-compatible mode is known)
  1644.                 /*extensions:*/            InsertExNamespaces(extPrefixes, ref ctxInfo.nsList, true);
  1645.            
  1646.             XslNode result;
  1647.            
  1648.             // Now we can determine whether this element is an extension element (spec section 14.1)
  1649.             if (input.IsExtensionNamespace(nsUri)) {
  1650.                 // This is not a literal result element, so drop all attributes we have collected
  1651.                 content = LoadFallbacks(name);
  1652.                 result = f.List();
  1653.             }
  1654.             else {
  1655.                 // Parse xsl:exclude-result-prefixes attribute (now that it's known this is a literal result element)
  1656.                     /*extensions:*/                InsertExNamespaces(exclPrefixes, ref ctxInfo.nsList, false);
  1657.                
  1658.                 // Insert all attribute sets at the beginning of content
  1659.                 content.InsertRange(0, ParseUseAttributeSets(useAttrSets, ctxInfo.lineInfo));
  1660.                
  1661.                 content = LoadEndTag(LoadInstructions(content));
  1662.                 result = f.LiteralElement(f.QName(name, nsUri, prefix));
  1663.             }
  1664.            
  1665.             return SetInfo(result, content, ctxInfo);
  1666.         }
  1667.        
  1668.         private void CheckWithParam(List<XslNode> content, XslNode withParam)
  1669.         {
  1670.             Debug.Assert(content != null && withParam != null);
  1671.             Debug.Assert(withParam.NodeType == XslNodeType.WithParam);
  1672.             foreach (XslNode node in content) {
  1673.                 if (node.NodeType == XslNodeType.WithParam && node.Name.Equals(withParam.Name)) {
  1674.                         /*[XT0670]*/                    ReportError(Res.Xslt_DuplicateWithParam, withParam.Name.QualifiedName);
  1675.                     break;
  1676.                 }
  1677.             }
  1678.         }
  1679.        
  1680.         private static void AddInstruction(List<XslNode> content, XslNode instruction)
  1681.         {
  1682.             Debug.Assert(content != null);
  1683.             if (instruction != null) {
  1684.                 content.Add(instruction);
  1685.             }
  1686.         }
  1687.        
  1688.         private List<XslNode> LoadEndTag(List<XslNode> content)
  1689.         {
  1690.             Debug.Assert(content != null);
  1691.             if (compiler.IsDebug && !input.IsEmptyElement) {
  1692.                 AddInstruction(content, SetLineInfo(f.Nop(), input.BuildLineInfo()));
  1693.             }
  1694.             return content;
  1695.         }
  1696.        
  1697.         private XslNode LoadUnknownXsltInstruction(string parentName)
  1698.         {
  1699.             if (!input.ForwardCompatibility) {
  1700.                     /*[XT_026]*/                ReportError(Res.Xslt_UnexpectedElementQ, input.QualifiedName, parentName);
  1701.                 input.SkipNode();
  1702.                 return null;
  1703.             }
  1704.             else {
  1705.                 ContextInfo ctxInfo = input.GetAttributes();
  1706.                 List<XslNode> fallbacks = LoadFallbacks(input.LocalName);
  1707.                 return SetInfo(f.List(), fallbacks, ctxInfo);
  1708.             }
  1709.         }
  1710.        
  1711.         private List<XslNode> LoadFallbacks(string instrName)
  1712.         {
  1713.             List<XslNode> fallbacksArray = new List<XslNode>();
  1714.             /* Process children */           
  1715. if (input.MoveToFirstChild()) {
  1716.                 do {
  1717.                     if (Ref.Equal(input.NamespaceUri, input.Atoms.UriXsl) && Ref.Equal(input.LocalName, input.Atoms.Fallback)) {
  1718.                         ContextInfo ctxInfo = input.GetAttributes();
  1719.                         fallbacksArray.Add(SetInfo(f.List(), LoadInstructions(), ctxInfo));
  1720.                     }
  1721.                     else {
  1722.                         input.SkipNode();
  1723.                     }
  1724.                 }
  1725.                 while (input.MoveToNextSibling());
  1726.                 input.MoveToParent();
  1727.             }
  1728.            
  1729.             // Generate runtime error if there is no fallbacks
  1730.             if (fallbacksArray.Count == 0) {
  1731.                 fallbacksArray.Add(f.Error(XslLoadException.CreateMessage(input.BuildLineInfo(), Res.Xslt_UnknownExtensionElement, instrName)));
  1732.             }
  1733.             return fallbacksArray;
  1734.         }
  1735.        
  1736.         // ------------------ little helper methods ---------------------
  1737.        
  1738.         // Suppresses errors if FCB is enabled
  1739.         private QilName ParseMode(string qname)
  1740.         {
  1741.             if (qname == null) {
  1742.                 return nullMode;
  1743.             }
  1744.             // mode is always optional attribute
  1745.             compiler.EnterForwardsCompatible();
  1746.             QilName mode = CreateXPathQName(qname);
  1747.             if (!compiler.ExitForwardsCompatible(input.ForwardCompatibility)) {
  1748.                 mode = nullMode;
  1749.             }
  1750.             return mode;
  1751.         }
  1752.        
  1753.         // Does not suppress errors
  1754.         private void ResolveQName(bool ignoreDefaultNs, string qname, out string localName, out string namespaceName, out string prefix)
  1755.         {
  1756.             if (qname == null) {
  1757.                 // That means stylesheet is incorrect
  1758.                 prefix = compiler.PhantomNCName;
  1759.                 localName = compiler.PhantomNCName;
  1760.                 namespaceName = compiler.CreatePhantomNamespace();
  1761.                 return;
  1762.             }
  1763.             if (!compiler.ParseQName(qname, out prefix, out localName, (IErrorHelper)this)) {
  1764.                 namespaceName = compiler.CreatePhantomNamespace();
  1765.                 return;
  1766.             }
  1767.             if (ignoreDefaultNs && prefix.Length == 0) {
  1768.                 namespaceName = string.Empty;
  1769.             }
  1770.             else {
  1771.                 namespaceName = input.LookupXmlNamespace(prefix);
  1772.                 if (namespaceName == null) {
  1773.                     namespaceName = compiler.CreatePhantomNamespace();
  1774.                 }
  1775.             }
  1776.         }
  1777.        
  1778.         // Does not suppress errors
  1779.         private QilName CreateXPathQName(string qname)
  1780.         {
  1781.             string prefix;
  1782.             string localName;
  1783.             string namespaceName;
  1784.                 /*ignoreDefaultNs:*/            ResolveQName(true, qname, out localName, out namespaceName, out prefix);
  1785.             return f.QName(localName, namespaceName, prefix);
  1786.         }
  1787.        
  1788.         // Does not suppress errors
  1789.         private XmlQualifiedName ResolveQName(bool ignoreDefaultNs, string qname)
  1790.         {
  1791.             string prefix;
  1792.             string localName;
  1793.             string namespaceName;
  1794.             ResolveQName(ignoreDefaultNs, qname, out localName, out namespaceName, out prefix);
  1795.             return new XmlQualifiedName(localName, namespaceName);
  1796.         }
  1797.        
  1798.         // Does not suppress errors
  1799.         private void ParseWhitespaceRules(string elements, bool preserveSpace)
  1800.         {
  1801.             if (elements != null && elements.Length != 0) {
  1802.                 string[] tokens = XmlConvert.SplitString(elements);
  1803.                 for (int i = 0; i < tokens.Length; i++) {
  1804.                     string prefix;
  1805.                     string localName;
  1806.                     string namespaceName;
  1807.                     if (!compiler.ParseNameTest(tokens[i], out prefix, out localName, (IErrorHelper)this)) {
  1808.                         namespaceName = compiler.CreatePhantomNamespace();
  1809.                     }
  1810.                     else if (prefix == null || prefix.Length == 0) {
  1811.                         namespaceName = prefix;
  1812.                     }
  1813.                     else {
  1814.                         namespaceName = input.LookupXmlNamespace(prefix);
  1815.                         if (namespaceName == null) {
  1816.                             namespaceName = compiler.CreatePhantomNamespace();
  1817.                         }
  1818.                     }
  1819.                     int index = ((localName == null ? 1 : 0) + (namespaceName == null ? 1 : 0));
  1820.                     curStylesheet.AddWhitespaceRule(index, new WhitespaceRule(localName, namespaceName, preserveSpace));
  1821.                 }
  1822.             }
  1823.         }
  1824.        
  1825.         // Does not suppress errors. In case of error, null is returned.
  1826.         private XmlQualifiedName ParseOutputMethod(string attValue, out XmlOutputMethod method)
  1827.         {
  1828.             string prefix;
  1829.             string localName;
  1830.             string namespaceName;
  1831.                 /*ignoreDefaultNs:*/            ResolveQName(true, attValue, out localName, out namespaceName, out prefix);
  1832.             method = XmlOutputMethod.AutoDetect;
  1833.            
  1834.             if (compiler.IsPhantomNamespace(namespaceName)) {
  1835.                 return null;
  1836.             }
  1837.             else if (prefix.Length == 0) {
  1838.                 switch (localName) {
  1839.                     case "xml":
  1840.                         method = XmlOutputMethod.Xml;
  1841.                         break;
  1842.                     case "html":
  1843.                         method = XmlOutputMethod.Html;
  1844.                         break;
  1845.                     case "text":
  1846.                         method = XmlOutputMethod.Text;
  1847.                         break;
  1848.                     default:
  1849.                             /*[XT1570]*/                        ReportError(Res.Xslt_InvalidAttrValue, input.Atoms.Method, attValue);
  1850.                         return null;
  1851.                 }
  1852.             }
  1853.             else {
  1854.                 if (!input.ForwardCompatibility) {
  1855.                         /*[XT1570]*/                    ReportWarning(Res.Xslt_InvalidMethod, attValue);
  1856.                 }
  1857.             }
  1858.             return new XmlQualifiedName(localName, namespaceName);
  1859.         }
  1860.        
  1861.         // Suppresses errors if FCB is enabled
  1862.         private List<XslNode> ParseUseAttributeSets(string useAttributeSets, ISourceLineInfo lineInfo)
  1863.         {
  1864.             List<XslNode> result = new List<XslNode>();
  1865.             if (useAttributeSets != null && useAttributeSets.Length != 0) {
  1866.                 compiler.EnterForwardsCompatible();
  1867.                
  1868.                 string[] qnames = XmlConvert.SplitString(useAttributeSets);
  1869.                 for (int idx = 0; idx < qnames.Length; idx++) {
  1870.                     AddInstruction(result, SetLineInfo(f.UseAttributeSet(CreateXPathQName(qnames[idx])), lineInfo));
  1871.                 }
  1872.                
  1873.                 if (!compiler.ExitForwardsCompatible(input.ForwardCompatibility)) {
  1874.                     // There were errors in the list, ignore the whole list
  1875.                     result = new List<XslNode>();
  1876.                 }
  1877.             }
  1878.             return result;
  1879.         }
  1880.        
  1881.         // Suppresses errors if FCB is enabled
  1882.         private TriState ParseYesNo(string val, string attName)
  1883.         {
  1884.             switch (val) {
  1885.                 case null:
  1886.                     return TriState.Unknown;
  1887.                 case "yes":
  1888.                     return TriState.True;
  1889.                 case "no":
  1890.                     return TriState.False;
  1891.                 default:
  1892.                     if (!input.ForwardCompatibility) {
  1893.                             /*[XT_028]*/                        ReportError(Res.Xslt_BistateAttribute, attName, "yes", "no");
  1894.                     }
  1895.                     return TriState.Unknown;
  1896.             }
  1897.         }
  1898.        
  1899.         // Suppresses errors if FCB is enabled
  1900.         private char ParseCharAttribute(string attValue, char defaultValue, string attName)
  1901.         {
  1902.             if (attValue == null) {
  1903.                 return defaultValue;
  1904.             }
  1905.             else if (attValue.Length != 1) {
  1906.                 if (!input.ForwardCompatibility) {
  1907.                         /*[XT_029]*/                    ReportError(Res.Xslt_CharAttribute, attName);
  1908.                 }
  1909.                 return defaultValue;
  1910.             }
  1911.             return attValue[0];
  1912.         }
  1913.        
  1914.         private void CheckNoContent()
  1915.         {
  1916.             string elementName = input.QualifiedName;
  1917.             bool error = false;
  1918.            
  1919.             // Really EMPTY means no content at all, but for the sake of compatibility with MSXML we allow whitespaces
  1920.             if (input.MoveToFirstChild()) {
  1921.                 do {
  1922.                     // NOTE: XPathNodeType.SignificantWhitespace are not allowed here
  1923.                     if (input.NodeType != XPathNodeType.Whitespace) {
  1924.                         if (!error) {
  1925.                                 /*[XT0260]*/                            ReportError(Res.Xslt_NotEmptyContents, elementName);
  1926.                             error = true;
  1927.                         }
  1928.                         input.SkipNode();
  1929.                     }
  1930.                 }
  1931.                 while (input.MoveToNextSibling());
  1932.                 input.MoveToParent();
  1933.             }
  1934.         }
  1935.        
  1936.         private static XslNode SetLineInfo(XslNode node, ISourceLineInfo lineInfo)
  1937.         {
  1938.             Debug.Assert(node != null);
  1939.             node.SourceLine = lineInfo;
  1940.             return node;
  1941.         }
  1942.        
  1943.         private static void SetContent(XslNode node, List<XslNode> content)
  1944.         {
  1945.             Debug.Assert(node != null);
  1946.             if (content != null && content.Count == 0) {
  1947.                 content = null;
  1948.                 // Actualy we can reuse this ArayList.
  1949.             }
  1950.             node.SetContent(content);
  1951.         }
  1952.        
  1953.         private static XslNode SetInfo(XslNode to, List<XslNode> content, ContextInfo info)
  1954.         {
  1955.             Debug.Assert(to != null);
  1956.             to.Namespaces = info.nsList;
  1957.             SetContent(to, content);
  1958.             SetLineInfo(to, info.lineInfo);
  1959.             return to;
  1960.         }
  1961.        
  1962.         // NOTE! We inverting namespace order that is irelevant for namespace of the same node, but
  1963.         // for included styleseets we don't keep stylesheet as a node and adding it's namespaces to
  1964.         // each toplevel element by MergeNamespaces().
  1965.         // Namespaces of stylesheet can be overriden in template and to make this works correclety we
  1966.         // should attache them after NsDec of top level elements.
  1967.         // Toplevel element almost never contais NsDecl and in practice node duplication will not happened, but if they have
  1968.         // we should copy NsDecls of stylesheet localy in toplevel elements.
  1969.         private static NsDecl MergeNamespaces(NsDecl thisList, NsDecl parentList)
  1970.         {
  1971.             if (parentList == null) {
  1972.                 return thisList;
  1973.             }
  1974.             if (thisList == null) {
  1975.                 return parentList;
  1976.             }
  1977.             // Clone all nodes and attache them to nodes of thisList;
  1978.             while (parentList != null) {
  1979.                 bool duplicate = false;
  1980.                 for (NsDecl tmp = thisList; tmp != null; tmp = tmp.Prev) {
  1981.                     // Namespace declaration
  1982.                     // Extension or excluded namespace
  1983.                     if (Ref.Equal(tmp.Prefix, parentList.Prefix) && (tmp.Prefix != null || tmp.NsUri == parentList.NsUri)) {
  1984.                         duplicate = true;
  1985.                         break;
  1986.                     }
  1987.                 }
  1988.                 if (!duplicate) {
  1989.                     thisList = new NsDecl(thisList, parentList.Prefix, parentList.NsUri);
  1990.                 }
  1991.                 parentList = parentList.Prev;
  1992.             }
  1993.             return thisList;
  1994.         }
  1995.        
  1996.         // -------------------------------- IErrorHelper --------------------------------
  1997.        
  1998.         public void ReportError(string res, params string[] args)
  1999.         {
  2000.             compiler.ReportError(input.BuildLineInfo(), res, args);
  2001.         }
  2002.        
  2003.         public void ReportWarning(string res, params string[] args)
  2004.         {
  2005.             compiler.ReportWarning(input.BuildLineInfo(), res, args);
  2006.         }
  2007.     }
  2008. }

Developer Fusion