[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] How to properly use Key elements


Subject: Re: [xsl] How to properly use Key elements
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxx>
Date: Mon, 14 Oct 2013 09:58:53 -0400

Hi Ted,

First, a caution. Before you find yourself thinking about Muenchian
grouping in 2013 you should ask whether you really have no option but
to use XSLT 1.0. XSLT 2.0 is far superior in many respects, including
the availability of xsl:for-each-group. I acknowledge that there may
be other reasons to explore Muenchian grouping besides having no
choice, so I don't want to discourage your question. But why try to
bake bread on an open fire when stoves are readily available, etc.

So:

<xsl:key
        name="ports-by-ship"
        match="td[position() = (count(.) - 1)]"
        use="tr[count(td) = 4]/td[position() = 1]"
 />

is legal, but wrong. It won't work because

a. count(.) will always return '1' so your key will never match,
because position() will never be 0.

b. use='tr[etc]' will use the values of (certain) 'tr' children of
your matched 'td' elements as key values, but 'td' never has 'tr'
children, so even if the key matched, you'd have empty string key
values.

To devise a correct solution, I suggest

1. Considering whether you can't use XSLT 2.0 for-each-group.

2. If not, consider whether doing this in two passes would simplify
the problem. (In the first pass you would label the td elements with
their information types, simplifying the declaration of the key for
the second pass.)

3. If neither of these, please clarify the logic whereby you know
which td is of which type.

At a higher level, I think the essence of the problem here is that you
aren't accounting for evaluation context properly in devising your
XPaths. Some review of the design and functionality of keys (apart
from how to do Muenchian grouping) would be effort well spent. Keys
are extremely useful in XSLT 2.0 as well! though no longer so
necessary for grouping.

A sample of required output for your input might be helpful in
presenting your problem to us.

Cheers, Wendell

Wendell Piez | http://www.wendellpiez.com
XML | XSLT | electronic publishing
Eat Your Vegetables
_____oo_________o_o___ooooo____ooooooo_^


On Sun, Oct 13, 2013 at 8:41 PM, G. T. Stresen-Reuter
<tedmasterweb@xxxxxxxxx> wrote:
> Hi,
>
> I've read (and reread) Jeni Tenison's description of Muenchian Grouping
several times and when my example is similar in structure to her example, I'm
able to use it quite effectively but when my source XML varies from her
example, I'm a bit lost.
>
> I'm wondering if I can create a key to group on ShipName and/or RouteNum. As
a complication, I don't knowing anything more than the fact that ShipName is a
preceding sibling and that there will be 4 TD elements in rows that contain
ShipName.
>
> XML
>
> <table>
>         <tbody>
>                 <tr>
>                         <td rowspan="6">ShipName</td>
>                         <td rowspan="3">RouteNum</td>
>                         <td>PortName</td>
>                         <td>PortCode</td>
>                 </tr>
>                 <tr>
>                         <td>PortName</td>
>                         <td>PortCode</td>
>                 </tr>
>                 <tr>
>                         <td>PortName</td>
>                         <td>PortCode</td>
>                 </tr>
>                 <tr>
>                         <td rowspan="3">RouteNum</td>
>                         <td>PortName</td>
>                         <td>PortCode</td>
>                 </tr>
>                 <tr>
>                         <td>PortName</td>
>                         <td>PortCode</td>
>                 </tr>
>                 <tr>
>                         <td>PortName</td>
>                         <td>PortCode</td>
>                 </tr>
>
>                 {b& repeat rows b&}
>
>         </tbody>
> </table>
>
>
> My question is if I can "legally" define a KEY element like this:
>
> <xsl:key
>         name="ports-by-ship"
>         match="td[position() = (count(.) - 1)]"
>         use="tr[count(td) = 4]/td[position() = 1]"
>  />
>
> The XSL spec says that "match" should be a "pattern" while "use" can be an
"expression". I'm not exactly sure what they mean by expression, how it is
different from a pattern match that uses a predicate.
>
> I've been unable to get this to work but it sure would be handy if I could.
>
> Thanks to anyone who can lend a hand. I've been off the list for years but
recently found myself (happily) doing some more xslt.
>
> Sincerely,
>
> Ted Stresen-Reuter


Current Thread
Keywords