我有一个xslt模板,我试图将我的项目的所有逻辑分成不同的文件和模板,所以一切都会很好,整洁。我正在使用微软xslt处理器btw。
好吧,我遇到了这个问题,我在一个节点集变量上调用apply-template,节点集成为root xml节点。
<xsl:import href="tblLogins.xslt"/>
<xsl:import href="tblPay_OrderItems.xslt/>
<xsl:variable name="item" select="/Entities/Data/tblLogins"/>
<!-- Get the users orders -->
<xsl:variable name="_orders" >
<xsl:apply-templates select="$item" mode="GetOrders" />
</xsl:variable>
<xsl:variable name="orders" select="msxsl:node-set($_orders)/*" />
<!-- Get the order's items -->
<!-- This works and we now have all the orders -->
<xsl:variable name="_orderItems" >
<xsl:apply-templates select="$orders" mode="GetOrderItems" />
</xsl:variable>
<xsl:variable name="orderItems" select="msxsl:node-set($_orderItems)/*" />
<!-- will always be empty -->
tblLogins.xslt
<xsl:key name="ordersByUserId" match="tblPay_Orders" use="UserId" />
<xsl:template match="tblLogins" mode="GetOrders" >
<xsl:copy-of select="key('ordersByUserId',loginID)"/>
</xsl:template>
tblPay_Order.xslt
<xsl:key name="orderItemsByOrderId" match="tblPay_OrderItems" use="OrderId" />
<xsl:template match="tblPay_Orders" mode="GetOrderItems" >
<!-- "/" is now the tblPay_Orders and nothing else is available -->
<xsl:copy-of select="key('orderItemsByOrderId',Id)"/>
<!-- will return nothing -->
</xsl:template>
没有模板
<!-- Works -->
<xsl:copy-of select="key('orderItemsByOrderId',key('ordersByUserId',loginID)/Id)"/>
编辑:我现在在不同的文件中设置它。我确实把所有文件都复制并粘贴到一个xslt中,这仍然发生了。
现在,如果我撤消模板并且只有一个Key列表('',键('',键(''.....等等它会起作用,因为“/”包含所有内容。但是当我应用模板,会发生这种情况。
我看到了问题XSLT: Process an Xml node set in a template while still having access to the document root,这是解决问题的方法。但我的问题更多的是为什么会发生这种情况以及如何在XSLT 2.0中处理? (即使MS永远不会更新到2.0)
我认为在XSLT 2.0中,结果树片段已被废除。是否还有像对象一样的“结果树片段”,但它现在支持“/”操作等等?或者一切都是节点集?
答案 0 :(得分:1)
问题在于_orders
变量中的节点不是输入文档中的原始节点,而是结果树片段中新创建的副本节点。 msxsl:node-set
函数将此RTF转换为单个文档根节点(在XPath数据模型术语中 - 在DOM术语中它是一个文档片段),复制的tblPay_Orders
元素作为其子元素。
因此,当您apply-templates
到这些节点时,您正在将当前文档更改为此片段,因此/
然后引用片段节点而不是原始文档根(更准确地说,是/
指的是当前上下文节点所属的任何文档的根节点,并且key
函数查找片段中的节点。
如果您使用相同的模板(XSLT 2.0将其称为“临时树”而不是RTF,但原理相同),您在XSLT 2.0中会遇到完全相同的问题 - copy-of
仍会创建新节点在一棵临时树上。但您可以改为使用xsl:sequence
:
<xsl:template match="tblLogins" mode="GetOrders" >
<xsl:sequence select="key('ordersByUserId',loginID)"/>
</xsl:template>
这里的区别在于xsl:sequence
返回附加到原始文档的原始节点,而不是在新树中创建临时副本。
答案 1 :(得分:-1)