开发者

xsl: how to use parameter inside "match"?

开发者 https://www.devze.com 2023-03-07 23:45 出处:网络
My xsl has a parameter <xsl:param name=\"halfPath\" select=\"\'halfPath\'\"/> I want to use it inside mat开发者_如何转开发ch

My xsl has a parameter

<xsl:param name="halfPath" select="'halfPath'"/>

I want to use it inside mat开发者_如何转开发ch

<xsl:template match="Element[@at1='value1' and not(@at2='{$halfPath}/another/half/of/the/path')]"/>

But this doesn't work. I guess a can not use parameters inside ''. How to fix/workaround that?


The XSLT 1.0 W3C Specification forbids referencing variables/parameters inside a match pattern.:

"It is an error for the value of the match attribute to contain a VariableReference"

There is no such limitation in XSLT 2.0, so use XSLT 2.0.

If due to unsurmountable reasons using XSLT2.0 isn't possible, put the complete body of the <xsl:template> instruction inside an <xsl:if> where the test in conjunction with the match pattern is equivalent to the XSLT 2.0 match pattern that contains the variable/parameter reference(s).

In a more complicated case where you have more than one template matching the same kind of node but with different predicates that reference variables/parameters, then a wrapping <xsl:choose> will need to be used instead of a wrapping <xsl:if>.


Well, you could use a conditional instruction inside the template:

<xsl:template match="Element[@at1='value1']">
  <xsl:if test="not(@at2=concat($halfPath,'/another/half/of/the/path'))">
    .. do something
  </xsl:if>
</xsl:template>

You just need to be aware that this template will handle all elements that satisfy the first condition. If you have a different template that handles elements that match the first, but not the second, then use an <xsl:choose>, and put the other template's body in the <xsl:otherwise> block.

Or, XSLT2 can handle it as is if you can switch to an XSLT2 processor.


This topic had the answer to my question, but the proposed solution by Flynn1179 was not quite correct for me (YMMV). So try it the way it is suggested by people more expert than me, but if it doesn't work for you, consider how I solved it. I am using xsltproc that only handles XSL version 1.0.

I needed to match <leadTime hour="0024">, but use a param: <xsl:param name="hour">0024</xsl:param>. I found that: <xsl:if test="@hour='{$hour}'"> did not work, despite statements here and elsewhere that this is the required syntax for XSL v.1.0. Instead, the simpler <xsl:if test="@hour=$hour"> did the job.

One other point: it is suggested above by Dimitre that you put template inside if statement. xsltproc complained about this: instead I put the if statement inside the template:

<xsl:template match="leadTime">
  <xsl:if test="@hour=$leadhour">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:if>
</xsl:template>


In XSLT 2.0 you can refer to global variables within a match pattern, but the syntax is simpler than your guess:

<xsl:template match="Element[@at1='value1' and 
              not(@at2=$halfPath/another/half/of/the/path)]"/>

rather than

<xsl:template match="Element[@at1='value1' and 
              not(@at2='{$halfPath}/another/half/of/the/path')]"/>

Also, the semantics are not what you appear to be expecting: a variable referenced on the lhs of "/" must contain a node-set, not a fragment of an XPath expression.

0

精彩评论

暂无评论...
验证码 换一张
取 消