如果您希望在完整解释之前阅读它们,我的问题就在本文的底部。
我正在使用XSL将XML文档转换为漂亮的网页,并且无法正确传递变量。我定义了许多xsl:template
,并且需要将特定参数传递给其中一个。我希望我能够传递一个命名参数,该参数可能会被发送到所有xsl:template
,但只能由一个参与,而被其他人忽略。但是,当我试图为自己测试这个(以及我对XSL的有限理解)时,我根本无法传递参数,更不用说测试它是否意外地干扰了任何其他xsl:template
。
以下是简化的示例代码(为此问题键入,可能包含一个错字或两个)。我有许多不同的xsl:template
被定义来处理XML中的节点,到目前为止一切都运行良好。正是在为这些模板添加一个参数时,我似乎遇到了问题。
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="main.xsl"?>
<wrapperNode>
<testNode>
<subNode/>
</testNode>
</wrapperNode>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:import href="test.xsl"/>
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates>
<xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param>
</xsl:apply-templates>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="testNode">
<xsl:param name="testParam" />
TEST1
<xsl:value-of select="$testParam" />
TEST2
</xsl:template>
</xsl:stylesheet>
TEST1 TEST2
TEST1 TEST_PARAMETER TEST2
我对此有疑问:
是否可以发送命名
我所有的参数
xsl:template
使用了
xsl:apply-templates
xsl:with-param
,但请选择此项
特别是name=
内的值
实际模板,以便它可以
明确地用在一个单一的
模板,被其他所有人忽略
(即使我想添加其他,
不同的名称,参数
其他模板稍后)?
我目前的示例代码出错了,它似乎根本没有收到参数?
有没有更好的方法来实现这一目标?
修改:我想明确指出,由于test.xsl
:testNode
模板中的其他输出,我确信它 IS 被成功召唤。 仅参数部分无法正常工作。我并不是要浪费人们的时间来弄清楚为什么不调用该模板。它是。
更新:回应我最初收到的答案,其中指出我编写的示例并不完全正确(我的错误)并且没有非常清楚地显示问题(即:正确的模板被调用,但仅参数似乎不起作用),我用更好的示例替换了示例。此示例更清楚地显示已成功调用testNode
模板,但似乎未传递参数。在考虑此问题的先前答案之前和之后,我已经多次测试过。我绝对难过,因为从我在其他地方读到的内容和到目前为止人们的建议看来,一切似乎都是正确的。
答案 0 :(得分:27)
我对此有疑问:
- 是否可以将命名参数发送到我的所有xsl:templates 使用xsl:apply-templates xsl:with-param,但选择此值 特别是名字=在...内 实际模板,以便它可以 明确用于单个模板 并被所有其他人忽视(即使我 想要以不同方式添加其他内容 named,其他模板的参数 以后)?
醇>
是即可。在XSLT 2.0中,可以使用所谓的“隧道参数”,但在XSLT 1.0中这是使某些参数到达链中的某个远程模板的方式。
另一种方法是使用全局参数,这样就不必通过链中的每个模板传递它们。
0.2。我目前的示例代码没有错误 似乎完全接收参数?
原因在于您未向我们展示的代码。或者,您在实际案例中拥有的源XML文档可能与此处提供的文档不同。我运行了提供的代码,我根本无法重现问题 - 产生了所需的输出。
我的猜测是在匹配testNode
的模板之前选择了其他模板。此模板对传递的参数一无所知,也没有将其传递给反过来适用的模板。因此,该参数根本不会传递给匹配testNode
的模板。
我的猜测是,如果你替换:
<xsl:apply-templates>
<xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param>
</xsl:apply-templates>
与
<xsl:apply-templates select="testNode">
<xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param>
</xsl:apply-templates>
你可以获得所需的输出。
此外,您可以使用XSLT调试器(例如Visual Studio中的调试器)进行跟踪,并确切地查看选择了哪个模板。
0.3。有没有更好的方法来实现这一目标?
正如我之前所说,全局参数可以作为替代 - 但我不确定这是否更好。
最后,这是我运行的无法重现问题的代码:
XSLT样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
This is text1
<xsl:apply-templates>
<xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param>
</xsl:apply-templates>
This is text2
</xsl:template>
<xsl:template match="testNode">
<xsl:param name="testParam" />
<xsl:value-of select="$testParam" />
</xsl:template>
</xsl:stylesheet>
XML文档:
<?xml-stylesheet type="text/xsl" href="main.xsl"?>
<testNode>
<subNode/>
</testNode>
<强>结果强>:
This is text1
TEST_PARAMETER
This is text2
<强>更新强>
OP提供了更准确的信息,这证明了我的猜测。
现在很明显,问题是由于允许为wrapperNode
选择 XSLT built-in template 元素节点引起的。当然,这个模板不知道任何参数,它不使用testParam
参数,也不通过这个参数。因此,内置模板中的<xsl:apply-templates/>
会导致选择模板匹配testNode
,而不会向其传递任何参数。这解释了报告的行为/结果。
解决方案:解决方案是指定一个匹配wrapperNode
的模板,该模板接受名为testParam
的参数,并在应用模板时将其传递:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates>
<xsl:with-param name="testParam" select="'TEST_PARAMETER'"/>
</xsl:apply-templates>
</body>
</html>
</xsl:template>
<xsl:template match="testNode">
<xsl:param name="testParam" />
TEST1
<xsl:value-of select="$testParam" />
TEST2
</xsl:template>
<xsl:template match="wrapperNode">
<xsl:param name="testParam" />
<xsl:apply-templates>
<xsl:with-param name="testParam" select="$testParam"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
现在,当对提供的XML文档应用此转换时,会生成预期结果:
<html>
<body>
TEST1
TEST_PARAMETER
TEST2
</body>
</html>
答案 1 :(得分:1)
您的<html>
和<body>
标记不会出现在XSL样式表中。当我删除它们和结束标签并在Oxygen / XML中运行时,我得到你的“所需”输出。我想您希望将这些标记放在顶级模板中,在这种情况下,它会在html
和body
标记内生成输出。
您使用哪种XSLT引擎并没有抱怨无效的样式表?
答案 2 :(得分:0)
我照原样运行了上面的海报的3个示例,并在Ubuntu 18.04上的Wine上使用Notepad ++ 7.7.1在安装了XML工具的情况下获得了此结果。
<html><body>
TEST1
TEST_PARAMETER
TEST2
</body></html>