XSL使用"apply-templates"将参数命名为"with-param" [英] XSL named parameter 'with-param' using 'apply-templates'

查看:95
本文介绍了XSL使用"apply-templates"将参数命名为"with-param"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题在这篇文章的底部,如果您想在完整的解释之前阅读它们.

我正在使用XSL将XML文档转换为漂亮的网页,并且无法正确传递变量.我定义了许多xsl:template,并且需要将特定参数传递给其中的一个.我希望我能够传递一个命名参数,该参数可能会发送给所有xsl:template,但只能由单个参数使用,而其他参数则忽略.但是,当尝试自己测试(以及对XSL的有限了解)时,我根本无法传递该参数,更不用说测试它是否意外地干扰了其他xsl:template.

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:templates 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:templates, 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:templates.

以下是简化的示例代码(为此问题键入的,可能包含一两个错字).我定义了许多不同的xsl:template来处理XML中的节点,并且到目前为止一切正常.似乎是在向这些模板添加参数时出现问题.

The following is simplified example code (typed up for this question, it may contain a typo or two). I have many many different xsl:templates 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 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


我对此有以下疑问:


My questions in regards to this:

  1. 是否可以发送已命名的 我所有的参数 xsl:template s使用 xsl:apply-templatesxsl:with-param,但是选择此 具体由name=内的值 实际的模板,以便它可以 明确地在单个中使用 模板,被所有其他人忽略 (即使我想添加其他内容, 命名不同,用于的参数 其他模板)?

  1. Is it possible to send a named parameter to all of my xsl:templates using an xsl:apply-templates with xsl:with-param, but select this value specifically by name= 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?

我想说明一下,由于test.xsl:testNode模板中的其他输出,我肯定知道 IS 已成功叫.是 ONLY 无效的参数部分.我并不是要浪费人们的时间弄清楚为什么未调用该模板.是的.

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.

更新:针对我最初收到的答案,该答案指出我编写的示例并不完全正确(我的错误),也没有非常清楚地表明问题所在(即:调用了正确的模板 ,但是该参数 only 似乎不起作用),我将示例替换为更好的示例.此示例更清楚地显示了testNode模板已成功调用,但是似乎未传递参数.在考虑之前对这个问题的回答之前和之后,我已经多次测试了这一点.我绝对感到很沮丧,因为从我在其他地方所读的内容以及到目前为止人们的建议,所有内容似乎都是正确的.

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.

推荐答案

我对此有以下疑问:

My questions in regards to this:

  1. 是否可以将命名参数发送到我的所有xsl:templates 使用xsl:apply-templates与 xsl:with-param,但是选择此值 特别是在 实际的模板,以便它可以是 在单个模板中明确使用 并被其他所有人忽略(即使我 想要添加其他内容,以不同的方式 命名,其他模板的参数 稍后)?
  1. Is it possible to send a named parameter to all of my xsl:templates using an xsl:apply-templates with xsl:with-param, but select this value specifically by name= 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)?

.在XSLT 2.0中,可以使用所谓的隧道参数",但是在XSLT 1.0中,这是使某些参数到达链中某些远程模板的方法.

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.

.2.我当前的示例代码在做错什么,但事实并非如此 似乎根本没有收到参数?

.2. What am I doing wrong with my current sample code that it does not seem to receive the parameter at all?

原因是您未向我们显示的代码中.或者,您实际拥有的源XML文档可能与此处提供的文档不同.我运行了提供的代码,但根本无法解决问题-产生了所需的输出.

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.

我的猜测是在与testNode匹配的模板之前选择了其他模板.该模板对传递的参数一无所知,也不会将其传递给反过来,它也适用.因此,该参数根本不会传递给匹配testNode的模板.

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 matching testNode.

我的猜测是,如果您替换:

My guess is that if you replace:

  <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> 

您可以获得所需的输出.

you could get the desired output.

此外,您可以使用XSLT调试器(例如Visual Studio中的调试器)进行跟踪,并确切地看到选择了哪个模板.

Also, you could trace with an XSLT debugger (such as the one in Visual Studio) and see exactly which template is selected.

.3.有没有更好的方法可以做到这一点?

.3. Is there a better way to accomplish this?

正如我之前所说,可以将全局参数用作替代方法-我不确定这是否更好.

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样式表:

<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提供了更准确的信息,这证明了我的猜测.

The OP has provided more accurate information which prooves my guess.

现在,很明显,问题是由允许 要为wrapperNode选择元素节点的XSLT内置模板 .自然,此模板不知道任何参数,并且不使用testParam参数,也不通过此参数.因此,内置模板中的<xsl:apply-templates/>会导致选择与testNode匹配的模板,而无需向其传递任何参数.这解释了报告的行为/结果.

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 the testParam parameter nor does it pass this parameter through. Thus, the <xsl:apply-templates/> in the built-in template causes the template matching testNode to be selected without passing any parameter to it. THis explains the reported behavior/result.

解决方案:解决方案是指定一个匹配wrapperNode的模板,该模板接受名为testParam的参数,并在应用模板时将其传递通过:

Solution: The solution is to specify a template matching wrapperNode that accepts a parameter named testParam and passes it through when it applies templates:

<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>

这篇关于XSL使用"apply-templates"将参数命名为"with-param"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆