Beispiel #1
0
        private QilNode CompileSingleKey(List <Key> defList, QilNode key, IFocus env)
        {
            Debug.Assert(defList != null && defList.Count > 0);
            if (defList.Count == 1)
            {
                return(_f.Invoke(defList[0].Function, _f.ActualParameterList(env.GetCurrent(), key)));
            }

            QilIterator i      = _f.Let(key);
            QilNode     result = _f.Sequence();

            foreach (Key keyDef in defList)
            {
                result.Add(_f.Invoke(keyDef.Function, _f.ActualParameterList(env.GetCurrent(), i)));
            }
            return(_f.Loop(i, result));
        }
Beispiel #2
0
        QilNode IXPathEnvironment.ResolveFunction(string prefix, string name, IList <QilNode> args, IFocus env)
        {
            Debug.Assert(!args.IsReadOnly, "Writable collection expected");
            if (prefix.Length == 0)
            {
                FunctionInfo?func;
                if (FunctionTable.TryGetValue(name, out func))
                {
                    func.CastArguments(args, name, _f);

                    switch (func.id)
                    {
                    case FuncId.Current:
                        if (!_allowCurrent)
                        {
                            throw new XslLoadException(SR.Xslt_CurrentNotAllowed);
                        }
                        // NOTE: This is the only place where the current node (and not the context node) must be used
                        return(((IXPathEnvironment)this).GetCurrent() !);

                    case FuncId.Key:
                        if (!_allowKey)
                        {
                            throw new XslLoadException(SR.Xslt_KeyNotAllowed);
                        }
                        return(CompileFnKey(args[0], args[1], env));

                    case FuncId.Document: return(CompileFnDocument(args[0], args.Count > 1 ? args[1] : null));

                    case FuncId.FormatNumber: return(CompileFormatNumber(args[0], args[1], args.Count > 2 ? args[2] : null));

                    case FuncId.UnparsedEntityUri: return(CompileUnparsedEntityUri(args[0]));

                    case FuncId.GenerateId: return(CompileGenerateId(args.Count > 0 ? args[0] : env.GetCurrent() !));

                    case FuncId.SystemProperty: return(CompileSystemProperty(args[0]));

                    case FuncId.ElementAvailable: return(CompileElementAvailable(args[0]));

                    case FuncId.FunctionAvailable: return(CompileFunctionAvailable(args[0]));

                    default:
                        Debug.Fail($"{func.id} is present in the function table, but absent from the switch");
                        return(null);
                    }
                }
                else
                {
                    throw new XslLoadException(SR.Xslt_UnknownXsltFunction, Compiler.ConstructQName(prefix, name));
                }
            }
            else
            {
                string ns = ResolvePrefixThrow(/*ignoreDefaultNs:*/ true, prefix);
                Debug.Assert(ns != null);
                if (ns == XmlReservedNs.NsMsxsl)
                {
                    if (name == "node-set")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 1, /*maxArg:*/ 1, name, args.Count);
                        return(CompileMsNodeSet(args[0]));
                    }
                    else if (name == "string-compare")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 2, /*maxArg:*/ 4, name, args.Count);
                        return(_f.InvokeMsStringCompare(
                                   /*x:      */ _f.ConvertToString(args[0]),
                                   /*y:      */ _f.ConvertToString(args[1]),
                                   /*lang:   */ 2 < args.Count ? _f.ConvertToString(args[2]) : _f.String(string.Empty),
                                   /*options:*/ 3 < args.Count ? _f.ConvertToString(args[3]) : _f.String(string.Empty)
                                   ));
                    }
                    else if (name == "utc")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 1, /*maxArg:*/ 1, name, args.Count);
                        return(_f.InvokeMsUtc(/*datetime:*/ _f.ConvertToString(args[0])));
                    }
                    else if (name == "format-date" || name == "format-time")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 1, /*maxArg:*/ 3, name, args.Count);
                        return(_f.InvokeMsFormatDateTime(
                                   /*datetime:*/ _f.ConvertToString(args[0]),
                                   /*format:  */ 1 < args.Count ? _f.ConvertToString(args[1]) : _f.String(string.Empty),
                                   /*lang:    */ 2 < args.Count ? _f.ConvertToString(args[2]) : _f.String(string.Empty),
                                   /*isDate:  */ _f.Boolean(name == "format-date")
                                   ));
                    }
                    else if (name == "local-name")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 1, /*maxArg:*/ 1, name, args.Count);
                        return(_f.InvokeMsLocalName(_f.ConvertToString(args[0])));
                    }
                    else if (name == "namespace-uri")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 1, /*maxArg:*/ 1, name, args.Count);
                        return(_f.InvokeMsNamespaceUri(_f.ConvertToString(args[0]), env.GetCurrent() !));
                    }
                    else if (name == "number")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 1, /*maxArg:*/ 1, name, args.Count);
                        return(_f.InvokeMsNumber(args[0]));
                    }
                }

                if (ns == XmlReservedNs.NsExsltCommon)
                {
                    if (name == "node-set")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 1, /*maxArg:*/ 1, name, args.Count);
                        return(CompileMsNodeSet(args[0]));
                    }
                    else if (name == "object-type")
                    {
                        FunctionInfo.CheckArity(/*minArg:*/ 1, /*maxArg:*/ 1, name, args.Count);
                        return(EXslObjectType(args[0]));
                    }
                }

                // NOTE: If you add any function here, add it to IsFunctionAvailable as well

                // Ensure that all node-set parameters are DocOrderDistinct
                for (int i = 0; i < args.Count; i++)
                {
                    args[i] = _f.SafeDocOrderDistinct(args[i]);
                }

                if (_compiler.Settings.EnableScript)
                {
                    XmlExtensionFunction?scrFunc = _compiler.Scripts.ResolveFunction(name, ns, args.Count, (IErrorHelper)this);
                    if (scrFunc != null)
                    {
                        return(GenerateScriptCall(_f.QName(name, ns, prefix), scrFunc, args));
                    }
                }
                else
                {
                    if (_compiler.Scripts.ScriptClasses.ContainsKey(ns))
                    {
                        ReportWarning(SR.Xslt_ScriptsProhibited);
                        return(_f.Error(_lastScope !.SourceLine, SR.Xslt_ScriptsProhibited));
                    }
                }

                return(_f.XsltInvokeLateBound(_f.QName(name, ns, prefix), args));
            }
        }
Beispiel #3
0
        private QilNode CompileSingleKey(QilNode name, QilNode key, IFocus env)
        {
            Debug.Assert(name.XmlType == T.StringX && key.XmlType == T.StringX);
            QilNode result;

            if (name.NodeType == QilNodeType.LiteralString)
            {
                string keyName = (QilLiteral)name;

                _compiler.ParseQName(keyName, out string prefix, out string local, default(ThrowErrorHelper));
                string  nsUri = ResolvePrefixThrow(/*ignoreDefaultNs:*/ true, prefix);
                QilName qname = _f.QName(local, nsUri, prefix);

                if (!_compiler.Keys.Contains(qname))
                {
                    throw new XslLoadException(SR.Xslt_UndefinedKey, keyName);
                }
                result = CompileSingleKey(_compiler.Keys[qname], key, env);
            }
            else
            {
                if (_generalKey == null)
                {
                    _generalKey = CreateGeneralKeyFunction();
                }
                QilIterator i            = _f.Let(name);
                QilNode     resolvedName = ResolveQNameDynamic(/*ignoreDefaultNs:*/ true, i);
                result = _f.Invoke(_generalKey, _f.ActualParameterList(i, resolvedName, key, env.GetCurrent()));
                result = _f.Loop(i, result);
            }
            return(result);
        }
        // NOTE: DO NOT call QilNode.Clone() while executing this method since fixup nodes cannot be cloned
        QilNode IXPathEnvironment.ResolveFunction(string prefix, string name, IList<QilNode> args, IFocus env) {
            Debug.Assert(!args.IsReadOnly, "Writable collection expected");
            if (prefix.Length == 0) {
                FunctionInfo func;
                if (FunctionTable.TryGetValue(name, out func)) {
                    func.CastArguments(args, name, f);

                    switch (func.id) {
                    case FuncId.Current             :
                        if (!allowCurrent) {
                            throw new XslLoadException(Res.Xslt_CurrentNotAllowed);
                        }
                        // NOTE: This is the only place where the current node (and not the context node) must be used
                        return ((IXPathEnvironment) this).GetCurrent();
                    case FuncId.Key                 :
                        if (!allowKey) {
                            throw new XslLoadException(Res.Xslt_KeyNotAllowed);
                        }
                        return CompileFnKey(args[0], args[1], env);
                    case FuncId.Document            : return CompileFnDocument(args[0], args.Count > 1 ? args[1] : null);
                    case FuncId.FormatNumber        : return CompileFormatNumber(args[0], args[1], args.Count > 2 ? args[2] : null);
                    case FuncId.UnparsedEntityUri   : return CompileUnparsedEntityUri(args[0]);
                    case FuncId.GenerateId          : return CompileGenerateId(args.Count > 0 ? args[0] : env.GetCurrent());
                    case FuncId.SystemProperty      : return CompileSystemProperty(args[0]);
                    case FuncId.ElementAvailable    : return CompileElementAvailable(args[0]);
                    case FuncId.FunctionAvailable   : return CompileFunctionAvailable(args[0]);
                    default:
                        Debug.Fail(func.id + " is present in the function table, but absent from the switch");
                        return null;
                    }
                } else {
                    throw new XslLoadException(Res.Xslt_UnknownXsltFunction, Compiler.ConstructQName(prefix, name));
                }
            } else {
                string ns = ResolvePrefixThrow(/*ignoreDefaultNs:*/true, prefix);
                Debug.Assert(ns != null);
                if (ns == XmlReservedNs.NsMsxsl) {
                    if (name == "node-set") {
                        FunctionInfo.CheckArity(/*minArg:*/1, /*maxArg:*/1, name, args.Count);
                        return CompileMsNodeSet(args[0]);
                    } else if (name == "string-compare") {
                        FunctionInfo.CheckArity(/*minArg:*/2, /*maxArg:*/4, name, args.Count);
                        return f.InvokeMsStringCompare(
                            /*x:      */f.ConvertToString(args[0]),
                            /*y:      */f.ConvertToString(args[1]),
                            /*lang:   */2 < args.Count ? f.ConvertToString(args[2]) : f.String(string.Empty),
                            /*options:*/3 < args.Count ? f.ConvertToString(args[3]) : f.String(string.Empty)
                        );
                    } else if (name == "utc") {
                        FunctionInfo.CheckArity(/*minArg:*/1, /*maxArg:*/1, name, args.Count);
                        return f.InvokeMsUtc(/*datetime:*/f.ConvertToString(args[0]));
                    } else if (name == "format-date" || name == "format-time") {
                        FunctionInfo.CheckArity(/*minArg:*/1, /*maxArg:*/3, name, args.Count);
                        bool fwdCompat = (xslVersion == XslVersion.ForwardsCompatible);
                        return f.InvokeMsFormatDateTime(
                            /*datetime:*/f.ConvertToString(args[0]),
                            /*format:  */1 < args.Count ? f.ConvertToString(args[1]) : f.String(string.Empty),
                            /*lang:    */2 < args.Count ? f.ConvertToString(args[2]) : f.String(string.Empty),
                            /*isDate:  */f.Boolean(name == "format-date")
                        );
                    } else if (name == "local-name") {
                        FunctionInfo.CheckArity(/*minArg:*/1, /*maxArg:*/1, name, args.Count);
                        return f.InvokeMsLocalName(f.ConvertToString(args[0]));
                    } else if (name == "namespace-uri") {
                        FunctionInfo.CheckArity(/*minArg:*/1, /*maxArg:*/1, name, args.Count);
                        return f.InvokeMsNamespaceUri(f.ConvertToString(args[0]), env.GetCurrent());
                    } else if (name == "number") {
                        FunctionInfo.CheckArity(/*minArg:*/1, /*maxArg:*/1, name, args.Count);
                        return f.InvokeMsNumber(args[0]);
                    }
                }

                if (ns == XmlReservedNs.NsExsltCommon) {
                    if (name == "node-set") {
                        FunctionInfo.CheckArity(/*minArg:*/1, /*maxArg:*/1, name, args.Count);
                        return CompileMsNodeSet(args[0]);
                    } else if (name == "object-type") {
                        FunctionInfo.CheckArity(/*minArg:*/1, /*maxArg:*/1, name, args.Count);
                        return EXslObjectType(args[0]);
                    }
                }

                // NOTE: If you add any function here, add it to IsFunctionAvailable as well

                // Ensure that all node-set parameters are DocOrderDistinct
                for (int i = 0; i < args.Count; i++)
                    args[i] = f.SafeDocOrderDistinct(args[i]);

                if (compiler.Settings.EnableScript) {
                    XmlExtensionFunction scrFunc = compiler.Scripts.ResolveFunction(name, ns, args.Count, (IErrorHelper)this);
                    if (scrFunc != null) {
                        return GenerateScriptCall(f.QName(name, ns, prefix), scrFunc, args);
                    }
                } else {
                    if (compiler.Scripts.ScriptClasses.ContainsKey(ns)) {
                        ReportWarning(Res.Xslt_ScriptsProhibited);
                        return f.Error(lastScope.SourceLine, Res.Xslt_ScriptsProhibited);
                    }
                }

                return f.XsltInvokeLateBound(f.QName(name, ns, prefix), args);
            }
        }
        private QilNode CompileSingleKey(List<Key> defList, QilNode key, IFocus env) {
            Debug.Assert(defList != null && defList.Count > 0);
            if (defList.Count == 1) {
                return f.Invoke(defList[0].Function, f.ActualParameterList(env.GetCurrent(), key));
            }

            QilIterator i  = f.Let(key);
            QilNode result = f.Sequence();
            foreach (Key keyDef in defList) {
                result.Add(f.Invoke(keyDef.Function, f.ActualParameterList(env.GetCurrent(), i)));
            }
            return f.Loop(i, result);
        }
        private QilNode CompileSingleKey(QilNode name, QilNode key, IFocus env) {
            Debug.Assert(name.XmlType == T.StringX && key.XmlType == T.StringX);
            QilNode     result;

            if (name.NodeType == QilNodeType.LiteralString) {
                string keyName = (string)(QilLiteral)name;
                string prefix, local, nsUri;

                compiler.ParseQName(keyName, out prefix, out local, new ThrowErrorHelper());
                nsUri = ResolvePrefixThrow(/*ignoreDefaultNs:*/true, prefix);
                QilName qname = f.QName(local, nsUri, prefix);

                if (!compiler.Keys.Contains(qname)) {
                    throw new XslLoadException(Res.Xslt_UndefinedKey, keyName);
                }
                result = CompileSingleKey(compiler.Keys[qname], key, env);
            } else {
                if (generalKey == null) {
                    generalKey = CreateGeneralKeyFunction();
                }
                QilIterator i = f.Let(name);
                QilNode resolvedName = ResolveQNameDynamic(/*ignoreDefaultNs:*/true, i);
                result = f.Invoke(generalKey, f.ActualParameterList(i, resolvedName, key, env.GetCurrent()));
                result = f.Loop(i, result);
            }
            return result;
        }