General outline: I need to write a transformation restricted using XSLT 1.0 possibilties only without using any external extension. I took the basic sample files from
Michael Kay's excellent XSLT: Programmer's Reference, 2nd Edition by
downloading its sample codes .
!! I'd read the advise putting a specific question to the appropriate forum here at wrox, however my task is to extending this basic grouping sample with a tokenizing or splitting involving it. Because I think the problem may be more general (only the example shown is specific to the above mentioned book), I posted my question here.
Sample task: Let's suppose there are same city names in different countries ...
Here is the sample source
cities.xml file being a little extended and also abbreviated
Code:
<cities>
<city name="Paris" country="France,Texas"/>
<city name="Venice" country="Italia,Luisiana"/>
<city name="Roma" country="Italia"/>
<city name="Nice" country="France"/>
<city name="Milano" country="Italia"/>
<city name="Firenze" country="Italia"/>
<city name="Napoli" country="Italia"/>
<city name="Lyon" country="France"/>
</cities>
I expect the following HTML output
HTML Code:
<h1>France</h1>
Paris<br/>
Nice<br/>
Lyon<br/>
<h1>Texas</h1>
Paris<br/>
</h1>Italia</h1>
Venice<br/>
Roma<br/>
Milano<br/>
Firenze<br/>
Napoli<br/>
<h1>Luisiana</h1>
Venice<br/>
here is my extended
cities_group_and_tokenize.xsl transformation file trying to solve the problem
Code:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:key name="country-group" match="city" use="@country"/>
<xsl:template match="/">
<html>
<body>
<!-- Need to separate/split @country which contains country1, country2 without any extension used-->
<xsl:variable name="countryitems" >
<xsl:call-template name="splitcountries">
<xsl:with-param name="string" select="//@country"/>
</xsl:call-template>
</xsl:variable>
<!-- I'm trying only to test it here how to refer to the key after splitting -->
<xsl:variable name="testcountryitem" >
<xsl:value-of select="$countryitems/token/@country" />
</xsl:variable>
<xsl:for-each select="//city[generate-id() = generate-id(key('country-group', $testcountryitem)[1])]">
<!-- <xsl:for-each select="//city[generate-id() = generate-id(key('country-group', @country)[1])]">-->
<h1><xsl:value-of select="@country"/></h1>
<xsl:for-each select="key('country-group', @country)">
<xsl:value-of select="@name"/><br/>
</xsl:for-each>
</xsl:for-each>
</body>
</html>
</xsl:template>
<!-- Split countries subtemplate -->
<xsl:template name="splitcountries">
<xsl:param name="string"/>
<xsl:param name="separator" select="','"/>
<xsl:choose>
<xsl:when test="contains($string,$separator)">
<token country="{substring-before($string,$separator)}">
<!-- <xsl:value-of select="substring-before($string,$separator)"/> -->
</token>
<xsl:call-template name="splitcountries">
<xsl:with-param name="string" select="substring-after($string,$separator)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="string-length($string) = 0">
<token country="Empty"></token>
</xsl:when>
<xsl:otherwise>
<token country="{$string}">
<!-- <xsl:value-of select="$string"/> -->
</token>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Split countries subtemplate -->
</xsl:transform>
My above transformation file outputs only
France
Nice
Lyon
then finishes its working.
----- Notes -----
I suppose, the problem may be
1.
<xsl:key name="country-group" match="city" use="@country"/>
top level declaration will generate a key-table (see: behind the keys
http://www.cranesoftwrights.com/reso...keys/index.htm) something like this
key-table
IDX key values
1 France,Texas
2 Italia,Luisiana
3 Italia
4 France
5 Italia
6 Italia
7 Italia
8 France
2. In the outer loop of the above given transformation file
<xsl:for-each select="//city[generate-id() = generate-id(key('country-group', $testcountryitem)[1])]">
will generate the id for the first token 'France' contained in $testcountryitem probably well
3. However in the second inner loop of it
<xsl:for-each select="key('country-group', @country)">
will go through the key-table and it will find only two matches (see idx=4 and idx=8 in the above key-table)
4. I guess, it doesn't find 'France' at idx=1 in the key-table, because there is not any instruction how to split even that key value too. And the 'France,Texas' string really doesn't same as 'France' string only.
5. Because I can't use any external EXSLT str:split, EXSLT str:tokenize, or Saxon saxon:tokenize functions in the top <xsl:key ... use=".." declaration which will make the key-values in the key_table supposedly splitting
5.1 I only guess, either I need to use an other top level
<xsl:key name="country-group" match="token" use="@country"/>
<xsl:key name="country-group" match="token" use="."/>
declaration(s) (using either of the versions concerning see: above the written 'Split countries subtemplate') for generating a union key-table which somehow will contain additional but the splitting key-values too.
However I don't understand generally whether there will be any key-table generated at all when a sub template is called? Factually the sub template will give a tree fragment tokens held in a variable (countryitems) which are not real nodes on which the key generation process will go through as per my present understanding. So I suppose my guessed declaration is useless.
5.2 Or, I can't guess even how to resolve this combined problem.
Grateful thanks, for giving me any advise or tip or comment.