private void SetArg(IList<XslNode> args, int pos, QilName name, QilNode value) { VarPar varPar; if (args.Count <= pos || args[pos].Name != name) { varPar = AstFactory.WithParam(name); args.Insert(pos, varPar); } else { varPar = (VarPar)args[pos]; } varPar.Value = value; }
private QilNode InvokeApplyFunction(StylesheetLevel sheet, QilName mode, IList<XslNode> actualArgs) { // Here we create function that has one argument for each with-param in apply-templates // We have actualArgs -- list of xsl:with-param(name, value) // From it we create: // invokeArgs -- values to use with QilInvoke // formalArgs -- list of iterators to use with QilFunction // actualArgs -- modify it to hold iterators (formalArgs) instead of values to ise in invoke generator inside function budy XslFlags flags; { if (!sheet.ModeFlags.TryGetValue(mode, out flags)) { flags = 0; } flags |= XslFlags.Current; // Due to recursive nature of Apply(Templates/Imports) we will need current node any way } actualArgs = AddRemoveImplicitArgs(actualArgs, flags); QilList invokeArgs = _f.ActualParameterList(); QilFunction applyFunction = null; // Look at the list of all functions that have been already built. If a suitable one is found, reuse it. List<QilFunction> functionsForMode; if (!sheet.ApplyFunctions.TryGetValue(mode, out functionsForMode)) { functionsForMode = sheet.ApplyFunctions[mode] = new List<QilFunction>(); } foreach (QilFunction func in functionsForMode) { if (FillupInvokeArgs(func.Arguments, actualArgs, /*ref*/invokeArgs)) { applyFunction = func; break; } } // If a suitable function has not been found, create it if (applyFunction == null) { invokeArgs.Clear(); // We wasn't able to find suitable function. Let's build new: // 1. Function arguments QilList formalArgs = _f.FormalParameterList(); for (int i = 0; i < actualArgs.Count; i++) { Debug.Assert(actualArgs[i].NodeType == XslNodeType.WithParam, "All Sorts was removed in CompileSorts()"); VarPar withParam = (VarPar)actualArgs[i]; // Add actual arg to 'invokeArgs' array. No need to clone it since it must be // a literal or a reference. invokeArgs.Add(withParam.Value); // Create correspondent formal arg QilParameter formalArg = _f.Parameter(i == 0 ? T.NodeNotRtf : withParam.Value.XmlType); formalArg.Name = CloneName(withParam.Name); formalArgs.Add(formalArg); // Change actual arg value to formalArg for reuse in calling built-in templates rules withParam.Value = formalArg; } // 2. Function header applyFunction = _f.Function(formalArgs, _f.Boolean((flags & XslFlags.SideEffects) != 0), T.NodeNotRtfS ); string attMode = (mode.LocalName.Length == 0) ? string.Empty : " mode=\"" + mode.QualifiedName + '"'; applyFunction.DebugName = (sheet is RootLevel ? "<xsl:apply-templates" : "<xsl:apply-imports") + attMode + '>'; functionsForMode.Add(applyFunction); _functions.Add(applyFunction); // 3. Function body Debug.Assert(actualArgs[0].Name == _nameCurrent, "Caller should always pass $current as a first argument to apply-* calls."); QilIterator current = (QilIterator)formalArgs[0]; // 3.1 Built-in templates: // 3.1.1 loop over content of current element QilLoop loopOnContent; { QilIterator iChild = _f.For(_f.Content(current)); QilNode filter = _f.Filter(iChild, _f.IsType(iChild, T.Content)); filter.XmlType = T.ContentS; // not attribute LoopFocus curLoopSaved = _curLoop; _curLoop.SetFocus(_f.For(filter)); /* Prepare actual arguments */ // At XSLT 1.0, if a built-in template rule is invoked with parameters, the parameters are not // passed on to any templates invoked by the built-in rule. At XSLT 2.0, these parameters are // passed through the built-in template rule unchanged. // we can't just modify current/position/last of actualArgs in XSLT 2.0 as we tried before, // becuase flags for apply-import amy now be different then flags for apply-templates, so // we may need to add some space for additional position/last arguments QilNode body = InvokeApplyFunction(_compiler.Root, mode, /*actualArgs:*/null); if (IsDebug) { body = _f.Sequence(InvokeOnCurrentNodeChanged(), body); } loopOnContent = _curLoop.ConstructLoop(body); _curLoop = curLoopSaved; } // 3.1.2 switch on type of current node QilTernary builtinTemplates = _f.BaseFactory.Conditional(_f.IsType(current, _elementOrDocumentType), loopOnContent, _f.Conditional(_f.IsType(current, _textOrAttributeType), _f.TextCtor(_f.XPathNodeValue(current)), _f.Sequence() ) ); // 3.2 Stylesheet templates _matcherBuilder.CollectPatterns(sheet, mode); applyFunction.Definition = _matcherBuilder.BuildMatcher(current, actualArgs, /*otherwise:*/builtinTemplates); } return _f.Invoke(applyFunction, invokeArgs); }
public XmlQueryType CheckLiteralQName(QilName node) { CheckLiteralValue(node, typeof(QilName)); // return XmlQueryTypeFactory.QNameX; }
protected virtual QilNode VisitLiteralQName(QilName n) { return(VisitChildren(n)); }
private QilGenerator(bool debug) { _scope = new CompilerScopeManager<QilIterator>(); _outputScope = new OutputScopeManager(); _prefixesInUse = new HybridDictionary(); _f = new XsltQilFactory(new QilFactory(), debug); _xpathBuilder = new XPathBuilder((IXPathEnvironment)this); _xpathParser = new XPathParser<QilNode>(); _ptrnBuilder = new XPathPatternBuilder((IXPathEnvironment)this); _ptrnParser = new XPathPatternParser(); _refReplacer = new ReferenceReplacer(_f.BaseFactory); _invkGen = new InvokeGenerator(_f, debug); _matcherBuilder = new MatcherBuilder(_f, _refReplacer, _invkGen); _singlFocus = new SingletonFocus(_f); _funcFocus = new FunctionFocus(); _curLoop = new LoopFocus(_f); _strConcat = new QilStrConcatenator(_f); _varHelper = new VariableHelper(_f); _elementOrDocumentType = T.DocumentOrElement; _textOrAttributeType = T.NodeChoice(XmlNodeKindFlags.Text | XmlNodeKindFlags.Attribute); _nameCurrent = _f.QName("current", XmlReservedNs.NsXslDebug); _namePosition = _f.QName("position", XmlReservedNs.NsXslDebug); _nameLast = _f.QName("last", XmlReservedNs.NsXslDebug); _nameNamespaces = _f.QName("namespaces", XmlReservedNs.NsXslDebug); _nameInit = _f.QName("init", XmlReservedNs.NsXslDebug); _formatterCnt = 0; }
protected virtual QilNode VisitLiteralQName(QilName n) { return VisitChildren(n); }
/// <summary> /// Load an XmlNavigatorFilter that matches only the specified name and types onto the stack. /// </summary> private void LoadSelectFilter(XmlNodeKindFlags xmlTypes, QilName ndName) { if (ndName != null) { // Push NameFilter Debug.Assert(xmlTypes == XmlNodeKindFlags.Element); _helper.CallGetNameFilter(_helper.StaticData.DeclareNameFilter(ndName.LocalName, ndName.NamespaceUri)); } else { // Either type cannot be a union, or else it must be >= union of all Content types bool isXmlTypeUnion = IsNodeTypeUnion(xmlTypes); Debug.Assert(!isXmlTypeUnion || (xmlTypes & XmlNodeKindFlags.Content) == XmlNodeKindFlags.Content); if (isXmlTypeUnion) { if ((xmlTypes & XmlNodeKindFlags.Attribute) != 0) { // Union includes attributes, so allow all node kinds _helper.CallGetTypeFilter(XPathNodeType.All); } else { // Filter attributes _helper.CallGetTypeFilter(XPathNodeType.Attribute); } } else { // Filter nodes of all but one type _helper.CallGetTypeFilter(QilXmlToXPathNodeType(xmlTypes)); } } }
private QilName CloneName(QilName name) { return (QilName)name.ShallowClone(_f.BaseFactory); }
/// <summary> /// Generate boiler-plate code to create an Xml iterator that uses an XmlNavigatorFilter to filter items. /// </summary> /// <remarks> /// Iterator iter; /// iter.Create(navCtxt, filter [, orSelf] [, navEnd]); /// LabelNext: /// if (!iter.MoveNext()) /// goto LabelNextCtxt; /// </remarks> private void CreateFilteredIterator(QilNode ndCtxt, string iterName, Type iterType, MethodInfo methCreate, MethodInfo methNext, XmlNodeKindFlags kinds, QilName ndName, TriState orSelf, QilNode ndEnd) { // Iterator iter; LocalBuilder locIter = _helper.DeclareLocal(iterName, iterType); // iter.Create(navCtxt, filter [, orSelf], [, navEnd]); _helper.Emit(OpCodes.Ldloca, locIter); NestedVisitEnsureStack(ndCtxt); LoadSelectFilter(kinds, ndName); if (orSelf != TriState.Unknown) _helper.LoadBoolean(orSelf == TriState.True); if (ndEnd != null) NestedVisitEnsureStack(ndEnd); _helper.Call(methCreate); GenerateSimpleIterator(typeof(XPathNavigator), locIter, methNext); }
/// <summary> /// Generate boiler-plate code to create an Xml iterator that controls a nested iterator. /// </summary> /// <remarks> /// Iterator iter; /// iter.Create(filter [, orSelf]); /// ...nested iterator... /// navInput = nestedNested; /// goto LabelCall; /// LabelNext: /// navInput = null; /// LabelCall: /// switch (iter.MoveNext(navInput)) { /// case IteratorState.NoMoreNodes: goto LabelNextCtxt; /// case IteratorState.NextInputNode: goto LabelNextNested; /// } /// </remarks> private void CreateContainerIterator(QilUnary ndDod, string iterName, Type iterType, MethodInfo methCreate, MethodInfo methNext, XmlNodeKindFlags kinds, QilName ndName, TriState orSelf) { // Iterator iter; LocalBuilder locIter = _helper.DeclareLocal(iterName, iterType); Label lblOnEndNested; QilLoop ndLoop = (QilLoop)ndDod.Child; Debug.Assert(ndDod.NodeType == QilNodeType.DocOrderDistinct && ndLoop != null); // iter.Create(filter [, orSelf]); _helper.Emit(OpCodes.Ldloca, locIter); LoadSelectFilter(kinds, ndName); if (orSelf != TriState.Unknown) _helper.LoadBoolean(orSelf == TriState.True); _helper.Call(methCreate); // Generate nested iterator (branch to lblOnEndNested when iteration is complete) lblOnEndNested = _helper.DefineLabel(); StartNestedIterator(ndLoop, lblOnEndNested); StartBinding(ndLoop.Variable); EndBinding(ndLoop.Variable); EndNestedIterator(ndLoop.Variable); _iterCurr.Storage = _iterNested.Storage; GenerateContainerIterator(ndDod, locIter, lblOnEndNested, methNext, typeof(XPathNavigator)); }
/// <summary> /// Serialize literal QName as three separate attributes. /// </summary> protected override QilNode VisitLiteralQName(QilName value) { this.writer.WriteAttributeString("name", value.ToString()); return(value); }
protected override QilNode VisitLiteralQName(QilName n) { return(NoReplace(n)); }
public QilParameter Parameter(QilNode defaultValue, QilName name, XmlQueryType t) { return(_f.Parameter(defaultValue, name, t)); }
private void VerifyXPathQName(QilName qname) { Debug.Assert( _compiler.IsPhantomName(qname) || qname.NamespaceUri == ResolvePrefix(/*ignoreDefaultNs:*/true, qname.Prefix), "QilGenerator must resolve the prefix to the same namespace as XsltLoader" ); }
/// <summary> /// Generate code for QilNodeType.LiteralQName. /// </summary> protected override QilNode VisitLiteralQName(QilName ndQName) { _helper.ConstructLiteralQName(ndQName.LocalName, ndQName.NamespaceUri); _iterCurr.Storage = StorageDescriptor.Stack(typeof(XmlQualifiedName), false); return ndQName; }
private QilNode AddDebugVariable(QilName name, QilNode value, QilNode content) { QilIterator var = _f.Let(value); var.DebugName = name.ToString(); return _f.Loop(var, content); }
public XmlQueryType CheckLiteralQName(QilName node) { CheckLiteralValue(node, typeof(QilName)); // BUGBUG: Xslt constructs invalid QNames, so don't check this //Check(ValidateNames.ValidateName(node.Prefix, node.LocalName, node.NamespaceUri, XPathNodeType.Element, ValidateNames.Flags.All), node, "QName is not valid"); return XmlQueryTypeFactory.QNameX; }
private QilParameter CreateXslParam(QilName name, XmlQueryType xt) { QilParameter arg = _f.Parameter(xt); arg.DebugName = name.ToString(); arg.Name = name; return arg; }
public QilName LiteralQName(string localName, string namespaceUri, string prefix) { QilName n = new QilName(QilNodeType.LiteralQName, localName, namespaceUri, prefix); n.XmlType = this.typeCheck.CheckLiteralQName(n); TraceNode(n); return n; }
protected override QilNode VisitLiteralQName(QilName n) { return NoReplace(n); }
public static VarPar CreateWithParam(QilName name, QilNode value) { VarPar withParam = AstFactory.WithParam(name); withParam.Value = value; return withParam; }
private QilNode GenerateScriptCall(QilName name, XmlExtensionFunction scrFunc, IList<QilNode> args) { XmlQueryType xmlTypeFormalArg; for (int i = 0; i < args.Count; i++) { xmlTypeFormalArg = scrFunc.GetXmlArgumentType(i); switch (xmlTypeFormalArg.TypeCode) { case XmlTypeCode.Boolean: args[i] = f.ConvertToBoolean(args[i]); break; case XmlTypeCode.Double: args[i] = f.ConvertToNumber(args[i]); break; case XmlTypeCode.String: args[i] = f.ConvertToString(args[i]); break; case XmlTypeCode.Node: args[i] = xmlTypeFormalArg.IsSingleton ? f.ConvertToNode(args[i]) : f.ConvertToNodeSet(args[i]); break; case XmlTypeCode.Item: break; default: Debug.Fail("This XmlTypeCode should never be inferred from a Clr type: " + xmlTypeFormalArg.TypeCode); break; } } return f.XsltInvokeEarlyBound(name, scrFunc.Method, scrFunc.XmlReturnType, args); }
private QilNode InvokeApplyFunction(Stylesheet sheet, QilName mode, IList<XslNode> actualArgs) { // Here we create function that has one argument for each with-param in apply-templates // We have actualArgs -- list of xsl:with-param(name, value) // From it we create: // invokeArgs -- values to use with QilInvoke // formalArgs -- list of iterators to use with QilFunction // actualArgs -- modify it to hold iterators (formalArgs) instead of values to ise in invoke generator inside function budy // Special treatment for current/position/last XslFlags flags; if (! compiler.ModeFlags.TryGetValue(mode, out flags)) { flags = 0; } if (IsDebug) { flags = XslFlags.FullFocus; } flags |= XslFlags.Current; // Due to recursive nature of Apply(Templates/Imports) we will need current node any way Debug.Assert(actualArgs[0].Name == nameCurrent, "Caller should always pass $current as a first argument to apply-* calls."); QilList invokeArgs = f.ActualParameterList(); QilFunction applyFunction = null; // Look at the list of all functions that have been already built. If a suitable one is found, reuse it. Dictionary<QilName, List<QilFunction>> funcTable = ( sheet == null ? compiler.ApplyTemplatesFunctions : sheet.ApplyImportsFunctions ); List<QilFunction> functionsForMode; if (!funcTable.TryGetValue(mode, out functionsForMode)) { functionsForMode = funcTable[mode] = new List<QilFunction>(); } foreach (QilFunction func in functionsForMode) { if (FillupInvokeArgs(func.Arguments, actualArgs, /*ref*/invokeArgs)) { applyFunction = func; break; } } // If a suitable function has not been found, create it if (applyFunction == null) { invokeArgs.Clear(); // We wasn't able to find suitable function. Let's build new: // 1. Function arguments QilList formalArgs = f.FormalParameterList(); for (int i = 0; i < actualArgs.Count; i++) { Debug.Assert(actualArgs[i].NodeType == XslNodeType.WithParam, "All Sorts was removed in CompileSorts()"); VarPar withParam = (VarPar)actualArgs[i] ; // Add actual arg to 'invokeArgs' array. No need to clone it since it must be // a literal or a reference. invokeArgs.Add(withParam.Value); // Create correspondent formal arg QilParameter formalArg = f.Parameter(i == 0 ? T.NodeNotRtf : withParam.Value.XmlType); formalArg.Name = CloneName(withParam.Name); formalArgs.Add(formalArg); // Change actual arg value to formalArg for reuse in calling built-in templates rules withParam.Value = formalArg; } // 2. Function header applyFunction = f.Function(formalArgs, f.False(), T.NodeNotRtfS); string attMode = (mode.LocalName.Length == 0) ? string.Empty : " mode=\"" + mode.QualifiedName + '"'; applyFunction.DebugName = (sheet == null ? "<xsl:apply-templates" : "<xsl:apply-imports") + attMode + '>'; functionsForMode.Add(applyFunction); this.functions.Add(applyFunction); // 3. Function body QilIterator current = (QilIterator)formalArgs[0]; // 3.1 Built-in templates QilTernary builtinTemplates = f.BaseFactory.Conditional(f.IsType(current, elementOrDocumentType), // This will be fixed up later f.BaseFactory.Nop(f.BaseFactory.Unknown(T.NodeNotRtfS)), f.Conditional(f.IsType(current, textOrAttributeType), f.TextCtor(f.XPathNodeValue(current)), f.Sequence() ) ); // 3.2 Stylesheet templates matcherBuilder.CollectPatterns(sheet ?? compiler.PrincipalStylesheet, mode, /*applyImports:*/sheet != null); applyFunction.Definition = matcherBuilder.BuildMatcher(current, actualArgs, /*otherwise:*/builtinTemplates); // 3.3 Fix up the loop in built-in templates QilLoop loopOnContent; { QilIterator iChild = f.For(f.Content(current)); QilNode filter = f.Filter(iChild, f.IsType(iChild, T.Content)); filter.XmlType = T.ContentS; // not attribute LoopFocus curLoopSaved = curLoop; curLoop.SetFocus(f.For(filter)); if ((flags & XslFlags.Last) != 0) { // Mark that we need last argument curLoop.GetLast(); } /* Prepare actual arguments */ { // At XSLT 1.0, if a built-in template rule is invoked with parameters, the parameters are not // passed on to any templates invoked by the built-in rule. At XSLT 2.0, these parameters are // passed through the built-in template rule unchanged. const bool Xslt10Rules = true; if (Xslt10Rules) { List<XslNode> newActualArgs = new List<XslNode>(3); int argNum = 0; if ((flags & XslFlags.Current ) != 0) { newActualArgs.Add(actualArgs[argNum ++]); } if ((flags & XslFlags.Position) != 0) { newActualArgs.Add(actualArgs[argNum ++]); } if ((flags & XslFlags.Last ) != 0) { newActualArgs.Add(actualArgs[argNum ++]); } actualArgs = newActualArgs; } // Fix values of current, position, and last { int argNum = 0; if ((flags & XslFlags.Current ) != 0) { ((VarPar)actualArgs[argNum ++]).Value = GetCurrentNode (); } if ((flags & XslFlags.Position) != 0) { ((VarPar)actualArgs[argNum ++]).Value = GetCurrentPosition(); } if ((flags & XslFlags.Last ) != 0) { ((VarPar)actualArgs[argNum ++]).Value = GetLastPosition (); } } } loopOnContent = curLoop.ConstructLoop(InvokeApplyFunction(/*sheet:*/null, mode, actualArgs)); curLoop = curLoopSaved; } Debug.Assert(builtinTemplates.Center.NodeType == QilNodeType.Nop); ((QilUnary)builtinTemplates.Center).Child = loopOnContent; } return f.Invoke(applyFunction, invokeArgs); }
public QilParameter Parameter(QilNode defaultValue, QilName name, XmlQueryType t) { return f.Parameter(defaultValue, name, t); }
private void EndElement() { MethodInfo facMethod = null; object[] facArgs; QilList list; QilNode nd; ReaderAnnotation ann; list = this.stk.Pop(); ann = (ReaderAnnotation)list.Annotation; // Special case certain element names string s = r.LocalName; switch (r.LocalName) { case "QilExpression": { Debug.Assert(list.Count > 0, "QilExpression node requires a Root expression"); QilExpression qil = f.QilExpression(list[list.Count - 1]); // Be flexible on order and presence of QilExpression children for (int i = 0; i < list.Count - 1; i++) { switch (list[i].NodeType) { case QilNodeType.True: case QilNodeType.False: qil.IsDebug = list[i].NodeType == QilNodeType.True; break; case QilNodeType.FunctionList: qil.FunctionList = (QilList)list[i]; break; case QilNodeType.GlobalVariableList: qil.GlobalVariableList = (QilList)list[i]; break; case QilNodeType.GlobalParameterList: qil.GlobalParameterList = (QilList)list[i]; break; } } nd = qil; break; } case "ForwardDecls": this.inFwdDecls = false; return; case "Parameter": case "Let": case "For": case "Function": { string id = ann.Id; QilName name = ann.Name; Debug.Assert(id != null, r.LocalName + " must have an id attribute"); Debug.Assert(!this.inFwdDecls || ann.XmlType != null, "Forward decl for " + r.LocalName + " '" + id + "' must have an xmlType attribute"); // Create node (may be discarded later if it was already declared in forward declarations section) switch (r.LocalName) { case "Parameter": Debug.Assert(list.Count <= (this.inFwdDecls ? 0 : 1), "Parameter '" + id + "' must have 0 or 1 arguments"); Debug.Assert(ann.XmlType != null, "Parameter '" + id + "' must have an xmlType attribute"); if (this.inFwdDecls || list.Count == 0) { nd = f.Parameter(null, name, ann.XmlType); } else { nd = f.Parameter(list[0], name, ann.XmlType); } break; case "Let": Debug.Assert(list.Count == (this.inFwdDecls ? 0 : 1), "Let '" + id + "' must have 0 or 1 arguments"); if (this.inFwdDecls) { nd = f.Let(f.Unknown(ann.XmlType)); } else { nd = f.Let(list[0]); } break; case "For": Debug.Assert(list.Count == 1, "For '" + id + "' must have 1 argument"); nd = f.For(list[0]); break; default: Debug.Assert(list.Count == (this.inFwdDecls ? 2 : 3), "Function '" + id + "' must have 2 or 3 arguments"); if (this.inFwdDecls) { nd = f.Function(list[0], list[1], ann.XmlType); } else { nd = f.Function(list[0], list[1], list[2], ann.XmlType != null ? ann.XmlType : list[1].XmlType); } break; } // Set DebugName if (name != null) { ((QilReference)nd).DebugName = name.ToString(); } if (this.inFwdDecls) { Debug.Assert(!this.scope.ContainsKey(id), "Multiple nodes have id '" + id + "'"); this.fwdDecls[id] = nd; this.scope[id] = nd; } else { if (this.fwdDecls.ContainsKey(id)) { // Replace forward declaration Debug.Assert(r.LocalName == Enum.GetName(typeof(QilNodeType), nd.NodeType), "Id '" + id + "' is not not bound to a " + r.LocalName + " forward decl"); nd = this.fwdDecls[id]; this.fwdDecls.Remove(id); if (list.Count > 0) { nd[0] = list[0]; } if (list.Count > 1) { nd[1] = list[1]; } } else { // Put reference in scope Debug.Assert(!this.scope.ContainsKey(id), "Id '" + id + "' is already in scope"); this.scope[id] = nd; } } nd.Annotation = ann; break; } case "RefTo": { // Lookup reference string id = ann.Id; Debug.Assert(id != null, r.LocalName + " must have an id attribute"); Debug.Assert(this.scope.ContainsKey(id), "Id '" + id + "' is not in scope"); this.stk.Peek().Add(this.scope[id]); return; } case "Sequence": nd = f.Sequence(list); break; case "FunctionList": nd = f.FunctionList(list); break; case "GlobalVariableList": nd = f.GlobalVariableList(list); break; case "GlobalParameterList": nd = f.GlobalParameterList(list); break; case "ActualParameterList": nd = f.ActualParameterList(list); break; case "FormalParameterList": nd = f.FormalParameterList(list); break; case "SortKeyList": nd = f.SortKeyList(list); break; case "BranchList": nd = f.BranchList(list); break; case "XsltInvokeEarlyBound": { Debug.Assert(ann.ClrNamespace != null, "XsltInvokeEarlyBound must have a clrNamespace attribute"); Debug.Assert(list.Count == 2, "XsltInvokeEarlyBound must have exactly 2 arguments"); Debug.Assert(list.XmlType != null, "XsltInvokeEarlyBound must have an xmlType attribute"); MethodInfo mi = null; QilName name = (QilName)list[0]; foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) { Type t = asm.GetType(ann.ClrNamespace); if (t != null) { mi = t.GetMethod(name.LocalName); break; } } Debug.Assert(mi != null, "Cannot find method " + ann.ClrNamespace + "." + name.ToString()); nd = f.XsltInvokeEarlyBound(name, f.LiteralObject(mi), list[1], ann.XmlType); break; } default: { // Find factory method which will be used to construct the Qil node Debug.Assert(nameToFactoryMethod.ContainsKey(r.LocalName), "Method " + r.LocalName + " could not be found on QilFactory"); facMethod = nameToFactoryMethod[r.LocalName]; Debug.Assert(facMethod.GetParameters().Length == list.Count, "NodeType " + r.LocalName + " does not allow " + list.Count + " parameters"); // Create factory method arguments facArgs = new object[list.Count]; for (int i = 0; i < facArgs.Length; i++) { facArgs[i] = list[i]; } // Create node and set its properties nd = (QilNode)facMethod.Invoke(f, facArgs); break; } } nd.SourceLine = list.SourceLine; // Add node to its parent's list this.stk.Peek().Add(nd); }