Re: [xsl] many-to-many

Subject: Re: [xsl] many-to-many
From: Ronan Klyne <ronan.klyne@xxxxxxxxxxx>
Date: Tue, 30 Jan 2007 15:23:55 +0000
Comments below - I hope they are clear enough, but if you don't see how
or why something is happening, I shall try to clarify...

Brown, William S wrote:
> Is your suggestion then that I place something like
> <xsl:value-of select="key('pid-p', key('i-p', @id)/@id)????"/>
> within the for-each at the point indicated below?

Not within the for-each, but as it's select, as shown in the stylesheet
below...
"key('i-p', @id)" will give a set of part elements with only an id
attribute (the ones under the invoice with the id specified). To see why
it's these elements, look at the xsl:key element.
"key('i-p', @id)/@id" will give a straight set of ids of these elements.
"key('pid-p', key('i-p', @id)/@id)" will take these ids, and return the
part (the element under /doc/parts) associated with each of them.
Putting that in the select attribute of a fore-each will iterate over them.

> (I'm apparently misunderstanding what's being returned by the key function, or how to use it - because what I've written doesn't work. Entirely *my* error I'm sure. Can I not use a value-of here? I would have thought that what is returned at this point is unique.)

(Note here that keys are (for me) quite difficult to explain clearly)
The key function returns whatever is specified in the 'match' attribute
of the key element with the same name.
For example:
<xsl:key name="pid-p" match="/doc/parts/part" use="@id"/>
The name is an identifier that allows us to use many keys.
The match attribute specifies which elements you want the key function
to return.
The use attribute specifies the identifying information you want to use
to find a particular element. It is an XPath expression, in the context
of the element matched. In this case, the id attribute of a part.

> Asking your indulgence...how exactly do I get to the partLoc?

See below :)

	# r

Here is a stylesheet that runs on your test data:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="1.0">
<xsl:output method="html" indent="no" encoding="ISO-8859-1"/>

<xsl:key name="p-i" match="/doc/invoices/invoice" use="part/@id"/>
<xsl:key name="i-p" match="/doc/invoices/invoice/part" use="../@id"/>
<xsl:key name="pid-p" match="/doc/parts/part" use="@id"/>

<xsl:template match="invoice">
  <h3>invoice <xsl:value-of select="@id"/> contains:</h3>
  <xsl:for-each select="key('pid-p', key('i-p', @id)/@id)">
    Part: <xsl:value-of select="@id"/> (partLoc: <xsl:value-of
select="partLoc"/>)
  </xsl:for-each>
</xsl:template>

<xsl:template match="part">
  <h3>part <xsl:value-of select="@id"/> was part of invoices:</h3>

  <xsl:for-each select="key('p-i', @id)">
    <xsl:value-of select="@id"/>,
  </xsl:for-each>
</xsl:template>

<xsl:template match="doc">
  <h2>invoice to parts</h2>
  <xsl:apply-templates select="invoices/*"/>
  <h2>part to invoices</h2>
  <xsl:apply-templates select="parts/*"/>
</xsl:template>

</xsl:stylesheet>

-- 
Ronan Klyne
Business Collaborator Developer
Tel: +44 (0)870 163 2555
ronan.klyne@xxxxxxxxxxx
www.groupbc.com

Current Thread