开发者

Is it possible to use a Dynamic xPath expression in a xslt style sheet?

I'd like to use the value of an xslt parameter in an xpath expression. Specifically, as part of a not() call in an <xsl:if expression.

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- my_param contains a string '/foo/bar', passed in from ant -->
    <!-- the 'no' is just a default value -->
    <xsl:param name="my_param">no</xsl:param>
    <xsl:variable name="var_myparam" select="$my_param" />
    <!-- ... -->

    <!-- this works -->
    <xsl:if test="not(/foo/bar)" /> <!-- expression returns boolean true -->
        <!-- ... -->
    </xsl:if>

    <!-- I can't figure out how to do this the right way -->
    <!-- None of these appear to work -->
    <xsl:if test="not($var_myparam)" /> <!-- expression returns boolean false -->
        <!-- ... -->
    </xsl:if>       
    <xsl:if test="not({$var_myparam})" /> <!-- complains Required attribute 'test' is missing -->
        <!-- ... -->
    </xsl:if>       
    <xsl:if test="not({$myparam})" />   <!-- complains Required attribute 'test' is missing -->
        <!-- ... -->
    </xsl:if>       
    <xsl:if test="not($myparam)" />     <!-- expression returns boolean false -->
        <!-- ... -->
    </xsl:if>       

</xsl:transform>

I'm a little unclear on what the correct syntax is for creating a dynamic xpath expression in an xslt style sheet. I'm also a little fuzzy on the difference between a paramater, a variable, and how expanstion of both works. For example, with parameters, I know that sometimes I need the brackets, and sometimes I don't.

<!-- when creating an element, it seems I need brackets -->
<xsl:element name="{$my_param}" />

<!-- when selecting an element value for the output stre开发者_StackOverflow中文版am, no brackets are needed -->
<xsl:value-of select="$my_param"/>

Any general/specific help would be greatly appreciated.


Check out http://www.exslt.org/. Specifically look at the dynamic:evaluate module.


XSLT doesn't support dynamic evaluation of XPath - that's why you need to use an extension function like EXSLT's evaluate to do it.

If you don't want to use extension functions (and there are good reasons not to), another possibility is to query the input document's DOM before you execute the transform, and pass the node-set into the transform as a parameter.

Edit

About those curly braces: Those are attribute value templates (AVTs). These are semantically equivalent in an XSLT transform:

<foo>
   <xsl:attribute name="bar">
      <xsl:value-of select="XPathExpression"/>
   </xsl:attribute>
</foo>

<foo bar="{XPathExpression}"/>

The second is just a shortcut for the first.

About variables and parameters: Syntactically, there's no difference between a variable and a parameter; anywhere you reference $foo in an XPath expression it will work the same whether foo is defined by xsl:variable or xsl:param.

The difference between the two is how they get populated. Variables are populated in the xsl:variable declaration. Parameters are declared in a named template using xsl:param, but they're populated by whatever calls the named template, using xsl:with-param, e.g.:

<xsl:call-template name="foo">
   <xsl:with-param name="bar" select="XPathExpression"/>
</xsl:call-template>

<xsl:template name="foo">
   <xsl:param name="bar"/>
   ...

The big honking exception to this is parameters that are a child of xsl:stylesheet. There's no way to populate those parameters within the transform; those are populated externally, by whatever (environment-specific) mechanism is invoking the transform.

A pretty common use case is making up for the fact that XSLT doesn't have a system date function. So you'll see something like:

<xsl:stylesheet ...
   <xsl:param name="system-date"/>
   ...

and then, when invoking the transform, something like this (in C#):

XsltArgumentList args = new XsltArgumentList();
args.AddParam("system-date", "", DateTime.Now.ToString("s"));
xslt.Transform(input, args, result);


Try some variation of this:

<xsl:if test="not($var_myparam = 'no'))">
</xsl:if>

The problem is in how XPath evaluates booleans. Any non-empty string will evaluate to true in XPath. Checkout this write-up about xpath booleans.

As for your other questions... Variables and parameters act the same as each other in XPath expressions. Both are referenced with the form $var.

For any XSLT attribute named "select," you don't need the brackets. The brackets are used in what are called "attribute value templates." You use them when XSLT is expecting a string, for example:

<xsl:template match="name-a">
  <xsl:variable name="old-name" select="name(.)" />
  <name-b old-name="{$old-name}" new-attribute="hello"  />
</xsl:template>

The XSLT spec talks about AVTs, and so does this page.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜