[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: XPath's role (Was: Re: Re: . in for)

Subject: Re: XPath's role (Was: Re: Re: . in for)
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Mon, 7 Jan 2002 16:25:05 +0000
xpath lower case
Hi Mike,

> Basically, there is no way in XSLT of constructing a sequence. The
> only thing you can construct using XSLT instructions are trees.
> Given the addition of sequences to the data model, we needed to
> provide some way of constructing a sequence. Doing it in XPath,
> rather than by adding new XSLT instructions, (a) gives us a greater
> level of commonality with XQuery, and (b) gives better
> composability.

I disagree with the statement that there is no way of constructing a
sequence in XSLT, assuming that you were talking about XSLT 2.0 plus
XPath 1.0. XSLT 2.0 gives us xsl:function, and xsl:function enables us
to construct sequences because it allows us to return things other
than trees.

Writing your own (often recursive) functions with xsl:function is
undoubtedly too complicated for basic sequence generation, which is
why I suggested a simple mapping operator.

The other thing that I think makes sequence generation possible
(though not particularly efficient) for simple typed values is the
presence of the type attribute on xsl:variable. Assuming that:

  <xsl:variable name="numbers"
                select="'1 2 3'"
                type="xs:integer+" />

assigns the sequence (1, 2, 3) to the $numbers variable (this rests on
an unresolved issue, I think, but it looks as though it's a
possibility), I don't see why:

<xsl:variable name="numbers" type="xs:integer+">
  <xsl:for-each select="(1 to 3)">
    <xsl:value-of select="." />
    <xsl:if test="position() != last()">
      <xsl:text> </xsl:text>
    </xsl:if>
  </xsl:for-each>
</xsl:variable>

should not do the same thing.

> Using <xsl:for-each> at the XSLT level is no substitute for XPath
> facilities. You can't use <xsl:for-each> to return those <employee>s
> whose deparment is in a list of departments supplied as a parameter,
> because <xsl:for-each> doesn't return anything, it constructs a
> tree, and the tree can't contain original <employee> nodes, it can
> only contain copies. You can use <xsl:for-each> to find *and
> process* those employees, if you want to do both at the same time;
> but this lacks composability because you can't put the list of
> selected employees into a variable and do other things with it, such
> as selecting the top ten earners from among them, grouping them by
> location, etc.
>
> How else would you do:
>
> <xsl:variable name="emps"
>   select="//employee[some $d in $departments
>                      satisfies lower-case(./@dept) = $d]"/>
> <xsl:if test="count($emps) > 10">
>   <xsl:for-each-group select="$emps" group-by="@location">
>     ...
> etc.

I think you meant:

  <xsl:variable name="emps"
    select="//employee[some $d in $departments
                       satisfies @dept = lower-case($d)]"/>

Otherwise I think the existential semantics of = are sufficient?

This example could be handled with a mapping operator:

  <xsl:variable name="emps"
    select="//employee[@dept = ($departments -> lower-case(.))]" />

In the more general case you could handle it with a function. Assuming
that $departments is a global variable (otherwise it has to be passed
as an argument, but that's not a problem, just makes me have to type
more):

<xsl:function name="my:in-dept">
  <xsl:result select="if (not($departments))
                           then false()
                      else if (@dept = lower-case($departments[1]))
                           then true()
                      else my:in-dept(sublist($departments, 2))" />
</xsl:function>

and:

  <xsl:variable name="emps"
                select="//employee[my:in-dept()]" />


Keep the examples coming :) My point is that the mapping operator
handles simple cases; user-defined functions can handle the rest; and
if you have the will to make the type attribute on xsl:variable do a
cast, xsl:for-each could also be used to create sequences of simple
typed values.
                
Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


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


Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.