Hello all,
XSLT 1.0 (i.e. Firefox 3.0, etc.)
XSLT 2.0 solutions not suitable.
I have a working xsl stylesheet that transforms an xml file with the
structure:
< wines >
< wine >...< /wine >+
< /wines >
I want, now, to rewrite my xsl stylesheet to work with a collection of
xml files, each of which contain an individual < wine > element--i.e. in
place of the single xml < wines > file.
I have succeeded, but with two problems. Firstly, I am unable to
separately specify the directory path of the files. Here is my "base"
xml file's content:
<docs path="jb">
<doc filename="jb/wine1.xml" />
<doc filename="jb/wine2.xml" />
<doc filename="jb/wine3.xml" />
...
</docs>
Note that I have provided the directory path within the @filename
attribute, but I would prefer to retrieve it from the @path attribute.
Here is the part of my xsl stylesheet that retrieves the contents of my
collection of xml files:
<xsl:template match="/docs">
<xsl:variable name="thePath" select="@path" />
<xsl:variable name="theWines" select="document(doc/@filename)/wine" />
...
Is there a way to use my $thePath variable, instead of including the
directory path inside the @filename attribute? I tried to concatenate,
but without success. I want to deal with all my xml files together,
rather than using a for-each loop, because of several aggregate
processes that I want to apply.
Secondly, I'm not sure I fully understand what my $theWines variable now
contains. I believe it is a collection of tree fragments--i.e. there's
no single top-most node, is that right? Or is there an implicit /
(document) node?
The reason I ask is because I have some templates that rely on
processing the preceding axis, and whereas my templates work fine for my
< wines > xml file, they do not produce the anticipated results when
using my $theWines variable.
This template works with the < wines > xml file, and is called by
another template that has already matched the "wines" node:
<xsl:template name="winesByCountry">
<table border="1">
<xsl:for-each
select="wine/countries/country[not(name=../../preceding-sibling::wine/countries/country/name)]">
<xsl:sort select="name" order="ascending" />
<xsl:variable name="countryName" select="name" />
<tr><th><xsl:value-of select="$countryName" /></th><td>
<xsl:value-of select="count(/wines/wine/countries/country[name =
$countryName])" /></td></tr>
</xsl:for-each>
</table>
</xsl:template>
The following template does not work. It outputs each country multiple
times--e.g. 2 wines from Italy are output twice as:
Italy 2
Italy 2
rather than the second time correctly seeing that that country is
already present in a preceding node:
<xsl:template name="winesByCountry">
<xsl:param name="theWines" />
<table border="1">
<xsl:for-each
select="$theWines/countries/country[not(name=preceding::country/name)]">
<xsl:sort select="name" order="ascending" />
<xsl:variable name="countryName" select="name" />
<tr><th><xsl:value-of select="$countryName" /></th><td>
<xsl:value-of
select="count($theWines/countries/country[name=$countryName])" /></td></tr>
</xsl:for-each>
</table>
</xsl:template>
Do I need to wrap the sequence of tree fragments in my $theWines
variable inside a node? I tried using the following:
<xsl:variable name="theWines">
<wines>
<xsl:value-of select="document(doc/@filename)/wine" />
</wines>
</xsl:variable>
but Firefox says: Error during XSLT transformation: An XPath expression
was expected to return a NodeSet.
Sorry for the length. Any suggestions?
Cheers!
Joe