xsl-list
[Top] [All Lists]

RE: [xsl] Showing unique rows at multiple levels

2006-10-04 23:13:01
Hi,

Your expression "//book[(bookshelf =
$bookshelfVar)]/author[not(.=preceding::author)]" is too strict (the
predicate too tolerant). You need to limit the preceding::author part to
match only authors that are on the same bookshelf. Similar thing for the
publisher. :-)

Besides, I would recommend trying to use keys and grouping techniques
like the Muenchian method. Something like:

(at top-level)

<xsl:key name="bookshelfs" match="bookshelf" use="." />
<xsl:key name="authors" match="author" use="concat(../bookshelf, '-',
.)" />

(inside bookshelf template)

<xsl:for-each select="key('bookshelfs', .)[1]">
  ...
</xsl:for-each>

(inside author template)

<xsl:for-each select="key('authors', concat(../bookshelf, '-', .)[1]">
  ...
</xsl:for-each>

Probably a lot quicker if your data file becomes larger. Using // is
usually very expensive in that case..

Kind regards,
Geert


   
 
Drs. G.P.H. Josten
Consultant
 
 

Daidalos BV
Source of Innovation
Hoekeindsehof 1-4
2665  JZ  Bleiswijk
Tel.: +31 (0) 10 850 1200
Fax: +31 (0) 10 850 1199
www.daidalos.nl
KvK 27164984


De informatie - verzonden in of met dit emailbericht - is afkomstig van 
Daidalos BV en is uitsluitend bestemd voor de geadresseerde. Indien u dit 
bericht onbedoeld hebt ontvangen, verzoeken wij u het te verwijderen. Aan dit 
bericht kunnen geen rechten worden ontleend.
 

Van: Glen Mazza [mailto:grm7790(_at_)verizon(_dot_)net] 
Verzonden: woensdag 4 oktober 2006 20:08
Aan: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Onderwerp: [xsl] Showing unique rows at multiple levels

Hello, for this input XML:

<books>
    <book>
        <title>T1</title>
        <author>A5</author>
        <publisher>P7</publisher>
        <bookshelf>B4</bookshelf>
    </book>
    <book>
        <title>T2</title>
        <author>A6</author>
        <publisher>P8</publisher>
        <bookshelf>B4</bookshelf>
    </book>
    <book>
        <title>T4</title>
        <author>A5</author>
        <publisher>P7</publisher>
        <bookshelf>B6</bookshelf>
    </book>
    <book>
        <title>T3</title>
        <author>A5</author>
        <publisher>P7</publisher>
        <bookshelf>B4</bookshelf>
    </book>
</books>

I would like an alphabetically sorted list of each unique 
bookshelf, and under each bookshelf, each unique author of at 
least one book on that shelf, and under each author, each 
unique publisher of at least one book by that author (on that shelf).

I.e., for the above, the following is desired:

B4
--A5   (show just once even though 2 books of A5)
----P7 (show just once even though 2 books of P7 under A5 on B4)
--A6
----P8
B6
--A5
----P7

Unfortunately, I am getting this:

B4
--A5
----P7
--A6
----P8
B6

where A5 and P7 are erroneously missing under shelf B6, because A5 and
P7 already happen to exist under shelf B4.  (In my sample 
data, if I rename A5 to say A15 and P7 to P17, i.e., nodes 
that don't exist elsewhere, these nodes then *will* appear under B6.)

Something is wrong with my filtering--I only want an author 
to be suppressed if it is already listed for the *same* 
shelf, and likewise with publishers under the same author 
(under the same shelf).

Here is my XSLT:

<xsl:stylesheet version="1.0"
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:template match="books">
    <xsl:for-each select="//bookshelf[not(.=preceding::bookshelf)]">
         <xsl:sort select="."/>
         <xsl:apply-templates select='.'/>
    </xsl:for-each>
</xsl:template>

<xsl:template match="bookshelf">
     <xsl:variable name="bookshelfVar" select="."/>
     <xsl:variable name="authorVar" select="../author"/>
     <xsl:value-of select="."/>
     <xsl:for-each select="//book[(bookshelf = 
$bookshelfVar)]/author[not(.=preceding::author)]">
         <xsl:sort select="."/>
         <xsl:apply-templates select='.'/>
     </xsl:for-each>
</xsl:template>

<xsl:template match="author">
     <xsl:variable name="bookshelfVar" select="../bookshelf"/>
     <xsl:variable name="authorVar" select="."/>
     --<xsl:value-of select="."/>
     <xsl:for-each select="//book[(bookshelf = $bookshelfVar) 
and (author = $authorVar)]/publisher[not(.=preceding::publisher)]">
         <xsl:sort select="."/>
         <xsl:apply-templates select='.'/>
     </xsl:for-each>
</xsl:template>

<xsl:template match="publisher">
     ----<xsl:value-of select="."/>
</xsl:template>

</xsl:stylesheet>

Can anyone see what I am doing wrong?  Any help would be appreciated.

Thanks,
Glen

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: 
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

<Prev in Thread] Current Thread [Next in Thread>