Re: [xsl] Putting parameter into XPATH expression

Subject: Re: [xsl] Putting parameter into XPATH expression
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Fri, 22 Jun 2001 16:06:19 +0100
James:

At 08:23 PM 6/22/01, you wrote:
Hi,

In the code extract below, I always get the result "OneOneOne" instead of
"OneTwoThree" which I am expecting.

I found a work around (based on my previous experience writing compilers)
that gets XSL processor to do what I want: "<xsl:value-of
select="a/b[$Position + 0 ]/c"/>"

Your code is working this way because you are sending strings into your named templates as parameters, not numbers. So the expression


<xsl:value-of select="a/b[$Position ]/c"/>

is returning a set of nodes including *all* <c> elements (since a non-empty string tests as true, b[$Position] gets you every <b> element in that step). The value of a set of nodes is the value of the first node in the set, hence OneOneOne.

<xsl:value-of select="a/b[$Position + 0 ]/c"/>

is working the way you want because adding a number (0) to a string ($Position), the processor casts the string to a number as if by the number() function, effectively changing the predicated expression into a number.

Far easier would be simply to pass numbers in as parameters, not strings, which you could do by saying

<xsl:with-param name="Position" select="1"/>

instead of <xsl:with-param name="Position" select="'1'"/> (which you have now).

But why not just write a stylesheet that traverses the tree in the normal way? In fact, in your case the null stylesheet

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"/>

would get you the output OneTwoThree, since the built-in default templates process the tree recursively, copying text nodes to output. (Well, actually it won't, because of the whitespace floating around your source document, which the processor will also faithfully copy; but it would if you stripped whitespace nodes with an <xsl:strip-space elements="*"/> statement. Try it, you'll see what I mean.)

Confused? It's all because of XSLT's powerful and really-not-so-mysterious processing model (that you do have to learn if you want to know how to make things work easily). Want to prevent those text nodes (or any other nodes that might happen to be around) from getting in the way? the stylesheet

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:template match="/">
  <xsl:for-each select="//c">
     <xsl:apply-templates/>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

will get you the output you want.

But maybe you want to jump around arbitrarily, controlling the flow order by some logic in the stylesheet, not the source document? Then maybe you need something like what you're writing. If you simply want output that reflects the content of the input in its native order, XSLT is designed to do that anyway with minimal fuss.

Regards,
Wendell

Can someone tell me a better (more correct) way to do this?

XML ------------------
<?xml version="1.0" encoding="ISO-8859-1"?>
<a>
  <b>   <c>One</c> </b>
  <b>   <c>Two</c> </b>
  <b>   <c>Three</c> </b>
</a>


In my XSL, I do the following to write out the words One, Two and Three ---------------

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:output method="text"/>

<xsl:template match="/">
                                <xsl:call-template name="Jump">
                                    <xsl:with-param name="Position"
select="'1'"/>
                                </xsl:call-template>

                                <xsl:call-template name="Jump">
                                    <xsl:with-param name="Position"
select="'2'"/>
                                </xsl:call-template>

                                <xsl:call-template name="Jump">
                                    <xsl:with-param name="Position"
select="'3'"/>
                                </xsl:call-template>
</xsl:template>

<xsl:template name="Jump">
                <xsl:param name="Position"/>

<xsl:value-of select="a/b[$Position ]/c"/>

</xsl:template>


======================================================================
Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
  Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================


XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list



Current Thread