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

Re: Is this a legal XPath Expression?

Subject: Re: Is this a legal XPath Expression?
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Thu, 15 Mar 2001 13:08:21 +0000
xpath exp
Hi Phil,

> Basically what I am doing is TRying to find unique occurrences of
> the contents of cells in column 15 of an HTML table, e.g
[snip]
> , then, for each of these, pick out unique occurrences of the
> contents of cells in column 28, and for each of those, pick out the
> contents of cell 3. Looks like a job for <saxon:group>, but I
> couldn't figure out how to do it, so my code looks like this: (it
> works, but its v. inefficient!)

I'd use keys for this (i.e. the Muenchian Method), and index each
*row* according to:

  (a) column 15
  (b) column 15 + column 28
  (c) column 15 + column 28 + column 3

The three keys would be:

<xsl:key name="group-15"      match="TR"
         use="TD[15]" />
<xsl:key name="group-15-28"   match="TR"
         use="concat(TD[15], '::', TD[28])" />
<xsl:key name="group-15-28-3" match="TR"
         use="concat(TD[15], '::', TD[28], '::', TD[3])" />

Now you should apply templates to only the unique rows. In the first
go, those are the rows where they're the first node in the list
returned when you use the 'group-15' key with a value of their own
TD[15] child.  So apply templates with:

<xsl:apply-templates
   select="TR[count(.|key('group-15', TD[15])[1]) = 1]"
   mode="group-15" />

The count() expression counts how many nodes there are in the node set
consisting of (a) the TR element you're looking at and (b) the first
of the nodes returned by the 'group-15' key when you use an index
value of the TR element that you're looking at's TD[15] child.

Then you can have a template that matches the TR elements in
'group-15' mode.  This template will only ever be applied to the
TR elements with unique values for their TD[15] child, so you don't
have to worry about testing the TR element for uniqueness.  Here, you
apply templates according to the second grouping in a very similar way
to how it's done above.

<xsl:template match="TR" mode="group-15">
   <xsl:variable name="subject" select="TD[15]" />
   <xsl:if test="string($subject)">
      <xsl:variable name="link" select="generate-id($subject)"/>
      <tr>
         <td>
            <a href="{$link}.html"><xsl:value-of select="$subject"/></a>
         </td>
      </tr>
      <!-- for each subject, output the project title to a sep. file-->
      <saxon:output file="{concat($link, '.html')}">
         <html><head></head>
            <body><table>
               <xsl:apply-templates
                   select="//TR[count(.|key('group-15-28',
                                            concat($subject, '::', TD[28])[1]) = 1]"
                   mode="group-15-28" />
            </table></body>
         </html>
      </saxon:output>
   </xsl:if>
</xsl:template>

Then you have another template that matches TR elements but in
group-15-28 mode.  Again it applies templates to the uniquely valued
table rows only:

<xsl:template match="TR" mode="group-15-28">
   <xsl:variable name="subject" select="TD[3]" />
   <xsl:variable name="projecttitle" select="TD[28]" />
   <xsl:if test="string($projecttitle)">
      <xsl:variable name="link" select="generate-id($projecttitle)" />
      <tr>
         <td>
            <a href="{$link}.html"><xsl:value-of select="$projecttitle"/></a>
         </td>
      </tr>

      <!-- for each project, output the filename to a sep. file-->
      <saxon:output file="{concat($link, '.html')}">
         <html><head></head>
            <body><table>
               <xsl:apply-templates
                   select="//TR[count(.|
                                      key('group-15-28-3',
                                          concat($subject, '::',
                                                 $projecttitle, '::',
                                                 TD[3])[1]) = 1]"
                   mode="group-15-28-3" />
            </table></body>
         </html>
      </saxon:output>

   </xsl:if>
</xsl:template>

And finally a template that matches in group-15-28-3 mode:

<xsl:template match="TR" mode="group-15-28-3">
   <xsl:variable name="fn"  select="TD[3]"/>
   <tr>
      <td>
         <a href="{$fn}">Download <xsl:value-of select="$fn"/></a>
      </td>
   </tr>
</xsl:template>

This is untested as I didn't have a sample.  But I think it should
roughly work.

I hope that helps,

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.