[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] 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
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|