RE: Grouping and Unique Lists

Subject: RE: Grouping and Unique Lists
From: "Michael J. Dyer" <michael.dyer@xxxxxxxxxx>
Date: Wed, 29 Sep 1999 11:11:02 -0400
Bill,

Nice work.  I was really bothered by having to use a global.

BTW, I had a number of people on another forum suggest that I re-architect
my XML file grouping by category.  I was very opposed to the idea because it
would mean that I was mixing content with presentation in an extremely
subtle and difficult to detect manner (even though the processing might be
more efficient).

My application is really starting to look good now.  For those interested,
here's how things look:

  1.  A URL request comes in to Microsoft IIS.
  2.  An ISAPI DLL transfers the request data to a machine sitting in a
COM/DCOM pool.
  3.  The COM server selects data based on the URL request and places the
results into an XML structure (along with sections containing XML an
representation of the URL request data.
  4.  The COM server selects an HTML template to present the data.  The HTML
template contains scripting which can insert individual elements from the
XML structure or it can insert the HTML results from an XSL transformation
  5.  The resulting HTML is sent to the client (via IIS).

This approach also gives me the flexibility of returning the XML stream
directly or to send an XML/XSL combination for IE5 users.

Regards,

Michael




-----Original Message-----
From: owner-xsl-list@xxxxxxxxxxxxxxxx
[mailto:owner-xsl-list@xxxxxxxxxxxxxxxx]On Behalf Of Bill Martschenko
Sent: Wednesday, September 29, 1999 3:05 AM
To: xsl-list@xxxxxxxxxxxxxxxx
Subject: RE: Grouping and Unique Lists


OK, here is another xsl:script solution for IE5.  Its
merit is that it avoids the use of globals.  I have
concerns about that even though MS has pseudo-positive
statement about its usage.

I'll take that issue up in another post.

The attached XSL will sort on CATEGORY nodes which
will make the same category names adjacent, forming
category groups.  Walking the entire sorted list, we
output a category header only if it's first of a
group.

Recommend re-ordering the original XML from A, B, B, C
to C, B, A, B to see better what is going on.

Bill


<?xml version='1.0'?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/TR/WD-xsl";>

<xsl:template match="/">
    <h2>Original list of categories, unsorted,
ungrouped:</h2>
    <xsl:for-each select="//CATEGORY">
        <b><i><xsl:value-of select="."/></i></b><br/>
        number=<xsl:value-of select="../NUMBER"/>,
        description=<xsl:value-of
select="../DESCRIPTION"/>
        <br/>
    </xsl:for-each>

    <br/><br/>

    <h2>Sorted, grouped list of categories:</h2>
    <xsl:for-each select="//CATEGORY" order-by=".">
        <!-- IsCategoryStart(this) returns whether
context node. a category -->
        <!-- is also the first category of its kind,
in document order.     -->
        <!-- This test is valid here for grouping
because the "ordered-by"  -->
        <!-- predicate above must do a "stable sort".
Here, stable sort    -->
        <!-- means preserve document order for sorting
keys that match.     -->
        <xsl:if
expr="IsCategoryStart(this)"><b><i><xsl:value-of
select="."/></i></b><br/></xsl:if>
        number=<xsl:value-of select="../NUMBER"/>,
        description=<xsl:value-of
select="../DESCRIPTION"/>
        <br/>
    </xsl:for-each>
</xsl:template>

<xsl:script>
    function FirstCategory(categoryNode)
    {
        // define pattern for selecting first node in
the same category, in document order
        // example:  (//CATEGORY)[.='Category A'][0]
        pattern = "(//CATEGORY)[.='" +
categoryNode.text + "'][0]";
        return categoryNode.selectSingleNode(pattern);
    }

    function IsCategoryStart(categoryNode)
    {
        return uniqueID(FirstCategory(categoryNode))
== uniqueID(categoryNode);
    }
</xsl:script>

</xsl:stylesheet>


--- Bill Martschenko <billmartschenko@xxxxxxxxx>
wrote:
> Ah, I can't keep up with you, Michael. :-)  I was
> going to try at home tonight...
>
> Just a tidbit to enhance:
>
> The line
>        <xsl:for-each select="/ITEMLIST/ITEM">
> should read
>        <xsl:for-each select="/ITEMLIST/ITEM"
> order-by="CATEGORY">
>
> This way, the input <ITEM>'s can be any order.
>
> Note to IE5 users:  IE5 does not support xsl:sort.
> I
> recall that "order-by" has been depracated.  Know
> that
> IE5's XSLT is based on the Dec 98 working draft.
> The
> latest draft is Aug 99.
>
> I was also surprised to learn about case
> sensitivity.
> Micheal's script did not work at all for me until I
> changed all the element names to lower case to match
> my XML.
>
> I didn't think XML tags were case sensitive.
>
> What's the story here?
>
> Bill
>
>
>
> --- "Michael J. Dyer" <michael.dyer@xxxxxxxxxx>
> wrote:
> > Bill,
> >
> > You're absolutely right - IE doesn't support the
> > "preceding-sibling"
> > construct and the XSL script won't work.  However,
> I
> > was able to do a
> > workaround using JavaScript.
> >
> > There are three JavaScript functions -
> > SetCurrentGroup, GetCurrentGroup and
> > IsNewGroup.  I'm not really using GetCurrentGroup
> ,
> > but it's there just to
> > be complete.  You'll node that when I call the
> > IsNewGroup and
> > SetCurrentGroup, I pass 'this' along with a text
> > string that represents the
> > node I want (relative to this).
> >
> > Hope this helps...
> >
> > Regards,
> >
> > Michael
> >
> >
> > <?xml version='1.0'?>
> > <xsl:stylesheet
> > xmlns:xsl="http://www.w3.org/TR/WD-xsl";>
> >
> >   <xsl:template match="/">
> >
> >       <xsl:for-each select="/ITEMLIST/ITEM">
> >
> >         <xsl:if expr="IsNewGroup(this,
> 'CATEGORY')">
> > 	    <xsl:eval>
> >             SetCurrentGroup(this, 'CATEGORY')
> >           </xsl:eval>
> >           <xsl:value-of select="CATEGORY"/>
> > 	  </xsl:if>
> >
> >         <xsl:value-of select="NUMBER"/>
> > 	  <xsl:value-of select="DESCRIPTION"/>
> >
> >       </xsl:for-each>
> >
> >   </xsl:template>
> >
> >   <xsl:script>
> >
> >     cCurrentGroup = "_empty_" ;
> >
> >     function SetCurrentGroup(cThis, cChar)
> >       {
> > 	cValue = cThis.selectSingleNode(cChar).text ;
> > 	cCurrentGroup = cValue ;
> > 	return "" ;
> > 	}
> >
> >     function IsNewGroup(cThis, cChar)
> >       {
> > 	cValue = cThis.selectSingleNode(cChar).text ;
> > 	if (cValue == cCurrentGroup)
> >         cReturn = false ;
> > 	else
> > 	  cReturn = true ;
> > 	return cReturn ;
> > 	}
> >
> >     function GetCurrentGroup()
> > 	{
> > 	return cCurrentGroup ;
> > 	}
> >
> >   </xsl:script>
> >
> > </xsl:stylesheet>
> >
> >
> > -----Original Message-----
> > From: owner-xsl-list@xxxxxxxxxxxxxxxx
> > [mailto:owner-xsl-list@xxxxxxxxxxxxxxxx]On Behalf
> Of
> > Bill Martschenko
> > Sent: Tuesday, September 28, 1999 3:20 PM
> > To: xsl-list@xxxxxxxxxxxxxxxx
> > Subject: RE: Grouping and Unique Lists
> >
> >
> > Excellent.
> >
> > I'd like to add that IE5 can't handle it.  IE5
> > doesn't
> > support all of the XSLT constructs.
> > "preceding-sibling" is one of them.
> >
> > I have an IE5 solution in the works that uses
> > xsl:script to get past some of the limitations.
> >
> > The basic ideas are the same:  start with a sorted
> > list and then as you process them in order check
> > your
> > predecessor to see if you are first one in a
> group.
> >
> > More later--if I succeed :-)--for any IE5
> > audience...
> >
> > Bill
> >
> >
> >
> > --- "Sargeant, Richard (GEIS)"
> > <Richard.Sargeant@xxxxxxxxxxx> wrote:
> > > Hi,
> > >
> > >    I have not tried this with IE5 but this works
> > for
> > > me and produces exactly
> > > the output you specified... FYI I created and
> > > previewed this using the
> > > Stylus beta editor and then tested it with
> > Oracle's
> > > XMLparser.
> > >
> > >
> > >
> > > <xsl:stylesheet
> > > xmlns:xsl="http://www.w3.org/XSL/Transform/1.0";>
> > >
> > > <xsl:template
> > >
> match="*|/"><xsl:apply-templates/></xsl:template>
> > >
> > > <xsl:template match="text()|@*"><xsl:value-of
> > > select="."/></xsl:template>
> > >
> > > <xsl:template match="ITEMLIST">
> > >         <xsl:apply-templates select="ITEM"/>
> > > </xsl:template>
> > >
> > > <xsl:template match="ITEM">
> > >         <xsl:if test =
> > >
> >
>
"not(CATEGORY=preceding-sibling::ITEM[position()=1]/CATEGORY)">
> > >                 <xsl:value-of
> > > select="CATEGORY"/><br/>
> > >         </xsl:if>
> > >         <xsl:value-of select="NUMBER"/>
> > >         <xsl:text> </xsl:text>
> > >         <xsl:value-of
> select="DESCRIPTION"/><br/>
> > > </xsl:template>
> > >
> > > </xsl:stylesheet>
> > >
> > >
> > > regards
> > >    Richard Sargeant
> > >
> > >
>
=== message truncated ===

__________________________________________________
Do You Yahoo!?
Bid and sell for free at http://auctions.yahoo.com


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread