RE: [xsl] Preceding-Sibling Axes in Context node.

Subject: RE: [xsl] Preceding-Sibling Axes in Context node.
From: "Patel, Viral" <viral.patel@xxxxxxxxxxxxxxxxxxxx>
Date: Wed, 21 Apr 2004 10:47:37 -0500
Wendell,

Thanks for your feedback. The fact is that my xml file is huge and I am
trying to avoid multiple passes if possible.  Also I am guessing that
<xsl:key> would be a lot of overhead. Thats why I tried to do
preceding-sibling and see if in my current context if the current city that
I processed has the same state as the last city that I processed.  If yes,
then just process that city.  If no, then I want to create a new row, output
the state name and then process that city.  

But unfortunately, it sounds like its not possible unless I do several
passes through the xml document?  Any other possible suggestions?  How
expensive are the xsl:key and indexing that it does? 

Thanks for your help,
Viral.

-----Original Message-----
From: Wendell Piez [mailto:wapiez@xxxxxxxxxxxxxxxx]
Sent: Wednesday, April 21, 2004 10:17 AM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Preceding-Sibling Axes in Context node.


Hi Viral,

At 10:35 AM 4/21/2004, you wrote:
>I have a question about preceding-sibling.

Okay.

>   I have following XML
>
><root>
>
><record id="1" city="Carbondale" state="IL"/>
><record id="2" city="Columbia" state="MO"/>
><record id="3" city="Bloomington" state="IL"/>
><record id="4" city="St. Louis" state="MO"/>
><record id="5" city="Chicago" state="IL"/>
>
></root>
>
>And I have following XSL:
>
><?xml version="1.0" encoding="UTF-8"?>
><xsl:stylesheet version="1.0"
>xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>xmlns:fo="http://www.w3.org/1999/XSL/Format";>
><xsl:template match="/">
>         <table>
>                 <xsl:apply-templates match="//root/record">
>                         <xsl:sort select="@state"/>
>                         <xsl:sort select="@city"/>
>                 </xsl:apply-templates>
>         </table>
></xsl:template>
>
><xsl:template match="record">
>         <xsl:if test="not ( (preceding-sibling::*/@state) = @state )">
>                 <!-- Some logic that will print out the create a new table
>row (tr) and print out the state name....-->
>         </xsl:if>
>         <td><xsl:value-of select="@city"/></td>
></xsl:template>
>
></xsl:stylesheet>
>
>What I want is an output where it would to create one table row per state
>and list all of its city in the same row but a different <td>.  In my root
>template I am sorting the document by state when I do apply templates.  In
>the "record" template, I do when I do "preceding-sibling::*/@state" it
would
>bring me back the state attribute of the preceding sibling in the acutal
xml
>document and not in the current context.

Correct, except for one thing: preceding-sibling::*/@state will bring back 
the @state attributes on *all* preceding siblings of your context node. To 
get the immediately preceding sibling only, use
preceding-sibling::*[1]/@state.

>So for example if I just did apply-templates sorted by state and city, xsl
>should process my nodes in the order below and I have also printed out the
>"preceding-sibling" value that my xsl is giving me for each node and the
>"preceding-sibling" value that I would expect.:
>
>IL, Bloomington
>         -XSL's preceding-sibling: MO, Columbia
>         -Preceding-Sibling value that I would like: none
>IL, Carbondale
>         -XSL's preceding-sibling: none
>         -Preceding-Sibling value that I would like: IL, Bloomington
>IL, Chicago
>         -XSL's preceding-sibling: MO, St. Louis
>         -Preceding-Sibling value that I would like: IL, Carbondale
>MO, Columbia
>         -XSL's preceding-sibling: IL, Carbondale
>         -Preceding-Sibling value that I would like: IL, Chicago
>MO, St. Louis
>         -XSL's preceding-sibling: IL, Bloomington
>         -Preceding-Sibling value that I would like: MO, Columbia
>
>What would I need to do to achieve the preceding-sibling value that I want?
>Is it even possible?  I already tried using <xsl:key> but that didnt work
>either.  If you want me to explain my question then let me know.

I hesitate to say it's not possible, but it's certainly not practical in 
XSLT 1.0. The best approaches to getting access to the sorted order are: 
(1) process in two passes with two different stylesheets (first sort, then 
remove duplicates); (2) process in two passes with a node-set() extension 
function to turn the result-tree-fragment representing your sorted order 
into a node set you can process (then the axis will work the way you want); 
(3) do the same in XSLT 2.0, where no node-set() extension function is
needed.

But I'm not convinced you actually need to do this. For de-duplication 
purposes (making sure each state, or for that matter each city, is 
processed only once), access to the pre-sorted order will work fine, won't
it?

Cheers,
Wendell


======================================================================
Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
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
======================================================================

Current Thread