Exemplo n.º 1
0
 protected virtual T VisitChildren(XslNode node)
 {
     foreach (XslNode child in node.Content)
     {
         this.Visit(child);
     }
     return(default(T));
 }
Exemplo n.º 2
0
 protected virtual T VisitNop(XslNode node)
 {
     return(VisitChildren(node));
 }
Exemplo n.º 3
0
 protected virtual T VisitLiteralElement(XslNode node)
 {
     return(VisitChildren(node));
 }
Exemplo n.º 4
0
 protected virtual T VisitForEach(XslNode node)
 {
     return(VisitChildren(node));
 }
Exemplo n.º 5
0
        private QilNode CompileLiteralElement(XslNode node)
        {
            // IlGen requires that namespace declarations do not conflict with the namespace used by the element
            // constructor, see XmlILNamespaceAnalyzer.CheckNamespaceInScope() and SQLBUDT 389481, 389482. First
            // we try to replace all prefixes bound to aliases by result-prefixes of the corresponding
            // xsl:namespace-alias instructions. If there is at least one conflict, we leave all prefixes
            // untouched, changing only namespace URIs.
            bool changePrefixes = true;

        Start:
            _prefixesInUse.Clear();

            QilName qname = node.Name;
            string prefix = qname.Prefix;
            string nsUri = qname.NamespaceUri;

            _compiler.ApplyNsAliases(ref prefix, ref nsUri);
            if (changePrefixes)
            {
                _prefixesInUse.Add(prefix, nsUri);
            }
            else
            {
                prefix = qname.Prefix;
            }

            _outputScope.PushScope();

            // Declare all namespaces that should be declared
            // <spec>http://www.w3.org/TR/xslt.html#literal-result-element</spec>
            QilList nsList = InstructionList();
            foreach (ScopeRecord rec in _scope)
            {
                string recPrefix = rec.ncName;
                string recNsUri = rec.nsUri;
                if (recNsUri != XmlReservedNs.NsXslt && !_scope.IsExNamespace(recNsUri))
                {
                    _compiler.ApplyNsAliases(ref recPrefix, ref recNsUri);
                    if (changePrefixes)
                    {
                        if (_prefixesInUse.Contains(recPrefix))
                        {
                            if ((string)_prefixesInUse[recPrefix] != recNsUri)
                            {
                                // Found a prefix conflict. Start again from the beginning leaving all prefixes untouched.
                                _outputScope.PopScope();
                                changePrefixes = false;
                                goto Start;
                            }
                        }
                        else
                        {
                            _prefixesInUse.Add(recPrefix, recNsUri);
                        }
                    }
                    else
                    {
                        recPrefix = rec.ncName;
                    }
                    AddNsDecl(nsList, recPrefix, recNsUri);
                }
            }

            QilNode content = CompileInstructions(node.Content, nsList);
            _outputScope.PopScope();

            qname.Prefix = prefix;
            qname.NamespaceUri = nsUri;
            return _f.ElementCtor(qname, content);
        }
Exemplo n.º 6
0
 internal static XslNode SetInfo(XslNode to, List<XslNode> content, ContextInfo info)
 {
     Debug.Assert(to != null);
     to.Namespaces = info.nsList;
     SetContent(to, content);
     SetLineInfo(to, info.lineInfo);
     return to;
 }
Exemplo n.º 7
0
 private void CheckWithParam(List<XslNode> content, XslNode withParam)
 {
     Debug.Assert(content != null && withParam != null);
     Debug.Assert(withParam.NodeType == XslNodeType.WithParam);
     foreach (XslNode node in content)
     {
         if (node.NodeType == XslNodeType.WithParam && node.Name.Equals(withParam.Name))
         {
             ReportError(/*[XT0670]*/SR.Xslt_DuplicateWithParam, withParam.Name.QualifiedName);
             break;
         }
     }
 }
Exemplo n.º 8
0
 protected virtual T VisitApplyImports(XslNode node)
 {
     return(VisitChildren(node));
 }
Exemplo n.º 9
0
        private QilNode CompileApplyImports(XslNode node)
        {
            Debug.Assert(node.NodeType == XslNodeType.ApplyImports);
            Debug.Assert(!_curLoop.IsFocusSet, "xsl:apply-imports cannot be inside of xsl:for-each");

            return GenerateApply((StylesheetLevel)node.Arg, node);
        }
Exemplo n.º 10
0
 private QilNode CompileError(XslNode node)
 {
     return _f.Error(_f.String(node.Select));
 }
Exemplo n.º 11
0
 private QilNode CompileComment(XslNode node)
 {
     return _f.CommentCtor(CompileInstructions(node.Content));
 }
Exemplo n.º 12
0
 private QilNode CompilePI(XslNode node)
 {
     QilNode qilName = CompileStringAvt(node.Select);
     if (qilName.NodeType == QilNodeType.LiteralString)
     {
         string name = (string)(QilLiteral)qilName;
         _compiler.ValidatePiName(name, (IErrorHelper)this);
     }
     return _f.PICtor(qilName, CompileInstructions(node.Content));
 }
Exemplo n.º 13
0
        private QilList EnterScope(XslNode node) {
            // This is the only place where lastScope is changed
            lastScope = node;
            xslVersion = node.XslVersion;
            this.scope.PushScope();

            bool hasNamespaces = false;
            NsDecl nsDecl = node.Namespaces;
            while (nsDecl != null) {
                Debug.Assert(nsDecl.NsUri != null);
                this.scope.AddNamespace(nsDecl.Prefix, nsDecl.NsUri);
                nsDecl = nsDecl.Prev;
                hasNamespaces = true;
            }
            if (hasNamespaces) {
                return BuildDebuggerNamespaces();
            }
            return null;
        }
Exemplo n.º 14
0
        private void AddImplicitArgs(XslNode node) {
            Debug.Assert(
                node.NodeType == XslNodeType.CallTemplate ||
                node.NodeType == XslNodeType.UseAttributeSet ||
                node.NodeType == XslNodeType.ApplyTemplates ||
                node.NodeType == XslNodeType.ApplyImports
            );

            XslFlags flags = 0;

            if (IsDebug) {
                flags = XslFlags.FullFocus;
            } else {
                if (node.NodeType == XslNodeType.CallTemplate) {
                    Template tmpl;
                    if (compiler.NamedTemplates.TryGetValue(node.Name, out tmpl)) {
                        flags = tmpl.Flags;
                    }
                } else if (node.NodeType == XslNodeType.UseAttributeSet) {
                    AttributeSet attSet;
                    if (compiler.AttributeSets.TryGetValue(node.Name, out attSet)) {
                        flags = attSet.Flags;
                    }
                } else {
                    if (! compiler.ModeFlags.TryGetValue(node.Name, out flags)) {
                        flags = 0;
                    }
                    // Due to recursive nature of xsl:apply-templates/imports we always need current node
                    flags |= XslFlags.Current;
                }
            }

            List<XslNode> implicitArgs = new List<XslNode>(); {
                if ((flags & XslFlags.Current ) != 0) { implicitArgs.Add(CreateWithParam(nameCurrent , GetCurrentNode()    )); }
                if ((flags & XslFlags.Position) != 0) { implicitArgs.Add(CreateWithParam(namePosition, GetCurrentPosition())); }
                if ((flags & XslFlags.Last    ) != 0) { implicitArgs.Add(CreateWithParam(nameLast    , GetLastPosition()   )); }
            };

            node.InsertContent(implicitArgs);
        }
Exemplo n.º 15
0
        private QilNode GenerateApply(Stylesheet sheet, XslNode node) {
            Debug.Assert(
                node.NodeType == XslNodeType.ApplyTemplates ||
                node.NodeType == XslNodeType.ApplyImports
            );

            if (compiler.Settings.CheckOnly) {
                return f.Sequence();
            }
            AddImplicitArgs(node);
            return InvokeApplyFunction(sheet, /*mode:*/node.Name, node.Content);
        }
Exemplo n.º 16
0
 protected virtual T VisitUseAttributeSet(XslNode node)
 {
     return(VisitChildren(node));
 }
Exemplo n.º 17
0
 protected virtual T VisitUnknown(XslNode node)
 {
     return(VisitChildren(node));
 }
Exemplo n.º 18
0
        private QilNode CompileUseAttributeSet(XslNode node)
        {
            VerifyXPathQName(node.Name);
            // REVIEW: Future optimization: invalidate only if there were AVTs
            _outputScope.InvalidateAllPrefixes();

            AttributeSet attSet;
            if (_compiler.AttributeSets.TryGetValue(node.Name, out attSet))
            {
                Debug.Assert(attSet.Function != null, "All templates should be already compiled");
                return _invkGen.GenerateInvoke(attSet.Function, AddRemoveImplicitArgs(node.Content, attSet.Flags));
            }
            else
            {
                if (!_compiler.IsPhantomName(node.Name))
                {
                    _compiler.ReportError(/*[XT0710]*/node.SourceLine, SR.Xslt_NoAttributeSet, node.Name.QualifiedName);
                }
                return _f.Sequence();
            }
        }
Exemplo n.º 19
0
 protected virtual T VisitApplyTemplates(XslNode node)
 {
     return(VisitChildren(node));
 }
Exemplo n.º 20
0
 private QilNode CompileCopy(XslNode copy)
 {
     QilNode node = GetCurrentNode();
     _f.CheckNodeNotRtf(node);
     if ((node.XmlType.NodeKinds & InvalidatingNodes) != XmlNodeKindFlags.None)
     {
         _outputScope.InvalidateAllPrefixes();
     }
     if (node.XmlType.NodeKinds == XmlNodeKindFlags.Element)
     {
         // Context node is always an element
         // The namespace nodes of the current node are automatically copied
         QilList content = InstructionList();
         content.Add(_f.XPathNamespace(node));
         _outputScope.PushScope();
         _outputScope.InvalidateAllPrefixes();
         QilNode result = CompileInstructions(copy.Content, content);
         _outputScope.PopScope();
         return _f.ElementCtor(_f.NameOf(node), result);
     }
     else if (node.XmlType.NodeKinds == XmlNodeKindFlags.Document)
     {
         // Context node is always a document
         // xsl:copy will not create a document node, but will just use the content template
         return CompileInstructions(copy.Content);
     }
     else if ((node.XmlType.NodeKinds & (XmlNodeKindFlags.Element | XmlNodeKindFlags.Document)) == XmlNodeKindFlags.None)
     {
         // Context node is neither an element, nor a document
         // The content of xsl:copy is not instantiated
         return node;
     }
     else
     {
         // Static classifying of the context node is not possible
         return _f.XsltCopy(node, CompileInstructions(copy.Content));
     }
 }
Exemplo n.º 21
0
 private static XslNode SetLineInfo(XslNode node, ISourceLineInfo lineInfo)
 {
     Debug.Assert(node != null);
     node.SourceLine = lineInfo;
     return node;
 }
Exemplo n.º 22
0
        private QilNode CompileCopyOf(XslNode node)
        {
            QilNode selectExpr = CompileXPathExpression(node.Select);
            if (selectExpr.XmlType.IsNode)
            {
                if ((selectExpr.XmlType.NodeKinds & InvalidatingNodes) != XmlNodeKindFlags.None)
                {
                    _outputScope.InvalidateAllPrefixes();
                }

                if (selectExpr.XmlType.IsNotRtf && (selectExpr.XmlType.NodeKinds & XmlNodeKindFlags.Document) == XmlNodeKindFlags.None)
                {
                    // Expression returns non-document nodes only
                    return selectExpr;
                }

                // May be an Rtf or may return Document nodes, so use XsltCopyOf operator
                if (selectExpr.XmlType.IsSingleton)
                {
                    return _f.XsltCopyOf(selectExpr);
                }
                else
                {
                    QilIterator it;
                    return _f.Loop(it = _f.For(selectExpr), _f.XsltCopyOf(it));
                }
            }
            else if (selectExpr.XmlType.IsAtomicValue)
            {
                // Expression returns non-nodes only
                // When the result is neither a node-set nor a result tree fragment, the result is converted
                // to a string and then inserted into the result tree, as with xsl:value-of.
                return _f.TextCtor(_f.ConvertToString(selectExpr));
            }
            else
            {
                // Static classifying is not possible
                QilIterator it;
                _outputScope.InvalidateAllPrefixes();
                return _f.Loop(
                    it = _f.For(selectExpr),
                    _f.Conditional(_f.IsType(it, T.Node),
                        _f.XsltCopyOf(_f.TypeAssert(it, T.Node)),
                        _f.TextCtor(_f.XsltConvert(it, T.StringX))
                    )
                );
            }
        }
Exemplo n.º 23
0
        // ----------------- use-attribute-sets, call-templates, apply-templates, apply-imports ----------------------------- //

        private QilNode GenerateCall(QilFunction func, XslNode node) {
            Debug.Assert(
                node.NodeType == XslNodeType.CallTemplate ||
                node.NodeType == XslNodeType.UseAttributeSet
            );

            AddImplicitArgs(node);
            return invkGen.GenerateInvoke(func, node.Content);
        }
Exemplo n.º 24
0
 private QilNode CompileValueOfDoe(XslNode valueOf)
 {
     return _f.RawTextCtor(_f.ConvertToString(CompileXPathExpression(/*select:*/valueOf.Select)));
 }
Exemplo n.º 25
0
 private QilNode CompileLiteralAttribute(XslNode node)
 {
     QilName qname = node.Name;
     string prefix = qname.Prefix;
     string nsUri = qname.NamespaceUri;
     // The default namespace do not apply directly to attributes
     if (prefix.Length != 0)
     {
         _compiler.ApplyNsAliases(ref prefix, ref nsUri);
     }
     qname.Prefix = prefix;
     qname.NamespaceUri = nsUri;
     return _f.AttributeCtor(qname, CompileTextAvt(node.Select));
 }
Exemplo n.º 26
0
 private QilNode CompileWhen(XslNode whenNode, QilNode otherwise)
 {
     return _f.Conditional(
         _f.ConvertToBoolean(CompileXPathExpression(/*test:*/whenNode.Select)),
         CompileInstructions(whenNode.Content),
         otherwise
     );
 }
Exemplo n.º 27
0
 protected virtual T VisitLiteralAttribute(XslNode node)
 {
     return(VisitChildren(node));
 }
Exemplo n.º 28
0
 private QilNode CompileIf(XslNode ifNode)
 {
     return CompileWhen(ifNode, InstructionList());
 }
Exemplo n.º 29
0
 protected virtual T VisitMessage(XslNode node)
 {
     return(VisitChildren(node));
 }
Exemplo n.º 30
0
        private QilNode CompileChoose(XslNode node)
        {
            IList<XslNode> cases = node.Content;
            QilNode result = null;

            // It's easier to compile xsl:choose from bottom to top
            for (int i = cases.Count - 1; 0 <= i; i--)
            {
                XslNode when = cases[i];
                Debug.Assert(when.NodeType == XslNodeType.If || when.NodeType == XslNodeType.Otherwise);
                QilList nsList = EnterScope(when);
                if (when.NodeType == XslNodeType.Otherwise)
                {
                    Debug.Assert(result == null, "xsl:otherwise must be the last child of xsl:choose");
                    result = CompileInstructions(when.Content);
                }
                else
                {
                    result = CompileWhen(when, /*otherwise:*/result ?? InstructionList());
                }
                ExitScope();
                SetLineInfoCheck(result, when.SourceLine);
                result = SetDebugNs(result, nsList);
            }
            if (result == null)
            {
                return _f.Sequence();
            }
            return IsDebug ? _f.Sequence(result) : result;
        }
Exemplo n.º 31
0
 protected virtual T VisitOtherwise(XslNode node)
 {
     return(VisitChildren(node));
 }
Exemplo n.º 32
0
        private QilNode CompileMessage(XslNode node)
        {
            string baseUri = _lastScope.SourceLine.Uri;
            QilNode content = _f.RtfCtor(CompileInstructions(node.Content), _f.String(baseUri));

            //content = f.ConvertToString(content);
            content = _f.InvokeOuterXml(content);

            // If terminate="no", then create QilNodeType.Warning
            if (!(bool)node.Arg)
            {
                return _f.Warning(content);
            }

            // Otherwise create both QilNodeType.Warning and QilNodeType.Error
            QilIterator i;
            return _f.Loop(i = _f.Let(content), _f.Sequence(_f.Warning(i), _f.Error(i)));
        }
Exemplo n.º 33
0
 protected virtual T VisitValueOfDoe(XslNode node)
 {
     return(VisitChildren(node));
 }
Exemplo n.º 34
0
 private QilNode CompileVariable(XslNode node)
 {
     Debug.Assert(node.NodeType == XslNodeType.Variable);
     if (_scope.IsLocalVariable(node.Name.LocalName, node.Name.NamespaceUri))
     {
         ReportError(/*[XT_030]*/SR.Xslt_DupLocalVariable, node.Name.QualifiedName);
     }
     return CompileVarParValue(node);
 }
Exemplo n.º 35
0
        private QilNode CompileVarParValue(XslNode node)
        {
            Debug.Assert(node.NodeType == XslNodeType.Variable || node.NodeType == XslNodeType.Param || node.NodeType == XslNodeType.WithParam);
            VerifyXPathQName(node.Name);

            string baseUri = _lastScope.SourceLine.Uri;
            IList<XslNode> content = node.Content;
            string select = node.Select;
            QilNode varValue;

            if (select != null)
            {
                // In case of incorrect stylesheet, variable or parameter may have both a 'select' attribute and non-empty content
                QilList list = InstructionList();
                list.Add(CompileXPathExpression(select));
                varValue = CompileInstructions(content, list);
            }
            else if (content.Count != 0)
            {
                _outputScope.PushScope();
                // Rtf will be instantiated in an unknown namespace context, so we should not assume anything here
                _outputScope.InvalidateAllPrefixes();
                varValue = _f.RtfCtor(CompileInstructions(content), _f.String(baseUri));
                _outputScope.PopScope();
            }
            else
            {
                varValue = _f.String(string.Empty);
            }
            if (IsDebug)
            {
                // In debug mode every variable/param must be of type 'any'
                varValue = _f.TypeAssert(varValue, T.ItemS);
            }
            Debug.Assert(varValue.SourceLine == null);
            return varValue;
        }
Exemplo n.º 36
0
        // ----------------- apply-templates, apply-imports ----------------------------- //

        private QilNode GenerateApply(StylesheetLevel sheet, XslNode node)
        {
            Debug.Assert(
                node.NodeType == XslNodeType.ApplyTemplates && sheet is RootLevel ||
                node.NodeType == XslNodeType.ApplyImports && sheet is Stylesheet
            );

            if (_compiler.Settings.CheckOnly)
            {
                return _f.Sequence();
            }
            return InvokeApplyFunction(sheet, /*mode:*/node.Name, node.Content);
        }
Exemplo n.º 37
0
        protected virtual T Visit(XslNode node)
        {
            switch (node.NodeType)
            {
            case XslNodeType.ApplyImports: return(VisitApplyImports((XslNode)node));

            case XslNodeType.ApplyTemplates: return(VisitApplyTemplates((XslNode)node));

            case XslNodeType.Attribute: return(VisitAttribute((NodeCtor)node));

            case XslNodeType.AttributeSet: return(VisitAttributeSet((AttributeSet)node));

            case XslNodeType.CallTemplate: return(VisitCallTemplate((XslNode)node));

            case XslNodeType.Choose: return(VisitChoose((XslNode)node));

            case XslNodeType.Comment: return(VisitComment((XslNode)node));

            case XslNodeType.Copy: return(VisitCopy((XslNode)node));

            case XslNodeType.CopyOf: return(VisitCopyOf((XslNode)node));

            case XslNodeType.Element: return(VisitElement((NodeCtor)node));

            case XslNodeType.Error: return(VisitError((XslNode)node));

            case XslNodeType.ForEach: return(VisitForEach((XslNode)node));

            case XslNodeType.If: return(VisitIf((XslNode)node));

            case XslNodeType.Key: return(VisitKey((Key)node));

            case XslNodeType.List: return(VisitList((XslNode)node));

            case XslNodeType.LiteralAttribute: return(VisitLiteralAttribute((XslNode)node));

            case XslNodeType.LiteralElement: return(VisitLiteralElement((XslNode)node));

            case XslNodeType.Message: return(VisitMessage((XslNode)node));

            case XslNodeType.Nop: return(VisitNop((XslNode)node));

            case XslNodeType.Number: return(VisitNumber((Number)node));

            case XslNodeType.Otherwise: return(VisitOtherwise((XslNode)node));

            case XslNodeType.Param: return(VisitParam((VarPar)node));

            case XslNodeType.PI: return(VisitPI((XslNode)node));

            case XslNodeType.Sort: return(VisitSort((Sort)node));

            case XslNodeType.Template: return(VisitTemplate((Template)node));

            case XslNodeType.Text: return(VisitText((Text)node));

            case XslNodeType.UseAttributeSet: return(VisitUseAttributeSet((XslNode)node));

            case XslNodeType.ValueOf: return(VisitValueOf((XslNode)node));

            case XslNodeType.ValueOfDoe: return(VisitValueOfDoe((XslNode)node));

            case XslNodeType.Variable: return(VisitVariable((VarPar)node));

            case XslNodeType.WithParam: return(VisitWithParam((VarPar)node));

            default: return(VisitUnknown((XslNode)node));
            }
        }
Exemplo n.º 38
0
        private QilNode CompileRootExpression(XslNode applyTmpls)
        {
            // Compile start apply-templates call
            CheckSingletonFocus();
            _singlFocus.SetFocus(SingletonFocusType.InitialContextNode);
            QilNode result = GenerateApply(_compiler.Root, applyTmpls);
            _singlFocus.SetFocus(null);

            return _f.DocumentCtor(result);
        }
Exemplo n.º 39
0
 protected virtual T VisitCallTemplate(XslNode node)
 {
     return(VisitChildren(node));
 }
Exemplo n.º 40
0
 private QilList EnterScope(XslNode node)
 {
     // This is the only place where lastScope is changed
     _lastScope = node;
     _xslVersion = node.XslVersion;
     if (_scope.EnterScope(node.Namespaces))
     {
         return BuildDebuggerNamespaces();
     }
     return null;
 }
Exemplo n.º 41
0
 private static void AddInstruction(List<XslNode> content, XslNode instruction)
 {
     Debug.Assert(content != null);
     if (instruction != null)
     {
         content.Add(instruction);
     }
 }
Exemplo n.º 42
0
 private QilNode CompileList(XslNode node)
 {
     return CompileInstructions(node.Content);
 }
Exemplo n.º 43
0
 private static void SetContent(XslNode node, List<XslNode> content)
 {
     Debug.Assert(node != null);
     if (content != null && content.Count == 0)
     {
         content = null; // Actualy we can reuse this ArrayList.
     }
     node.SetContent(content);
 }
Exemplo n.º 44
0
 private QilNode CompileNop(XslNode node)
 {
     return _f.Nop(_f.Sequence());
 }
        public WebresourceNode AddSingleNode(Webresource resource, string[] nameParts, FolderNode folder = null)
        {
            var             fileName = nameParts.Last();
            WebresourceType type     = WebresourceType.Auto;

            if (resource.Type != 0)
            {
                type = (WebresourceType)resource.Type;
            }

            if (type == WebresourceType.Auto)
            {
                if (fileName.IndexOf(".", StringComparison.Ordinal) < 0)
                {
                    if (resource.Type == 0)
                    {
                        return(null);
                    }

                    type = (WebresourceType)resource.Type;
                }
                else
                {
                    type = Webresource.GetTypeFromExtension(fileName
                                                            .Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries).Last());
                }
            }

            WebresourceNode node = null;

            switch (type)
            {
            case WebresourceType.WebPage:
                node = new WebpageNode(resource, Settings);
                break;

            case WebresourceType.Css:
                node = new CssNode(resource, Settings);
                break;

            case WebresourceType.Data:
                node = new DataNode(resource, Settings);
                break;

            case WebresourceType.Gif:
                node = new GifNode(resource, Settings);
                break;

            case WebresourceType.Ico:
                node = new IcoNode(resource, Settings);
                break;

            case WebresourceType.Jpg:
                node = new JpgNode(resource, Settings);
                break;

            case WebresourceType.Png:
                node = new PngNode(resource, Settings);
                break;

            case WebresourceType.Resx:
                node = new ResxNode(resource, Settings);
                break;

            case WebresourceType.Script:
                node = new JavaScriptNode(resource, Settings);
                break;

            case WebresourceType.Silverlight:
                node = new SilverlightNode(resource, Settings);
                break;

            case WebresourceType.Vector:
                node = new VectorNode(resource, Settings);
                break;

            case WebresourceType.Xsl:
                node = new XslNode(resource, Settings);
                break;
            }

            resource.Node = node;

            if (folder != null && node != null)
            {
                node.ForeColor = resource.State == WebresourceState.Saved ? Color.Blue :
                                 resource.State == WebresourceState.Draft ? Color.Red : Color.Black;

                folder.Nodes.Add(node);

                (node.Parent as FolderNode)?.SetFolderColor();
            }

            return(node);
        }
 protected virtual T Visit(XslNode node) =>
 node.NodeType switch
 {