我使用.Net XslCompiledTranform来运行一些简单的XSLT(参见下面的简化示例).
示例XSLT旨在简单地显示传递给模板的参数的值.输出是我所期望的(即
<result xmlns:p1="http://www.doesnotexist.com">
<valueOfParamA>valueA</valueOfParamA>
</result>
Run Code Online (Sandbox Code Playgroud)
当我使用Saxon 9.0时,但是当我在.net中使用XslCompiledTransform(XslTransform)时,我得到了
<result xmlns:p1="http://www.doesnotexist.com">
<valueOfParamA></valueOfParamA>
</result>
Run Code Online (Sandbox Code Playgroud)
问题是当我使用.Net类时,paramA的参数值没有传递到模板中.我完全难以理解为什么.当我在Visual Studio中单步调试时,调试器表示将使用paramA ='valueA'调用模板,但是当执行切换到模板时,paramA的值为空.
任何人都可以解释为什么会这样吗?这是MS实现中的错误还是(更有可能)我在做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>
Run Code Online (Sandbox Code Playgroud)
没有什么奇怪的——这是任何 XSLT 1.0 兼容处理器的预期行为。
说明:该$nodeset变量定义为:
<xsl:variable name="nodeset" select="extfn:node-set($resultTreeFragment)"/>
XSLT 1.0 中包含一个完整的xml 文档——文档节点,在 XPath 1.0 中用 表示/ 。
所以,
<xsl:apply-templates select="$nodeset" mode="AParticularMode">
<xsl:with-param name="paramA" select="'valueA'"/>
</xsl:apply-templates>
Run Code Online (Sandbox Code Playgroud)
/如果存在这样的模板,将在指定模式下应用与树(文档节点)匹配的模板。在您的情况下,不存在这样的模板。因此,应用了内置的 XSLT 1.0 模板/(属于每种模式)。
内置模板的文本可以在规范中找到:
<xsl:template match="*|/">
<xsl:apply-templates/>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)
根据规范:“每种模式还有一个内置模板规则,它允许在样式表中的显式模板规则没有成功模式匹配的情况下,以相同模式继续递归处理。此模板规则适用于元素节点和根节点。下面显示了模式 m 的内置模板规则的等效项。
<xsl:template match="*|/" mode="m">
<xsl:apply-templates mode="m"/>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)
”
当然,内置模板对您的参数一无所知$paramA,也不会将其传递给应用的模板。
因此,最后,您的模板匹配p1:foo"将 mode="AParticularMode"被选择进行处理。没有任何内容作为参数的值传递,因此它没有值——因此<xsl:value-of>不会产生甚至单个字符或节点。
要解决此问题,只需添加一个模板匹配/and in mode "AParticularMode":
<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>
Run Code Online (Sandbox Code Playgroud)
现在你得到了想要的结果。
在 XSLT 2.0 (Saxon 9) 中,您会观察到不同的行为,因为 XSLT 2.0 中的内置模板根据定义会重新传输应用它们的所有参数 - 请参阅XSLT 2.0 规范:
“如果使用参数调用内置规则,这些参数将在隐式 xsl:apply-templates 指令中传递。”
| 归档时间: |
|
| 查看次数: |
669 次 |
| 最近记录: |