xsl-list
[Top] [All Lists]

RE: [xsl] Selecting similar XML nodes by a sort criteria

2007-10-05 09:46:30
::blink::

Well hey, good eye. I've seen that pattern so many times, I've never
given a second thought to the [1] part. I guess it's a little clearer
at-a-glance that you're only looking for the first node in the key()
node-set, but since generate-id() only looks for the first one anyway, I
guess you don't need it.

~ Scott


-----Original Message-----
From: Chaudhary, Harsh [mailto:HCHAUDHA(_at_)amfam(_dot_)com] 
Sent: Friday, October 05, 2007 11:36 AM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: RE: [xsl] Selecting similar XML nodes by a sort criteria

Another question.

In your code, you have this line: 

<xsl:template match="pile">
   <xsl:for-each 
select="item[generate-id()=generate-id(key('item-by-number',@number)[1])
]">

What is the significance of [1] in the generate-id() function call?

Harsh.

-----Original Message-----
From: Chaudhary, Harsh 
Sent: Friday, October 05, 2007 11:03 AM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: RE: [xsl] Selecting similar XML nodes by a sort criteria


Wendell,

Thanks for the detailed response. I am using Xalan. But your email
helped me a lot and resolved the issue I was having. Also, its a nice
little intro to the Meunichian method.

Thanks a lot. You too David.

Harsh.

-----Original Message-----
From: Wendell Piez [mailto:wapiez(_at_)mulberrytech(_dot_)com] 
Sent: Thursday, October 04, 2007 4:34 PM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: RE: [xsl] Selecting similar XML nodes by a sort criteria


Harsh,

At 04:46 PM 10/4/2007, you wrote:
Before that, the color has nothing to do with the areacode being even
or
odd.

You didn't say that, and neither did your data, but it wasn't hard to
guess.

For example -->

Original data:  1/2/3/4/5
Desired colors: B/G/B/G/B

Original data: 1/2/3/2/5
Sorted data: 1/2/2/3/5
Desired colors: B/G/G/B/G

Unfortunately, I can't use XSLT 2.0.

The next question is whether you can use a node-set() extension 
function. (This would depend on your processor and operational 
requirements, but you haven't said what processor you're using, so 
again we have to guess.) If you can, two passes on the data would 
make this easier, at any rate conceptually.

Well, okay ... here's an adaptation of a grouping algorithm to handle 
it (no extensions necessary):

Input:

<pile>
   <item name="Albert" number="1"/>
   <item name="Berenice" number="4"/>
   <item name="Camille" number="4"/>
   <item name="Dora" number="2"/>
   <item name="Eustace" number="5"/>
</pile>

stylesheet:

<xsl:key name="item-by-number" match="item" use="@number"/>
<!-- allows us to select item elements in global scope by means of 
their @number -->

<xsl:template match="pile">
   <xsl:for-each 
select="item[generate-id()=generate-id(key('item-by-number',@number)[1])
]">
     <!-- iterating over each first item in the group of items with 
its number -->
     <xsl:sort select="@number"/>
     <!-- sorting by number -->
     <xsl:variable name="color">
       <xsl:choose>
         <xsl:when test="position() mod 2">red</xsl:when>
         <!-- assigning color red to first items in odd position 
among first items -->
         <xsl:otherwise>green</xsl:otherwise>
         <!-- assigning green to the others -->
       </xsl:choose>
     </xsl:variable>
     <xsl:for-each select="key('item-by-number',@number)">
       <!-- iterating over all the items with this @number -->
       <tr bgcolor="{$color}">
         <td>
           <xsl:value-of select="@number"/>
         </td>
         <td>
           <xsl:value-of select="@name"/>
         </td>
       </tr>
     </xsl:for-each>
   </xsl:for-each>
</xsl:template>

This uses the standard XSLT 1.0 idiom to select a set of nodes 
representing a set of groups of nodes, by selecting the single node 
whose generated id is the same as the generated id of the first node 
in the group. A key is used to collect members of the group.

Once we have this set (of first items in their groups), we can select 
it with a for-each, which also gives us a context size and context 
position for each -- the context position (returned by the position() 
function) of course alternates between odd and even.

The technique is generally called "Muenchian grouping" after Steve 
Muench, who first applied a key to the problem (thereby optimizing 
its performance significantly), although it's probably safe to say 
that several different people contributed to its development.

Oh -- output:

<tr bgcolor="red">
    <td>1</td>
    <td>Albert</td>
</tr>
<tr bgcolor="green">
    <td>2</td>
    <td>Dora</td>
</tr>
<tr bgcolor="red">
    <td>4</td>
    <td>Berenice</td>
</tr>
<tr bgcolor="red">
    <td>4</td>
    <td>Camille</td>
</tr>
<tr bgcolor="green">
    <td>5</td>
    <td>Eustace</td>
</tr>

I hope this helps,
Wendell



======================================================================
Wendell Piez                            
mailto:wapiez(_at_)mulberrytech(_dot_)com
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
   Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================


--~------------------------------------------------------------------
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>
--~--

--~------------------------------------------------------------------
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>