This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: Summarizing sibling nodes
- To: xsl-list at lists dot mulberrytech dot com
- Subject: Re: [xsl] Summarizing sibling nodes
- From: Wendell Piez <wapiez at mulberrytech dot com>
- Date: Wed, 14 Mar 2001 18:14:06 +0000
- Reply-To: xsl-list at lists dot mulberrytech dot com
Hi Wayne,
The problems here are in your XPath expressions. They're not doing quite
what you expect.
Let's look at that for-each select first:
The XPath:
Truck[not(VINModelYearName/preceding::Truck/VINModelYearName)]
| Truck[not(VINModelName/preceding::Truck/VINModelName)]
translates into (sort-of) English as
"All Truck element children that do not have a VINModelYearName child that
are preceded (somewhere in the document) by a Truck element with a
VINModelYearName child, ALONG WITH
all Truck element children that do not have a VINModelName child that are
preceded (somewhere in the document) by a Truck element with a VINModelName
child"
I don't think you want this. Something like (let's just look at the first half)
Truck[not(VINModelYearName = preceding::Truck/VINModelYearName)]
is closer, it says
"All Truck element children that do not have a VINModelYearName child
(whose string value is) equal to the VINModelYearName child of a preceding
Truck element"
But even that's not right. Putting this together with a similar second
term, you'd in effect be getting all Truck children with a new
VINModelYearName along with all Truck children with a new VINModelName --
but this isn't the list you want. (What if you encountered a new Truck, but
you'd had both its model name and its model year before, just not together
-- you'd miss it.)
Similarly, the XPath in the count expression will be wrong.
I think what you're missing is that XPath expressions are evaluated with
respect to a context node. This is making your logic hard to construct.
>I know the count part is wrong. I think I would put whatever pattern I use
>in my for-each in my count to return the same set of results to count.
Nope: the context node has changed, so the expression won't return the same
thing.
> I'm
>not sure though, because basically what I'm trying to do is create nodes on
>the fly matching a particular pattern. The pattern can change, because I
>want it for all the years, and for any Model (Which I could make a list of,
>but it would be quite long).
Well, sort of. Basically, yours is a grouping problem. (Hint: look up
"grouping" in the XSL FAQ.) And it admits of a nice elegant solution if you
use the XSLT idiom known as "Muenchian grouping", using a key expression.
In fact, your analysis hints at this solution, in stipulating that you want
to find nodes based on "a particular pattern": that's what the key will let
you do.
So, a key declaration such as
<xsl:key name="TruckModelYear" match="Truck" use="concat(VINModelName,
VINModelYearName)"/>
Creates a key you can use to retrieve your trucks. Each Truck is assigned a
"TruckModelYear" key whose value is the combination of its VINModelName AND
VINModelYearName children.
Then, the instruction
<xsl:for-each select="Truck[generate-id() =
generate-id(key('TruckModelYear', concat(VINModelName,
VinModelYearName)))[1]]">
[nb: untested] iterates over your Truck element children -- except it skips
those that are not the first that match any given key. [Explanation: it
keeps only those whose generated ID matches a generated ID for the first
node (in document order) in the set of nodes (Trucks) with the same key
value, i.e. same VINModelName and VINModelYearName.]
Then inside the for-each, the expression
count(key('TruckModelYear', concat(VINModelName, VinModelYearName)))
will count the number of nodes matched by the key of the current Truck,
that is, the number of Trucks that have the same key as the present Truck
(the context node).
This is an advanced answer, I know ... but it's neater and cleaner than
writing the (fancy and cumbersome) XPath to do it by brute force.
Hope that helps! (and folks, please check my logic),
Wendell
At 07:42 PM 3/14/01, you wrote:
>I'm rather new to XSL (Few months) and am running across a little problem,
>hoping someone here can help me. Thanks for your time.
>
>I have the following XML. . .
>
><Truck-list>
> <Truck>
> <VINModelName>
> T600
> </VINModelName>
> <VINModelYearName>
> 1999
> </VINModelYearName>
> </Truck>
> <Truck>
> <VINModelName>
> T100
> </VINModelName>
> <VINModelYearName>
> 1999
> </VINModelYearName>
> </Truck>
> <Truck>
> <VINModelName>
> T600
> </VINModelName>
> <VINModelYearName>
> 2000
> </VINModelYearName>
> </Truck>
> <Truck>
> <VINModelName>
> T600
> </VINModelName>
> <VINModelYearName>
> 1999
> </VINModelYearName>
> </Truck>
></Truck-list>
>
>What I am trying to accomplish is a summary of the truck somewhat like this
>(Except in HTML and prettier):
>
>Build Year: 1999
>Model: T100
>Count: 1
>
>Build Year: 1999
>Model: T600
>Count: 2
>
>Build Year: 2000
>Model: T100
>Count: 1
>
>Build Year: 2000
>Model: T600
>Count: 1
>
>The XSL chunk I have currently is as follows (I think this is the closest
>I've been, but I've tried lots of things here):
>
><xsl:template match="Truck-list">
> [HTML table build]
> <xsl:for-each
>select="Truck[not(VINModelYearName/preceding::Truck/VINModelYearName)]
> |Truck[not(VINModelName/preceding::Truck/VINModelName)]">
> <tr>
> <td class="lensBody" bgcolor="#FFFFFF" nowrap="true">
> <xsl:value-of select="VINModelYearName"/> 
> </td>
> <td class="lensBody" bgcolor="#FFFFFF" nowrap="true">
> <xsl:value-of select="VINModelName"/> 
> </td>
> <td class="lensBody" bgcolor="#FFFFFF" nowrap="true">
> <xsl:value-of select="count(VINModelName)"/> 
> </td>
> </tr>
> </xsl:for-each>
> </table>
></xsl:template>
======================================================================
Wendell Piez mailto:wapiez@mulberrytech.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