This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RE: Grouping examples make my head spin


> My data file is hierachical:
> 
> <contractors>
>   <contractor id="x" name="A">
>     <contract org="1596" contract-id="89" name="SuperDuperIII">
>       <contractType>System</contractType>
>       <deliverable>Application Development</deliverable>
>     </contract>
>     <contract org="98" contract-id="75" name="SixtySix">
>       <contractType>Non-system</contractType>
>       <deliverable>Neon Routers</deliverable>
>     </contract>
>   </contractor>
>   <contractor id="16" name="W">
>     <contract org="1596" contract-id="1365" name="Bosco">
>       <contractType>System</contractType>
>       <deliverable>Application Development</deliverable>
>     </contract>
>     <contract org="98" contract-id="258" name="Xanadu">
>       <contractType>System</contractType>
>       <deliverable>Application Development</deliverable>
>     </contract>
>   </contractor>
> </contractors>
> 
>  I want to outpt HTML. I want each distinct value for 
> /contractors/contractor/contract/@org
> to be output exactly once, with a list (format irrelevant for 
> the purposes of the exercise) of 
> /contractors/contractor/@name below that, one for each 
> contractor which has a contract with 
> /contractors/contractor/contract/@org.

Because you are grouping on the value of a node, you can use either of
the two common techniques for finding distinct values.

The simpler approach is:

/contractors/contractor/contract[not(@org=preceding::contract/@org]

Note the use of "preceding" rather than preceding-sibling.

But this probably will be rather inefficient, so Muenchian grouping is
probably better. Muenchian grouping uses the same logic whether or not
the nodes to be grouped are siblings.
> 
> If I find a new value, I want to emit an HTML 
> div element with that value, if the value has already been 
> encountered, I want to emit an HTML div element containing 
> the value of /contractors/contractor/@name.

That sounds dangerously like procedural thinking. Always think of
grouping problems in terms of two nested loops driven by the output you
want to generate (not the input that you are processing). In the outer
loop you want to select one representative of each group of nodes with
the same @org value, and the inner loop you want to select all the nodes
within that group.

Michael Kay
Software AG
home: Michael.H.Kay@ntlworld.com
work: Michael.Kay@softwareag.com 


> 
> I have tried this template:
> 
> <xsl:template name="byPO" match="*">
>   <xsl:for-each select="/contractors/contractor/contract">
>     <div>Contract Org: <xsl:value-of select="@org" /></div>
>     <div>Immediate preceeding sibling&apos;s contract Org: 
> <xsl:value-of select="preceding-sibling[1]/@org" /></div>
>   </xsl:for-each>
> </xsl:template>
> 
> but the output shows me that no 
> /contractors/contractor/contract has an immediately 
> preceeding sibling, which I can see is not true, so there for 
> I am missing something in my understanding of <xsl:value-of 
> select="preceding-sibling[1]/@org"
> />.
> 
> As usual, all help gratefully received.
> Thanks.
> 
> -- 
> Charles Knell
> cknell@onebox.com - email
>  
> 
>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
> 


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]