This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]