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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XslAst.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.Generic;
  16. using System.Collections.ObjectModel;
  17. using System.Diagnostics;
  18. using System.Globalization;
  19. using System.Xml.Xsl.Qil;
  20. namespace System.Xml.Xsl.Xslt
  21. {
  22.     using ContextInfo = XsltInput.ContextInfo;
  23.     using XPathQilFactory = System.Xml.Xsl.XPath.XPathQilFactory;
  24.    
  25.     // Set of classes that represent XSLT AST
  26.    
  27.     // XSLT AST is a tree of nodes that represent content of xsl template.
  28.     // All nodes are subclasses of QilNode. This was done to keep NodeCtor and Text ctors
  29.     // the sames nodes thay will be in resulting QilExpression tree.
  30.     // So we have: ElementCtor, AttributeCtor, QilTextCtor, CommentCtor, PICtor, NamespaceDecl, List.
  31.     // Plus couple subclasses of XslNode that represent different xslt instructions
  32.     // including artifitial: Sort, ExNamespaceDecl, UseAttributeSets
  33.    
  34.     internal enum XslNodeType
  35.     {
  36.         Unknown = 0,
  37.         ApplyImports,
  38.         ApplyTemplates,
  39.         Attribute,
  40.         AttributeSet,
  41.         CallTemplate,
  42.         Choose,
  43.         Comment,
  44.         Copy,
  45.         CopyOf,
  46.         Element,
  47.         Error,
  48.         ForEach,
  49.         If,
  50.         Key,
  51.         List,
  52.         LiteralAttribute,
  53.         LiteralElement,
  54.         Message,
  55.         Nop,
  56.         Number,
  57.         Otherwise,
  58.         Param,
  59.         PI,
  60.         Sort,
  61.         Template,
  62.         Text,
  63.         UseAttributeSet,
  64.         ValueOf,
  65.         ValueOfDoe,
  66.         Variable,
  67.         WithParam
  68.     }
  69.    
  70.     internal class NsDecl
  71.     {
  72.         public readonly NsDecl Prev;
  73.         // Empty string denotes the default namespace, null - extension or excluded namespace
  74.         public readonly string Prefix;
  75.         public readonly string NsUri;
  76.        
  77.         public NsDecl(NsDecl prev, string prefix, string nsUri)
  78.         {
  79.             Debug.Assert(nsUri != null);
  80.             this.Prev = prev;
  81.             this.Prefix = prefix;
  82.             this.NsUri = nsUri;
  83.         }
  84.     }
  85.    
  86.     internal class XslNode
  87.     {
  88.         public readonly XslNodeType NodeType;
  89.         public ISourceLineInfo SourceLine;
  90.         public NsDecl Namespaces;
  91.         public readonly QilName Name;
  92.         // name or mode
  93.         public readonly object Arg;
  94.         // select or test or terminate or stylesheet;-)
  95.         public readonly XslVersion XslVersion;
  96.         public XslFlags Flags;
  97.         private List<XslNode> content;
  98.        
  99.         public XslNode(XslNodeType nodeType, QilName name, object arg, XslVersion xslVer)
  100.         {
  101.             this.NodeType = nodeType;
  102.             this.Name = name;
  103.             this.Arg = arg;
  104.             this.XslVersion = xslVer;
  105.         }
  106.        
  107.         public XslNode(XslNodeType nodeType)
  108.         {
  109.             this.NodeType = nodeType;
  110.             this.XslVersion = XslVersion.Current;
  111.         }
  112.        
  113.         public string Select {
  114.             get { return (string)Arg; }
  115.         }
  116.         public bool ForwardsCompatible {
  117.             get { return XslVersion == XslVersion.ForwardsCompatible; }
  118.         }
  119.        
  120.         // -------------------------------- Content Management --------------------------------
  121.        
  122.         private static readonly IList<XslNode> EmptyList = new List<XslNode>().AsReadOnly();
  123.        
  124.         public IList<XslNode> Content {
  125.             get { return content ?? EmptyList; }
  126.         }
  127.        
  128.         public void SetContent(List<XslNode> content)
  129.         {
  130.             this.content = content;
  131.         }
  132.        
  133.         public void AddContent(XslNode node)
  134.         {
  135.             Debug.Assert(node != null);
  136.             if (content == null) {
  137.                 content = new List<XslNode>();
  138.             }
  139.             content.Add(node);
  140.         }
  141.        
  142.         public void InsertContent(IEnumerable<XslNode> collection)
  143.         {
  144.             if (content == null) {
  145.                 content = new List<XslNode>(collection);
  146.             }
  147.             else {
  148.                 content.InsertRange(0, collection);
  149.             }
  150.         }
  151.        
  152.         internal string TraceName {
  153.             get {
  154.                 #if DEBUG
  155.                 System.Text.StringBuilder sb = new System.Text.StringBuilder();
  156.                 string nodeTypeName;
  157.                 switch (NodeType) {
  158.                     case XslNodeType.AttributeSet:
  159.                         nodeTypeName = "attribute-set";
  160.                         break;
  161.                     case XslNodeType.Template:
  162.                         nodeTypeName = "template";
  163.                         break;
  164.                     case XslNodeType.Param:
  165.                         nodeTypeName = "param";
  166.                         break;
  167.                     case XslNodeType.Variable:
  168.                         nodeTypeName = "variable";
  169.                         break;
  170.                     case XslNodeType.WithParam:
  171.                         nodeTypeName = "with-param";
  172.                         break;
  173.                     default:
  174.                         nodeTypeName = NodeType.ToString();
  175.                         break;
  176.                 }
  177.                 sb.Append(nodeTypeName);
  178.                 if (Name != null) {
  179.                     sb.Append(' ');
  180.                     sb.Append(Name.QualifiedName);
  181.                 }
  182.                 ISourceLineInfo lineInfo = SourceLine;
  183.                 if (lineInfo == null && NodeType == XslNodeType.AttributeSet) {
  184.                     lineInfo = Content[0].SourceLine;
  185.                     Debug.Assert(lineInfo != null);
  186.                 }
  187.                 if (lineInfo != null) {
  188.                     string fileName = SourceLineInfo.GetFileName(lineInfo.Uri);
  189.                     int idx = fileName.LastIndexOf(System.IO.Path.DirectorySeparatorChar) + 1;
  190.                     sb.Append(" (");
  191.                     sb.Append(fileName, idx, fileName.Length - idx);
  192.                     sb.Append(':');
  193.                     sb.Append(lineInfo.StartLine);
  194.                     sb.Append(')');
  195.                 }
  196.                 return sb.ToString();
  197.                 #else
  198.                 return null;
  199.                 #endif
  200.             }
  201.         }
  202.     }
  203.    
  204.     internal abstract class ProtoTemplate : XslNode
  205.     {
  206.         public QilFunction Function;
  207.         // Compiled body
  208.         public ProtoTemplate(XslNodeType nt, QilName name, XslVersion xslVer) : base(nt, name, null, xslVer)
  209.         {
  210.         }
  211.         public abstract string GetDebugName();
  212.     }
  213.    
  214.     internal enum CycleCheck
  215.     {
  216.         NotStarted = 0,
  217.         Processing = 1,
  218.         Completed = 2
  219.     }
  220.    
  221.     internal class AttributeSet : ProtoTemplate
  222.     {
  223.         public readonly List<QilName> UsedAttributeSets = new List<QilName>();
  224.         public CycleCheck CycleCheck;
  225.         // Used to detect circular references
  226.         public AttributeSet(QilName name, XslVersion xslVer) : base(XslNodeType.AttributeSet, name, xslVer)
  227.         {
  228.             Debug.Assert(name != null);
  229.         }
  230.        
  231.         public override string GetDebugName()
  232.         {
  233.             BufferBuilder dbgName = new BufferBuilder();
  234.             dbgName.Append("<xsl:attribute-set name=\"");
  235.             dbgName.Append(Name.QualifiedName);
  236.             dbgName.Append("\">");
  237.             return dbgName.ToString();
  238.         }
  239.        
  240.         public new void AddContent(XslNode node)
  241.         {
  242.             Debug.Assert(node != null && node.NodeType == XslNodeType.List);
  243.             base.AddContent(node);
  244.         }
  245.        
  246.         public void MergeContent(AttributeSet other)
  247.         {
  248.             UsedAttributeSets.InsertRange(0, other.UsedAttributeSets);
  249.             InsertContent(other.Content);
  250.         }
  251.     }
  252.    
  253.     internal class Template : ProtoTemplate
  254.     {
  255.         public readonly string Match;
  256.         public readonly QilName Mode;
  257.         public readonly double Priority;
  258.         public int ImportPrecedence;
  259.         public int OrderNumber;
  260.        
  261.         public Template(QilName name, string match, QilName mode, double priority, XslVersion xslVer) : base(XslNodeType.Template, name, xslVer)
  262.         {
  263.             this.Match = match;
  264.             this.Mode = mode;
  265.             this.Priority = priority;
  266.         }
  267.        
  268.         public override string GetDebugName()
  269.         {
  270.             BufferBuilder dbgName = new BufferBuilder();
  271.             dbgName.Append("<xsl:template");
  272.             if (Match != null) {
  273.                 dbgName.Append(" match=\"");
  274.                 dbgName.Append(Match);
  275.                 dbgName.Append('"');
  276.             }
  277.             if (Name != null) {
  278.                 dbgName.Append(" name=\"");
  279.                 dbgName.Append(Name.QualifiedName);
  280.                 dbgName.Append('"');
  281.             }
  282.             if (!double.IsNaN(Priority)) {
  283.                 dbgName.Append(" priority=\"");
  284.                 dbgName.Append(Priority.ToString(CultureInfo.InvariantCulture));
  285.                 dbgName.Append('"');
  286.             }
  287.             if (Mode.LocalName.Length != 0) {
  288.                 dbgName.Append(" mode=\"");
  289.                 dbgName.Append(Mode.QualifiedName);
  290.                 dbgName.Append('"');
  291.             }
  292.             dbgName.Append('>');
  293.             return dbgName.ToString();
  294.         }
  295.     }
  296.    
  297.     internal class VarPar : XslNode
  298.     {
  299.         public XslFlags DefValueFlags;
  300.         public QilNode Value;
  301.         // Contains value for WithParams and global VarPars
  302.         public VarPar(XslNodeType nt, QilName name, string select, XslVersion xslVer) : base(nt, name, select, xslVer)
  303.         {
  304.         }
  305.     }
  306.    
  307.     internal class Sort : XslNode
  308.     {
  309.         public readonly string Lang;
  310.         public readonly string DataType;
  311.         public readonly string Order;
  312.         public readonly string CaseOrder;
  313.        
  314.         public Sort(string select, string lang, string dataType, string order, string caseOrder, XslVersion xslVer) : base(XslNodeType.Sort, null, select, xslVer)
  315.         {
  316.             this.Lang = lang;
  317.             this.DataType = dataType;
  318.             this.Order = order;
  319.             this.CaseOrder = caseOrder;
  320.         }
  321.     }
  322.    
  323.     internal class Keys : KeyedCollection<QilName, List<Key>>
  324.     {
  325.         protected override QilName GetKeyForItem(List<Key> list)
  326.         {
  327.             Debug.Assert(list != null && list.Count > 0);
  328.             return list[0].Name;
  329.         }
  330.     }
  331.    
  332.     internal class Key : XslNode
  333.     {
  334.         public readonly string Match;
  335.         public readonly string Use;
  336.         public QilFunction Function;
  337.        
  338.         public Key(QilName name, string match, string use, XslVersion xslVer) : base(XslNodeType.Key, name, null, xslVer)
  339.         {
  340.             // match and use can be null in case of incorrect stylesheet
  341.             Debug.Assert(name != null);
  342.             this.Match = match;
  343.             this.Use = use;
  344.         }
  345.        
  346.         public string GetDebugName()
  347.         {
  348.             BufferBuilder dbgName = new BufferBuilder();
  349.             dbgName.Append("<xsl:key name=\"");
  350.             dbgName.Append(Name.QualifiedName);
  351.             dbgName.Append('"');
  352.            
  353.             if (Match != null) {
  354.                 dbgName.Append(" match=\"");
  355.                 dbgName.Append(Match);
  356.                 dbgName.Append('"');
  357.             }
  358.             if (Use != null) {
  359.                 dbgName.Append(" use=\"");
  360.                 dbgName.Append(Use);
  361.                 dbgName.Append('"');
  362.             }
  363.             dbgName.Append('>');
  364.             return dbgName.ToString();
  365.         }
  366.     }
  367.    
  368.     internal enum NumberLevel
  369.     {
  370.         Single,
  371.         Multiple,
  372.         Any
  373.     }
  374.    
  375.     internal class Number : XslNode
  376.     {
  377.         public readonly NumberLevel Level;
  378.         public readonly string Count;
  379.         public readonly string From;
  380.         public readonly string Value;
  381.         public readonly string Format;
  382.         public readonly string Lang;
  383.         public readonly string LetterValue;
  384.         public readonly string GroupingSeparator;
  385.         public readonly string GroupingSize;
  386.        
  387.         public Number(NumberLevel level, string count, string from, string value, string format, string lang, string letterValue, string groupingSeparator, string groupingSize, XslVersion xslVer
  388.         ) : base(XslNodeType.Number, null, null, xslVer)
  389.         {
  390.             this.Level = level;
  391.             this.Count = count;
  392.             this.From = from;
  393.             this.Value = value;
  394.             this.Format = format;
  395.             this.Lang = lang;
  396.             this.LetterValue = letterValue;
  397.             this.GroupingSeparator = groupingSeparator;
  398.             this.GroupingSize = groupingSize;
  399.         }
  400.     }
  401.    
  402.     internal class NodeCtor : XslNode
  403.     {
  404.         public readonly string NameAvt;
  405.         public readonly string NsAvt;
  406.        
  407.         public NodeCtor(XslNodeType nt, string nameAvt, string nsAvt, XslVersion xslVer) : base(nt, null, null, xslVer)
  408.         {
  409.             this.NameAvt = nameAvt;
  410.             this.NsAvt = nsAvt;
  411.         }
  412.     }
  413.    
  414.     internal class Text : XslNode
  415.     {
  416.         public readonly SerializationHints Hints;
  417.        
  418.         public Text(string data, SerializationHints hints, XslVersion xslVer) : base(XslNodeType.Text, null, data, xslVer)
  419.         {
  420.             this.Hints = hints;
  421.         }
  422.     }
  423.    
  424.     internal class XslNodeEx : XslNode
  425.     {
  426.         public readonly ISourceLineInfo ElemNameLi;
  427.         public readonly ISourceLineInfo EndTagLi;
  428.        
  429.         public XslNodeEx(XslNodeType t, QilName name, object arg, ContextInfo ctxInfo, XslVersion xslVer) : base(t, name, arg, xslVer)
  430.         {
  431.             ElemNameLi = ctxInfo.elemNameLi;
  432.             EndTagLi = ctxInfo.endTagLi;
  433.             Debug.Assert(ElemNameLi != null && EndTagLi != null);
  434.         }
  435.        
  436.         public XslNodeEx(XslNodeType t, QilName name, object arg, XslVersion xslVer) : base(t, name, arg, xslVer)
  437.         {
  438.         }
  439.     }
  440.    
  441.     static internal class AstFactory
  442.     {
  443.         public static XslNode XslNode(XslNodeType nodeType, QilName name, string arg, XslVersion xslVer)
  444.         {
  445.             return new XslNode(nodeType, name, arg, xslVer);
  446.         }
  447.        
  448.         public static XslNode ApplyImports(QilName mode, Stylesheet sheet, XslVersion xslVer)
  449.         {
  450.             return new XslNode(XslNodeType.ApplyImports, mode, sheet, xslVer);
  451.         }
  452.        
  453.         public static XslNodeEx ApplyTemplates(QilName mode, string select, ContextInfo ctxInfo, XslVersion xslVer)
  454.         {
  455.             return new XslNodeEx(XslNodeType.ApplyTemplates, mode, select, ctxInfo, xslVer);
  456.         }
  457.        
  458.         // Special node for start apply-templates
  459.         public static XslNodeEx ApplyTemplates(QilName mode)
  460.         {
  461.                 /*select:*/            return new XslNodeEx(XslNodeType.ApplyTemplates, mode, null, XslVersion.Current);
  462.         }
  463.        
  464.         public static NodeCtor Attribute(string nameAvt, string nsAvt, XslVersion xslVer)
  465.         {
  466.             return new NodeCtor(XslNodeType.Attribute, nameAvt, nsAvt, xslVer);
  467.         }
  468.        
  469.         public static AttributeSet AttributeSet(QilName name)
  470.         {
  471.             return new AttributeSet(name, XslVersion.Current);
  472.         }
  473.        
  474.         public static XslNodeEx CallTemplate(QilName name, ContextInfo ctxInfo)
  475.         {
  476.             return new XslNodeEx(XslNodeType.CallTemplate, name, null, ctxInfo, XslVersion.Current);
  477.         }
  478.        
  479.         public static XslNode Choose()
  480.         {
  481.             return new XslNode(XslNodeType.Choose);
  482.         }
  483.        
  484.         public static XslNode Comment()
  485.         {
  486.             return new XslNode(XslNodeType.Comment);
  487.         }
  488.        
  489.         public static XslNode Copy()
  490.         {
  491.             return new XslNode(XslNodeType.Copy);
  492.         }
  493.        
  494.         public static XslNode CopyOf(string select, XslVersion xslVer)
  495.         {
  496.             return new XslNode(XslNodeType.CopyOf, null, select, xslVer);
  497.         }
  498.        
  499.         public static NodeCtor Element(string nameAvt, string nsAvt, XslVersion xslVer)
  500.         {
  501.             return new NodeCtor(XslNodeType.Element, nameAvt, nsAvt, xslVer);
  502.         }
  503.        
  504.         public static XslNode Error(string message)
  505.         {
  506.             return new XslNode(XslNodeType.Error, null, message, XslVersion.Current);
  507.         }
  508.        
  509.         public static XslNodeEx ForEach(string select, ContextInfo ctxInfo, XslVersion xslVer)
  510.         {
  511.             return new XslNodeEx(XslNodeType.ForEach, null, select, ctxInfo, xslVer);
  512.         }
  513.        
  514.         public static XslNode If(string test, XslVersion xslVer)
  515.         {
  516.             return new XslNode(XslNodeType.If, null, test, xslVer);
  517.         }
  518.        
  519.         public static Key Key(QilName name, string match, string use, XslVersion xslVer)
  520.         {
  521.             return new Key(name, match, use, xslVer);
  522.         }
  523.        
  524.         public static XslNode List()
  525.         {
  526.             return new XslNode(XslNodeType.List);
  527.         }
  528.        
  529.         public static XslNode LiteralAttribute(QilName name, string value, XslVersion xslVer)
  530.         {
  531.             return new XslNode(XslNodeType.LiteralAttribute, name, value, xslVer);
  532.         }
  533.        
  534.         public static XslNode LiteralElement(QilName name)
  535.         {
  536.             return new XslNode(XslNodeType.LiteralElement, name, null, XslVersion.Current);
  537.         }
  538.        
  539.         public static XslNode Message(bool term)
  540.         {
  541.             return new XslNode(XslNodeType.Message, null, term, XslVersion.Current);
  542.         }
  543.        
  544.         public static XslNode Nop()
  545.         {
  546.             return new XslNode(XslNodeType.Nop);
  547.         }
  548.        
  549.         public static Number Number(NumberLevel level, string count, string from, string value, string format, string lang, string letterValue, string groupingSeparator, string groupingSize, XslVersion xslVer
  550.         )
  551.         {
  552.             return new Number(level, count, from, value, format, lang, letterValue, groupingSeparator, groupingSize, xslVer
  553.             );
  554.         }
  555.        
  556.         public static XslNode Otherwise()
  557.         {
  558.             return new XslNode(XslNodeType.Otherwise);
  559.         }
  560.        
  561.         public static XslNode PI(string name, XslVersion xslVer)
  562.         {
  563.             return new XslNode(XslNodeType.PI, null, name, xslVer);
  564.         }
  565.        
  566.         public static Sort Sort(string select, string lang, string dataType, string order, string caseOrder, XslVersion xslVer)
  567.         {
  568.             return new Sort(select, lang, dataType, order, caseOrder, xslVer);
  569.         }
  570.        
  571.         public static Template Template(QilName name, string match, QilName mode, double priority, XslVersion xslVer)
  572.         {
  573.             return new Template(name, match, mode, priority, xslVer);
  574.         }
  575.        
  576.         public static XslNode Text(string data)
  577.         {
  578.             return new Text(data, SerializationHints.None, XslVersion.Current);
  579.         }
  580.        
  581.         public static XslNode Text(string data, SerializationHints hints)
  582.         {
  583.             return new Text(data, hints, XslVersion.Current);
  584.         }
  585.        
  586.         public static XslNode UseAttributeSet(QilName name)
  587.         {
  588.             return new XslNode(XslNodeType.UseAttributeSet, name, null, XslVersion.Current);
  589.         }
  590.        
  591.         public static VarPar VarPar(XslNodeType nt, QilName name, string select, XslVersion xslVer)
  592.         {
  593.             return new VarPar(nt, name, select, xslVer);
  594.         }
  595.        
  596.         public static VarPar WithParam(QilName name)
  597.         {
  598.                 /*select*/            return VarPar(XslNodeType.WithParam, name, null, XslVersion.Current);
  599.         }
  600.        
  601.         private static QilFactory f = new QilFactory();
  602.        
  603.         public static QilName QName(string local, string uri, string prefix)
  604.         {
  605.             return f.LiteralQName(local, uri, prefix);
  606.         }
  607.        
  608.         public static QilName QName(string local)
  609.         {
  610.             return f.LiteralQName(local);
  611.         }
  612.     }
  613. }

Developer Fusion