|
[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] Re: using XSLT to transform a XML recordset
Hi Svend,
> notice how, each bundle, being the main identifier, doesn't always
> have the same number of resources. the idea being, that we want the
> base to be flexible, so no set amount of values have been defined.
> Just that it always contains a reskey (resourcekey), and a resvalue
> (resourcevalue), and these properties/values are tied to a bundle
> name, in the above example, "svendtofte" and "mikkel".
Say that you knew the name of the bundle, and that it was held in the
$bundle variable. In order to create the relevant attributes on the
element for that bundle, you'd need a quick way of getting the row
elements whose bundle attribute was $bundle. Once you got those, it
would be easy to use a predicate to find the one with the appropriate
reskey.
A 'quick way' of getting the row elements for a particular bundle is
to use xsl:key. Set up the key to index the row elements by their
bundle attribute, with an xsl:key top-level element, as follows:
<xsl:key name="rows" match="row" use="@bundle" />
With the key defined, you can find the rows for the $bundle bundle
with:
key('rows', $bundle)
So you could create the element for the bundle with something like:
<xsl:variable name="rows" select="key('rows', $bundle)" />
<element bundle="{$bundle}"
description="{$rows[@reskey = 'description']/@resvalue}"
title="{$rows[@reskey = 'title']/@resvalue}"
link="{$rows[@reskey = 'link']/@resvalue}"
de="{$rows[@reskey = 'de']/@resvalue}"
blah="{$rows[@reskey = 'blah']/@resvalue}" />
You can use the same key to get the possible values for the $bundle
variable using the Muenchian Method. If you go through each of the row
elements, you can find the ones that are the first with each
particular value for $bundle by seeing whether the row is the first
node that's returned by the key for their particular bundle. You can
do this with:
<xsl:for-each select="row[count(.|key('rows', @bundle)[1]) = 1]">
<xsl:variable name="bundle" select="@bundle" />
<xsl:variable name="rows" select="key('rows', $bundle)" />
<element bundle="{$bundle}"
description="{$rows[@reskey = 'description']/@resvalue}"
title="{$rows[@reskey = 'title']/@resvalue}"
link="{$rows[@reskey = 'link']/@resvalue}"
de="{$rows[@reskey = 'de']/@resvalue}"
blah="{$rows[@reskey = 'blah']/@resvalue}" />
</xsl:for-each>
You can use the same method to work out what possible values there are
for the @reskey attributes, store them in a global variable, and then
iterate over them when you need to create the element, if that's
necessary.
To improve performance, you could also use a separate key to retrieve
the resvalue attribute for a particular bundle+reskey combination, if
you wanted:
<xsl:key name="resvalues" match="row/@resvalue"
use="concat(../@bundle, ':', ../@reskey)" />
and then retrieve the relevant values as follows:
<xsl:for-each select="row[count(.|key('rows', @bundle)[1]) = 1]">
<xsl:variable name="bundle" select="@bundle" />
<element bundle="{$bundle}"
description="{key('resvalues',
concat($bundle, ':description'))}"
title="{key('resvalues', concat($bundle, ':title'))}"
link="{key('resvalues', concat($bundle, ':link'))}"
de="{key('resvalues', concat($bundle, ':de'))}"
blah="{key('resvalues', concat($bundle, ':blah'))}"
</xsl:for-each>
So yes, it's possible, and in a one-pass solution, though it's not
particularly straightforward (hopefully XSLT 2.0 will help with that
eventually).
Cheers,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|

Cart








