XSL 命名参数“with-param”使用“应用模板”;
我的问题在这篇文章的底部,如果您想在完整解释之前阅读它们。
我正在使用 XSL 将 XML 文档转换为漂亮的网页,但在正确传递时遇到了问题一个变量。我定义了许多 xsl:template
,并且需要将特定参数传递给其中之一。我希望能够传递一个命名参数,该参数可能会发送到所有 xsl:template
,但只能由单个参数使用,而被其他参数忽略。然而,当我尝试为自己测试这一点(以及我对 XSL 的有限理解)时,我根本无法传递该参数,更不用说测试它是否意外干扰了任何其他 xsl:template
。
以下是简化的示例代码(为此问题键入的,它可能包含一两个拼写错误)。我定义了许多不同的 xsl:template 来处理 XML 中的节点,到目前为止一切都工作正常。我似乎在向这些模板添加参数时遇到了问题。
XML 文件:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="main.xsl"?>
<wrapperNode>
<testNode>
<subNode/>
</testNode>
</wrapperNode>
main.xsl:
<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>
test.xsl:
<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
模板中的其他输出,我确信它 < em>IS 被成功调用。 仅参数部分不起作用。我并不是要浪费人们的时间来弄清楚为什么该模板没有被调用。这是。
更新:响应我最初收到的答案,该答案指出我编写的示例并不完全正确(我的错误)并且没有非常清楚地显示问题(即:正确的模板正在被调用,但是只有参数似乎不起作用),我已经用更好的例子替换了这些例子。这个例子更清楚地表明,testNode
模板被成功调用,但参数似乎没有传递。在考虑这个问题的先前答案之前和之后,我已经对此进行了多次测试。我完全被难住了,因为从我在其他地方读到的内容以及人们迄今为止的建议来看,一切似乎都是正确的。
My questions are at the bottom of this post, if you wish to read them before the full explanation.
I'm converting an XML document to a pretty web page using XSL, and am having trouble with correctly passing a variable. I have many xsl:template
s defined, and need to pass a specific parameter to just one of them. I was hoping that I would be able to pass a named parameter that would presumably be sent to all of the xsl:template
s, but only be used by a single one and ignored by the others. However, when trying to test this for myself (and my limited understanding of XSL), I was unable to pass the parameter at all, let alone test if it was accidentally disturbing any other xsl:template
s.
The following is simplified example code (typed up for this question, it may contain a typo or two). I have many many different xsl:template
s defined to deal with nodes in the XML, and everything has been working fine until now. It is in adding a parameter to these templates that I appear to be having issues.
XML file:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="main.xsl"?>
<wrapperNode>
<testNode>
<subNode/>
</testNode>
</wrapperNode>
main.xsl:
<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>
test.xsl:
<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>
Output (actual):
TEST1 TEST2
Output (expected/desired):
TEST1 TEST_PARAMETER TEST2
My questions in regards to this:
Is it possible to send a named
parameter to all of myxsl:template
s using anxsl:apply-templates
withxsl:with-param
, but select this
value specifically byname=
within
the actual template so that it can
be explicitly used in a single
template and ignored by all others
(even if I wanted to add other,
differently named, parameters for
other templates later)?What am I doing wrong with my current sample code that it does not seem to receive the parameter at all?
Is there a better way to accomplish this?
Edit: I want to make it clear that due to other output within the test.xsl
:testNode
template, I know for sure that it IS being successfully called. It is ONLY the parameter part that is not working. I do not mean to waste people's time figuring out why that template is not being called. It is.
Update: In response to the answers I initially received, which pointed out that the example I made up was not completely correct (my mistake) and did not very clearly show the issue (ie: that the correct template is being called, but that only the parameter appears to not be working), I have replaced the examples with much better ones. This example more clearly shows that the testNode
template is successfully being called, but that the parameter does not seem to be passed. I have tested this numerous times, before and after consideration of the previous answers to this question. I am absolutely stumped, as everything appears to be correct from what I have read elsewhere and what people have suggested so far.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是。在 XSLT 2.0 中,人们可以使用所谓的“隧道参数”,但在 XSLT 1.0 中,这是让某些参数沿着链到达某个远程模板的方式。
另一种方法是使用全局参数,这样它们就不必通过链中的每个模板传递。
原因在于您未向我们展示的代码。或者,您实际情况中的源 XML 文档可能与此处提供的不同。我运行了提供的代码,但根本无法重现问题——产生了所需的输出。
我的猜测是,在与
testNode
匹配的模板之前选择了其他模板。该模板不知道有关传递的参数的任何信息,并且不会将其传递给它轮流应用的模板。因此,该参数根本不会传递到与testNode
匹配的模板。我的猜测是,如果您将:替换
为
您可以获得所需的输出。
此外,您还可以使用 XSLT 调试器(例如 Visual Studio 中的调试器)进行跟踪,并准确查看选择了哪个模板。
正如我之前所说,全局参数可以作为替代方案——但我不确定这更好。
最后,这是我运行的代码,无法重现您的问题:
XSLT样式表:
XML文档:
结果 :
更新:
OP提供了更准确的信息,证明了我的猜测。
现在很明显,问题是由于允许 XSLT 内置 -在模板中为
wrapperNode
选择元素节点。当然,这个模板不知道任何参数,它不使用testParam
参数,也不传递该参数。因此,内置模板中的
会导致选择与testNode
匹配的模板,而不向其传递任何参数。这解释了报告的行为/结果。解决方案:解决方案是指定一个与
wrapperNode
匹配的模板,该模板接受名为testParam
的参数,并在应用模板时传递该参数:现在,当此转换应用于提供的 XML 文档时,就会产生预期的结果:
Yes. In XSLT 2.0 one may use the so called "tunnel parameters", but in XSLT 1.0 this is the way to have some parameters reach some remote template down the chain.
Another way is to have global parameters, so that they wouldn't have to be passed through every template in the chain.
The reason is in the code you haven't shown to us. Or maybe the source XML document you have in your real case isn't the same as the one provided here. I ran the provided code and I couldn't repro the problem at all -- the desired output is produced.
My guess is that some other template is selected before the template that matches
testNode
. This template doesn't know anything about the passed parameter and it doesn't pass it to the templates that it, on its turn, applies. Thus the parameter is not passed at all to the template matchingtestNode
.My guess is that if you replace:
with
you could get the desired output.
Also, you could trace with an XSLT debugger (such as the one in Visual Studio) and see exactly which template is selected.
As I said earlier, global parameters can be used as alternative -- I am not sure that this is better, though.
Finally, here is the code that I ran that cannot repro your problem:
XSLT stylesheet:
XML document:
Result:
UPDATE:
The OP has provided more accurate information which prooves my guess.
Now it is obvious that the problem is caused by allowing the XSLT built-in template for element node to be selected for
wrapperNode
. This template, naturally, doesn't know about any parameters and it doesn't use thetestParam
parameter nor does it pass this parameter through. Thus, the<xsl:apply-templates/>
in the built-in template causes the template matchingtestNode
to be selected without passing any parameter to it. THis explains the reported behavior/result.Solution: The solution is to specify a template matching
wrapperNode
that accepts a parameter namedtestParam
and passes it through when it applies templates:Now when this transformation is applied on the provided XML document, the expected result is produced:
和
元素不能出现在 XSL 样式表中的位置。当我删除它们和结束标签并在 Oxygen/XML 中运行它时,我得到了您“所需的”输出。我认为您想将这些标签放在顶级模板中,在这种情况下,它将在
html
和body
标签内生成输出。您使用了哪种 XSLT 处理器并且没有抱怨无效的样式表?
Your
<html>
and<body>
elements can't occur where they are in an XSL stylesheet. When I remove them and the closing tags and run this in Oxygen/XML I get your "desired" output. I think you want to put those tags INSIDE the top-level template, in which case it would generate the output withinhtml
andbody
tags.Which XSLT processor did you use that didn't complain about the invalid stylesheet?
我按原样运行了海报上的 3 个示例,并在安装了 XML 工具的 Ubuntu 18.04 下的 Wine 上使用 Notepad++ 7.7.1 得到了这个结果。
I ran the poster's 3 samples above as is and got this result using Notepad++ 7.7.1 on Wine under Ubuntu 18.04 with the XML Tools installed.