XSL使用'apply-templates'命名参数'with-param'

Kev*_*enK 18 xslt parameters stylesheet apply-templates

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

我正在使用XSL将XML文档转换为漂亮的网页,并且无法正确传递变量.我xsl:template定义了很多,并且需要将特定参数传递给其中一个.我希望我能够传递一个命名参数,该参数可能被发送到所有xsl:templates,但只能被一个人使用而被其他人忽略.然而,当我试图为自己测试这个(以及我对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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

输出(实际):

TEST1 TEST2
Run Code Online (Sandbox Code Playgroud)

输出(预期/期望):

TEST1 TEST_PARAMETER TEST2
Run Code Online (Sandbox Code Playgroud)

我对此有疑问:

  1. 是否可以xsl:template使用xsl:apply-templateswith 向我的所有s 发送命名参数 xsl:with-param,但name=在实际模板中专门选择此值,以便它可以在单个模板中显式使用并被所有其他模板忽略(即使我想添加其他,不同名称的参数,以后的其他模板)?

  2. 我目前的示例代码出了什么问题,它似乎根本没有收到参数?

  3. 有没有更好的方法来实现这一目标?

编辑:我想弄清楚的是,由于内的其他输出test.xsl:testNode模板,我知道肯定是IS被成功调用.它是唯一不工作参数的一部分.我并不是要浪费人们的时间来弄清楚为什么不调用该模板.它是.

更新:在回答我最初收到的答复,其中指出,我做了的例子并不完全正确的(我的错误),并没有很清楚地显示问题(即:正确的模板调用,但该参数似乎不起作用),我用更好的例子替换了这些例子.此示例更清楚地显示testNode模板已成功调用,但该参数似乎未传递.在考虑此问题的先前答案之前和之后,我已经多次测试过.我绝对难以接受,因为从我在其他地方读到的内容和到目前为止人们所建议的内容来看,一切似乎都是正确的.

Dim*_*hev 28

我对此有疑问:

  1. 是否有可能给定参数发送给所有我的xsl:使用XSL模板:应用模板以xsl:按名称特别是与-PARAM,但选择该值=实际的模板中,以便它可以在明确使用单个模板并被其他所有人忽略(即使我想在以后为其他模板添加其他不同名称的参数)?

是的.在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> 
Run Code Online (Sandbox Code Playgroud)

  <xsl:apply-templates select="testNode"> 
    <xsl:with-param name="testParam">TEST_PARAMETER</xsl:with-param> 
  </xsl:apply-templates> 
Run Code Online (Sandbox Code Playgroud)

你可以获得所需的输出.

此外,您可以使用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>
Run Code Online (Sandbox Code Playgroud)

XML文档:

<?xml-stylesheet type="text/xsl" href="main.xsl"?>
<testNode>
  <subNode/>
</testNode>
Run Code Online (Sandbox Code Playgroud)

结果:

  This is text1
  TEST_PARAMETER
  This is text2
Run Code Online (Sandbox Code Playgroud)

更新:

OP提供了更准确的信息,这证明了我的猜测.

现在很明显,问题是由允许选择元素节点的XSLT内置模板引起的wrapperNode.当然,这个模板不知道任何参数,它不使用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>
Run Code Online (Sandbox Code Playgroud)

现在,当在提供的XML文档上应用此转换时,将生成预期结果:

<html>
<body>
  TEST1
  TEST_PARAMETER
  TEST2
 </body>
</html>
Run Code Online (Sandbox Code Playgroud)