Xslt 使用.Net转换类时未将参数传递到模板中
我正在使用.Net XslCompiledTranform运行一些简单的XSLT(参见下面的简化示例) 示例XSLT仅用于显示传递到模板的参数值。输出是我期望的(即Xslt 使用.Net转换类时未将参数传递到模板中,xslt,Xslt,我正在使用.Net XslCompiledTranform运行一些简单的XSLT(参见下面的简化示例) 示例XSLT仅用于显示传递到模板的参数值。输出是我期望的(即 瓦卢亚 当我使用Saxon 9.0时,但当我在.net中使用XslCompiledTransform(XslTransform)时,我得到 <result xmlns:p1="http://www.doesnotexist.com"> <valueOfParamA></valueOfParamA
瓦卢亚
当我使用Saxon 9.0时,但当我在.net中使用XslCompiledTransform(XslTransform)时,我得到
<result xmlns:p1="http://www.doesnotexist.com">
<valueOfParamA></valueOfParamA>
</result>
问题是,当我使用.Net类时,paramA的参数值没有传递到模板中。我完全不明白为什么。当我在Visual Studio中逐步执行时,调试器说将使用paramA='valueA'调用模板,但当执行切换到模板时,paramA的值为空
有人能解释为什么会发生这种情况吗?这是MS实现中的一个bug还是(更有可能)我正在做XSLT中禁止的事情
非常感谢您的帮助
这是我正在使用的XSLT
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:extfn="http://exslt.org/common" exclude-result-prefixes="extfn" xmlns:p1="http://www.doesnotexist.com">
<!--
Replace msxml with
xmlns:extfn="http://exslt.org/common"
xmlns:extfn="urn:schemas-microsoft-com:xslt"
-->
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="resultTreeFragment">
<p1:foo>
</p1:foo>
</xsl:variable>
<xsl:variable name="nodeset" select="extfn:node-set($resultTreeFragment)"/>
<result>
<xsl:apply-templates select="$nodeset" mode="AParticularMode">
<xsl:with-param name="paramA" select="'valueA'"/>
</xsl:apply-templates>
</result>
</xsl:template>
<xsl:template match="p1:foo" mode="AParticularMode">
<xsl:param name="paramA"/>
<valueOfParamA>
<xsl:value-of select="$paramA"/>
</valueOfParamA>
</xsl:template>
</xsl:stylesheet>
经过多次试验后,我发现修改模板可以应用于
<xsl:apply-templates select="$nodeset/*" mode="AParticularMode">
<xsl:with-param name="paramA" select="'valueA'"/>
</xsl:apply-templates>
(注意,select=“$nodeset/*”
而不是select=“nodeset”
)使它在.Net和Saxon中按我所希望的那样工作
不过,如果有人能解释我第一次尝试失败的原因,我将不胜感激。回答您的问题 为什么我的第一次尝试失败了 当您在代码中舒适地使用node-set()时,我想您可能很清楚结果树片段 通过利用RTF[Result tree fragment],您可以将“foo”视为一个节点 变量$nodeset存储了节点的树结构,因此您可以将其值视为节点集,其中as变量$nodeset仍然是一个变量。如果您要应用模板,然后应用于,则其子节点[精确地说是元素]显示为其值 而不是你可以用
<xsl:apply-templates select="$nodeset/p1:foo" mode="AParticularMode">
更准确地说,没有什么奇怪的——这是任何符合XSLT1.0的处理器的预期行为
说明:
$nodeset
变量定义为:
XSLT1.0中包含一个完整的xml文档——一个文档节点,在XPath1.0中由/
表示
所以,
<xsl:apply-templates select="$nodeset" mode="AParticularMode">
<xsl:with-param name="paramA" select="'valueA'"/>
</xsl:apply-templates>
根据规范:
“每个模式还有一个内置的模板规则,允许在样式表中没有显式模板规则成功匹配模式的情况下,在相同模式下继续递归处理。此模板规则同时适用于元素节点和根节点。下面显示了m的内置模板规则的等效项颂歌m
现在您得到了想要的结果。
在XSLT 2.0(Saxon 9)中,您会观察到不同的行为,因为XSLT 2.0中的内置模板根据定义会重新传输应用它们的所有参数——请参见:
“如果使用参数调用内置规则,则这些参数
在隐式xsl:apply templates指令中传递。”
我可以看到您对节点集函数返回值的看法。我假设$nodeset看起来像$nodeset,但实际上是这样,但在我看来仍然有两个WTF:-a)ifI可以看到您对节点集函数返回值的看法。我假设$nodeset的值是p1:foo元素,但它不是-它是一个以p1:foo为子元素的节点。但是,在我看来仍然存在WTF:-如果$nodeset确实是一个以p1:foo为子元素的节点,为什么
select=“$nodeset”“
将其匹配为p1:foo(因为调用了我的模板)。或者换一种说法,为什么apply templates select=“$nodeset”
和apply templates select=“$nodeset/*”
都调用我的模板-我本以为只有1个调用模板,而不是两个都调用。是的,非常困惑/复杂的问题:-P,甚至我都想知道背后的技术原因。。我们会让这个问题“热”2-3天;-)你很接近事实,但并不完全正确:)请看我的答案中的解释。这是一个好问题(+1),也是新手和经验丰富的专业人士最常犯的错误之一:)请看我的答案以了解详细信息。谢谢迪米特的解释。我是XSLT的新手,不知道每个模式都有一个内置的模板(每次我想了解XSLT时,我都会发现我的知识中有另一个漏洞)。我假设XSLT 2.0中的情况有所不同,这就是为什么我在Saxon 9.0中得到不同的结果。@ChrisF,是的,我更新了我的答案,解释了XSLT 2.0的行为。我非常肯定,你知道答案。。很高兴见到你:-)
<xsl:apply-templates select="$nodeset" mode="AParticularMode">
<xsl:with-param name="paramA" select="'valueA'"/>
</xsl:apply-templates>
<xsl:template match="*|/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="*|/" mode="m">
<xsl:apply-templates mode="m"/>
</xsl:template>
<xsl:template match="/" mode="AParticularMode">
<xsl:param name="paramA"/>
<xsl:apply-templates mode="AParticularMode">
<xsl:with-param name="paramA" select="$paramA"/>
</xsl:apply-templates>
</xsl:template>