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]

Re: Is this a legal XPath Expression?


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


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