XSL : Generated DOM seems in weird order - xslt

I'm experiencing an issue with an xsl cheatsheet. The generated DOM seems to be in wrong order. Here is my xsl :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="site-path" select="site-path" />
<xsl:param name="target" select="target" />
<xsl:param name="page-id" select="page-id" />
<xsl:variable name="portlet-id" select="portlet/portlet-id" />
<xsl:template match="portlet">
<xsl:variable name="device_class">
<xsl:choose>
<xsl:when test="string(display-on-small-device)='0'">hidden-xs</xsl:when>
<xsl:when test="string(display-on-normal-device)='0'">hidden-sm</xsl:when>
<xsl:when test="string(display-on-large-device)='0'">hidden-md</xsl:when>
<xsl:when test="string(display-on-xlarge-device)='0'">hidden-lg</xsl:when>
<xsl:otherwise></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<div class="portlet {$device_class}">
<xsl:if test="not(string(display-portlet-title)='1')">
<h3 id="article_{$portlet-id}" class="heading"><xsl:value-of disable-output-escaping="yes" select="portlet-name" /></h3>
</xsl:if>
<ul class="news-list gallery news-cards">
<xsl:apply-templates select="document-list-portlet/document" />
<xsl:text disable-output-escaping="yes">
<![CDATA[<div class="clearfix"> </div>]]>
</xsl:text>
</ul>
</div>
</xsl:template>
<xsl:template match="document">
<xsl:if test="not(string(document-xml-content)='null')">
<xsl:variable name="vignette-id" select="document-xml-content/article/article-vignette/file-resource/resource-document-id" />
<xsl:variable name="attribute-id" select="document-xml-content/article/article-vignette/file-resource/resource-attribute-id" />
<li class="news-list-card-item">
<a href="{$site-path}?document_id={document-id}&portlet_id={$portlet-id}" class="news-card">
<div style="background-image: url(document?id={$vignette-id}&id_attribute={$attribute-id}&working_content=true)" class="news-card-image" />
<div class="news-card-wrapper">
<div class="news-card-content">
<div class="news-card-category">
<span>Catégorie</span>
</div>
<div class="news-card-title">
<xsl:value-of select="document-xml-content/article/document-title" />
</div>
</div>
</div>
</a>
<xsl:if test="(string(resource-is-votable)='1')">
<br />
<xsl:variable name="resource-score" select="resource-score" />
<img src="images/local/skin/plugins/rating/stars_{$resource-score}.png" alt="Score" title="Score" />
</xsl:if>
<xsl:if test="(string(is-download-stat)='1')">
<br />
#i18n{rating.resource_vote.labelDownloadCount} : <xsl:value-of select="resource-download-stat" />
</xsl:if>
</li>
</xsl:if>
</xsl:template>
After the render, the generated DOM is :
<li class="news-list-card-item">
<a class="news-card" href="jsp/site/Portal.jsp?document_id=35&portlet_id=100">
</a>
<div class="news-card-image" style="background-image: url(document?id=35&id_attribute=64&working_content=true)">
<a class="news-card" href="jsp/site/Portal.jsp?document_id=35&portlet_id=100">
<div class="news-card-wrapper">
<div class="news-card-content">
<div class="news-card-category">
<span>Catégorie</span>
</div>
<div class="news-card-title">Artu avec vignette 2</div>
</div>
</div>
</a>
</div>
</li>
Here is the expected HTML :
<li class="news-list-card-item">
<a href="#" class="news-card">
<div class="news-card-wrapper">
<div style="background-image: url(../../modules/news-card/image.jpg)" class="news-card-image"></div>
<div class="news-card-content">
<div class="news-card-category"><span>Mobilité</span>
</div>
<div class="news-card-title">Découvrez les neuf Autolib' customisées qui vont sillonner Paris</div>
</div>
</div>
</a>
</li>
Differences are :
In the expected, you got :
li > a > div >div > div ...
In the generated you got :
li > a
div > a > div > div > div
HEre is a smaller reproductible example :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="portlet">
<div class="portlet">
<ul class="news-list gallery news-cards">
<xsl:apply-templates select="document-list-portlet/document" />
</ul>
</div>
</xsl:template>
<xsl:template match="document">
<li class="news-list-card-item">
<a class="news-card">
<div style="background-image: url(hello_world.png)" class="news-card-image" />
<div class="news-card-wrapper">
<div class="news-card-content">
<div class="news-card-category">
<span>Catégorie</span>
</div>
<div class="news-card-title">
Title
</div>
</div>
</div>
</a>
</li>
</xsl:template>
</xsl:stylesheet>
Here is an example data used to generate my DOM :
<?xml version="1.0" encoding="UTF-8"?>
<portlet>
<portlet-name>Actualités projet</portlet-name>
<portlet-id>100</portlet-id>
<page-id>1</page-id>
<plugin-name>document</plugin-name>
<display-portlet-title>0</display-portlet-title>
<display-on-small-device>1</display-on-small-device>
<display-on-normal-device>1</display-on-normal-device>
<display-on-large-device>1</display-on-large-device>
<display-on-xlarge-device>1</display-on-xlarge-device>
<document-list-portlet>
<document>
<document-id>35</document-id>
<document-date-publication>11/07/2017</document-date-publication>
<document-xml-content>
<article>
<document-id>35</document-id>
<document-title>Artu avec vignette 2</document-title>
<document-summary>Artu avec vignette 2</document-summary>
<document-date-begin>11/07/2017</document-date-begin>
<document-date-end>
<document-categories>
<article-url>http://</article-url>
<article-attachment>
<article-vignette>
<file-resource>
<resource-document-id>35</resource-document-id>
<resource-attribute-id>64</resource-attribute-id>
<resource-content-type>image/jpeg</resource-content-type>
</file-resource>
<file-size>134783</file-size>
</article-vignette>
<article-body>&lt;p&gt;Artu avec vignette 2&lt;/p&gt;</article-body>
</article-attachment>
</document-categories>
</document-date-end>
</article>
</document-xml-content>
</document>
</document-list-portlet>
</portlet>
I'm using Google Chrome 59.
I'm searching the issue since 2 days and i'm currently lost. Can you help me?
Thx,
SLED

I just solved my issue by adding a   in my background-image div :
<div class="news-card-wrapper">
<div style="background-image: url(document?id={$vignette-id}&id_attribute={$attribute-id}&working_content=true)" class="news-card-image" > </div>
<div class="news-card-content">
<div class="news-card-category">
<span>Catégorie</span>
</div>
<div class="news-card-title">
<xsl:value-of select="document-xml-content/article/document-title" />
</div>
</div>
</div>
Thanks for all your answer and for #MartinHonnen explaination.

Related

xslt Rename node's attribute value depending on ancestor's attribute value

I have a large number of html files like the following:
<html>
<body>
<div class="a">aaa
<div class="a1">a1a1a1</div>
<div class="a2">a2a2a2</div>
<div class="a2">a3a3a3</div>
</div>
<div class="v u">bbb
<div class="x">xxx</div>
<div class="y">yyy</div>
<div class="z">z1z1z1
<div class="w">www1</div>
<div class="w">www2</div>
<div class="w">www3</div>
</div>
<div class="z">z2z2z2
<div class="w">www4</div>
<div class="w">www5</div>
<div class="w">www6</div>
</div>
</div>
<div class="i">
<div class="j">jjj</div>
<div class="x">
<div class="k">
<div class="w">www7</div>
<div class="w">www8</div>
</div>
</div>
</div>
</body>
</html>
The classes x, y, z, and w can occur any number of times and with any div throughout the html.
There is one and only one div class="v u"
I would like to:
Rename the classes x, y, z, and w to b1, b2, b3, and b4 respectively if and only if any ancestor of that node is div class="v u"
Rename div class="v u" to div class="b"
The result would then be:
<html>
<body>
<div class="a">aaa
<div class="a1">a1a1a1</div>
<div class="a2">a2a2a2</div>
<div class="a2">a3a3a3</div>
</div>
<div class="b">bbb
<div class="b1">xxx</div>
<div class="b2">yyy</div>
<div class="b3">z1z1z1
<div class="b4">www1</div>
<div class="b4">www2</div>
<div class="b4">www3</div>
</div>
<div class="b3">z2z2z2
<div class="b4">www4</div>
<div class="b4">www5</div>
<div class="b4">www6</div>
</div>
</div>
<div class="i">
<div class="j">jjj</div>
<div class="x">
<div class="k">
<div class="w">www7</div>
<div class="w">www8</div>
</div>
</div>
</div>
</body>
</html>
I have tried the following xslt, that doesn't give me the expected result:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="#*|node()" >
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="div[#class='v u']">
<div class="b">
<xsl:copy-of select="node()" />
</div>
</xsl:template>
<xsl:template match="div[#class='v u']/div[#class='x']">
<div class="b1">
<xsl:copy-of select="node()" />
</div>
</xsl:template>
<xsl:template match="div[#class='v u']/div[#class='y']">
<div class="b2">
<xsl:copy-of select="node()" />
</div>
</xsl:template>
<xsl:template match="div[#class='v u']/div[#class='z']">
<div class="b3">
<xsl:copy-of select="node()" />
</div>
</xsl:template>
<xsl:template match="div[#class='v u']/div[#class='z']/div[#class='w']">
<div class="b4">
<xsl:copy-of select="node()" />
</div>
</xsl:template>
</xsl:stylesheet>
I think I understand why it is not giving me the correct result, however I do not seem to find the correct solution.
Instead of all those <xsl:copy-of select="node()" /> you need to use <xsl:apply-templates/> or <xsl:apply-templates select="node()"/> to keep the template based processing alive.

XSLT for dynamic tree

You can see my xml patern sample below. Every manuel has chapter tags, chapter tags may have subchapter and checklist tags. There is no static depth, it may change document to document, so I couldnt write the dynamic recursive xslt code to generate Html. Does anyone knows, how can I achive this.
<manuel name="Test">
<chapter name="00">
<subchapter name="00.01">
<checklist name="00.01.01">
<summary>abc</summary>
</checklist>
</subchapter>
<subchapter name="00.02">
<checklist name="00.02.01">
<summary>def</summary>
</checklist>
<subchapter name="00.02.02">
<checklist name="00.02.02.01">
<summary>xyz</summary>
</checklist>
</subchapter>
</subchapter>
<checklist name="00.03">
<summary>ZZZZ</summary>
</checklist>
</chapter>
</manuel>
For this sample, I suppose this result. I can set the css style, its not important now. The problem is generating the structure.
<div class="cssChapter"> 00</div>
<div class="cssSubChapter"> 00.01 </div>
<div class="cssCheckList"> 00.01.01 </div>
<div class="cssSummary"> abc </div>
<div class="cssSubChapter"> 00.02 </div>
<div class="cssCheckList"> 00.02.01 </div>
<div class="cssSummary"> def </div>
<div class="cssSubChapter"> 00.02.02 </div>
<div class="cssCheckList"> 00.02.02.01 </div>
<div class="cssSummary"> xyz </div>
<div class="cssCheckList"> 00.03 </div>
<div class="cssSummary"> ZZZZ</div>
Use a simple apply-templates:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" indent="yes"/>
<xsl:template match="manuel">
<xsl:apply-templates select=".//*"/>
</xsl:template>
<xsl:template match="chapter">
<div class="cssChapter">
<xsl:value-of select="#name"/>
</div>
</xsl:template>
<xsl:template match="subchapter">
<div class="cssSubChapter">
<xsl:value-of select="#name"/>
</div>
</xsl:template>
<xsl:template match="checklist">
<div class="cssChecklist">
<xsl:value-of select="#name"/>
</div>
</xsl:template>
<xsl:template match="summary">
<div class="cssSummary">
<xsl:value-of select="."/>
</div>
</xsl:template>
</xsl:transform>
Online at http://xsltransform.net/3NJ3915/1.

xslt adding constant number of siblings

I have a large number of files with a structure like the following a.html:
<html>
<body>
<div class="a">aaa
<div class="b">bbb</div>
<div class="c">ccc1
<div class="d">ddd11
<div class="e">eee11</div>
<div class="f">fff11
<div class="g">ggg111</div>
<div class="g">ggg112</div>
<div class="g">ggg113</div>
<div class="g">ggg114</div>
<div class="g">ggg115</div>
<div class="g">ggg116</div>
</div>
</div>
<div class="d">ddd12
<div class="e">eee12</div>
<div class="f">fff12
<div class="g">ggg121</div>
<div class="g">ggg122</div>
<div class="g">ggg123</div>
<div class="g">ggg124</div>
</div>
</div>
</div>
<div class="c">ccc2
<div class="d">ddd21
<div class="e">eee21</div>
<div class="f">fff21
<div class="g">ggg211</div>
<div class="g">ggg212</div>
<div class="g">ggg213</div>
<div class="g">ggg214</div>
<div class="g">ggg215</div>
</div>
</div>
</div>
...
</div>
</body>
</html>
The number of div class="c" is variable in each file (zero or more)
The number of div class="d" is variable inside each (zero or more)
The number of div class="g" is variable inside each (zero or more)
I would like to have a number of div class="c" equal to the max_c parameter in all files.
I use the following shell script to pass the max_c parameter with a value equal to 3:
#!/bin/bash
xsltproc --param max_c 3 a.xslt a.html
And I use the following a.xslt:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="max_c"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="div[#class='a']">
<xsl:copy>
<xsl:apply-templates select="div[#class='a']" />
<xsl:apply-templates select="div[#class='b']" />
<xsl:apply-templates select="div[#class='c']" />
<xsl:call-template name="AddC">
<xsl:with-param name="count" select="$max_c - count(div[#class='c'])" />
</xsl:call-template>
</xsl:copy>
</xsl:template>
<xsl:template name="AddC">
<xsl:param name="count" />
<xsl:if test="$count > 0">
<div class="c">ccc
</div>
<xsl:call-template name="AddC">
<xsl:with-param name="count" select="$count - 1" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
The output is the following:
<html>
<body>
<div>
<div class="b">bbb</div>
<div class="c">ccc1
<div class="d">ddd11
<div class="e">eee11</div>
<div class="f">fff11
<div class="g">ggg111</div>
<div class="g">ggg112</div>
<div class="g">ggg113</div>
<div class="g">ggg114</div>
<div class="g">ggg115</div>
<div class="g">ggg116</div>
</div>
</div>
<div class="d">ddd12
<div class="e">eee12</div>
<div class="f">fff12
<div class="g">ggg121</div>
<div class="g">ggg122</div>
<div class="g">ggg123</div>
<div class="g">ggg124</div>
</div>
</div>
</div>
<div class="c">ccc2
<div class="d">ddd21
<div class="e">eee21</div>
<div class="f">fff21
<div class="g">ggg211</div>
<div class="g">ggg212</div>
<div class="g">ggg213</div>
<div class="g">ggg214</div>
<div class="g">ggg215</div>
</div>
</div>
</div>
<div class="c">ccc$count</div>
</div>
</body>
</html>
This is almost what I would like, with 2 exceptions:
The first div has lost its class="a" and its value aaa
The added div class="c" should have a value of ccc3, and not ccc$count
What am I doing wrong?
As usual I thank you in advance for your help.
The first div has lost its class="a" and its value aaa
To add the missing attributes and text content change the xslt:copy like the following:
<xsl:copy>
<xsl:apply-templates select="#* | div[#class='b'] | text()" />
<xsl:apply-templates select="div[#class='c']" />
The #*adds all attributes and the text() all text content.
The added div class="c" should have a value of ccc3, and not ccc$count
change the output for div c as:
<div class="c">
ccc<xsl:value-of select="$count"/>
</div>

XSLT For-Each Wrapping every nth item in a div

I have a series of nodes that are direct child nodes to a parent I want to loop over those nodes but have them wrapped in 'groups' of 4... I'm probably not wording this very clearly so this might help;
<span class="child01">#nodename</span>
<span class="child02">#nodename</span>
<span class="child03">#nodename</span>
<span class="child04">#nodename</span>
<span class="child05">#nodename</span>
<span class="child06">#nodename</span>
<span class="child07">#nodename</span>
<span class="child08">#nodename</span>
..
<span class="child32">#nodename</span>
<span class="child33">#nodename</span>
..and so on
Goal
<div class="group">
<span class="child01">#nodename</span>
<span class="child02">#nodename</span>
<span class="child03">#nodename</span>
<span class="child04">#nodename</span>
</div>
<div class="group">
<span class="child05">#nodename</span>
<span class="child06">#nodename</span>
<span class="child07">#nodename</span>
<span class="child08">#nodename</span>
</div>
<div class="group">
..
<span class="child32">#nodename</span>
</div>
<div class="group">
<span class="child33">#nodename</span>
..and so on
I have tried variations on this idea - wrapping the lot in the open and closing group tags and every fourth loop drop in a new close / open pair
<div class="group">
<xsl:for-each select="$currentPage/*">
<span>
<xsl:value-of select="#nodeName" />
</span>
<!--
=============================================================
After very 4th item
=============================================================
-->
<xsl:if test="position() mod 4 = 0">
<xsl:text></div><div class="page"></xsl:text>
</xsl:if>
</xsl:for-each>
</div>
But essentially it seems XSLT won't let me start with a closing unmatched tag
The clkoset solution I ahve found so far is a 'fix' in jquery Wrapping a div around every three divs but I would rather not rely on javascript to format the page.
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pNumCols" select="3"/>
<xsl:template match="/*">
<xsl:apply-templates select="span[position() mod $pNumCols = 1]"/>
</xsl:template>
<xsl:template match="span">
<div>
<xsl:copy-of select=
".|following-sibling::span[not(position() > $pNumCols -1)]"/>
</div>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<t>
<span class="child01">#nodename</span>
<span class="child02">#nodename</span>
<span class="child03">#nodename</span>
<span class="child04">#nodename</span>
<span class="child05">#nodename</span>
<span class="child06">#nodename</span>
<span class="child07">#nodename</span>
<span class="child08">#nodename</span> ..
<span class="child32">#nodename</span>
<span class="child33">#nodename</span>
</t>
produces the wanted result:
<div>
<span class="child01">#nodename</span>
<span class="child02">#nodename</span>
<span class="child03">#nodename</span>
</div>
<div>
<span class="child04">#nodename</span>
<span class="child05">#nodename</span>
<span class="child06">#nodename</span>
</div>
<div>
<span class="child07">#nodename</span>
<span class="child08">#nodename</span>
<span class="child32">#nodename</span>
</div>
<div>
<span class="child33">#nodename</span>
</div>
If like me you need to transform the source elements that are being divided by position, use xsl:for-each instead of xsl:copy:
<xsl:template match="span">
<ol>
<xsl:for-each select=".|following-sibling::span[not(position() > $pNumCols -1)]"/>
<li><xsl:value-of select="./text()"/></li>
</xsl:for-each>
</ol>
</xsl:template>
Faced by the same problem, that is wanting to output
<div class="container">
<div class="row">
<div class="col">...</div>
<div class="col"/>...</div>
</div>
<div class="row">
...
</div>
</div>
from a CXML (Collection XML) file (http://gallery.clipflair.net/collection/activities.cxml - the data behind the PivotViewer display at http://gallery.clipflair.net/activity)
I coined up the following, based on other suggestions here, but using "mode" attribute of "template" and "apply-templates" XSL tags instead which make it cleaner I believe:
<?xml version="1.0" encoding="UTF-8"?>
<?altova_samplexml http://gallery.clipflair.net/collection/activities.cxml?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:cxml="http://schemas.microsoft.com/collection/metadata/2009"
exclude-result-prefixes="cxml"
>
<xsl:output method="html" version="4.0" encoding="UTF-8" indent="yes"/>
<xsl:param name="COLUMNS" select="2"/>
<!-- ########################### -->
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>ClipFlair Activities</title>
<link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<!-- ########################### -->
<xsl:template match="cxml:Collection">
<div class="container">
<xsl:apply-templates/>
</div>
</xsl:template>
<!-- ########################### -->
<xsl:template match="cxml:Items">
<xsl:apply-templates select="cxml:Item[position() mod $COLUMNS = 1]" mode="row"/>
</xsl:template>
<!-- ########################### -->
<xsl:template match="cxml:Item" mode="row">
<div class="row">
<div>----------</div>
<xsl:apply-templates select=".|following-sibling::cxml:Item[position() < $COLUMNS]" mode="col"/>
</div>
</xsl:template>
<xsl:template match="cxml:Item" mode="col">
<xsl:variable name="URL" select="#Href"/>
<xsl:variable name="FILENAME" select="cxml:Facets/cxml:Facet[#Name='Filename']/cxml:String/#Value"/>
<div class="col">
<xsl:value-of select="$FILENAME"/> --- <xsl:value-of select="$URL"/>
</div>
</xsl:template>
<!-- ########################### -->
<xsl:template match="*">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="text()|#*">
</xsl:template>
</xsl:stylesheet>
the output from the above when run in Altova XMLSpy tool (note that it uses altova_samplexml processor instruction to find the XML data) is:
2DaysInParis-OpenActivity-CapRev-FR-EN.clipflair --- http://studio.clipflair.net/?activity=2DaysInParis-OpenActivity-CapRev-FR-EN.clipflair
Abu_Dukhan-CapRev-A1-AR.clipflair --- http://studio.clipflair.net/?activity=Abu_Dukhan-CapRev-A1-AR.clipflair
----------
AFarewellToArms-RevCap-C2-EN.clipflair --- http://studio.clipflair.net/?activity=AFarewellToArms-RevCap-C2-EN.clipflair
agComhaireamhCountingRND.clipflair --- http://studio.clipflair.net/?activity=agComhaireamhCountingRND.clipflair
----------
Al-imtihan-CapRev-B1-AR.clipflair --- http://studio.clipflair.net/?activity=Al-imtihan-CapRev-B1-AR.clipflair
AlBar-Cap-B1-B2-IT.clipflair --- http://studio.clipflair.net/?activity=AlBar-Cap-B1-B2-IT.clipflair
...

XSL: Print divider by checking variables

I'm new to XSL and i want to do something like
var oldvalue= ''
for each
get currentvalue
if (oldvalue != currentvalue)
{
print divider
oldvalue = currentvalue
}
end for
I've tried it with
<xsl:variable name="oldname" select="name" />
<xsl:for-each select="myxpathstring">
<xsl:choose>
<xsl:when test="$newname = $newname">
<xsl:variable name="oldname" select="$newname" />
<div class='divider'>divider stuff </div>
</xsl:when>
<xsl:otherwise>No</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
But that doesn't work because i can't update the 'oldname' variable.
Anyone have a solution ?
The complete XSL (with JSP-parameters because i generate the XSL dynamically)
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:variable name="counter" select="count(<%= request.getParameter("xpath")%>)" />
<div id='counter' class='ui-state-highlight ui-corner-all'><p><span style="float: left; margin-right: .3em;" class="ui-icon ui-icon-info"></span><xsl:value-of select="$counter"/> schema's gevonden</p></div>
<div class="page_navigation ui-widget-header ui-corner-all"></div>
<ul id='schemeslist' class="content">
<xsl:for-each select="<%= request.getParameter("xpath")%>"><!-- filter on sports //scheme[ (sports/sport ='Fietsen') and (planduration=12 or planduration=16)]-->
<xsl:sort select="name"/>
<!-- ////////////////// -->
<!-- print divider if name is new -->
<!-- ////////////////// -->
<li class='scheme' id='scheme'>
<div class='schemeSports'>
<!-- <xsl:for-each select="sports/sport">
<xsl:value-of select="."/>
</xsl:for-each> -->
<xsl:value-of select="sport"/>
</div>
<xsl:variable name="theid" select="#id" />
<div class='schemeName'><xsl:value-of select="name"/></div>
<div class='planDuration'><xsl:value-of select="planduration"/></div>
<div class='fitnessLevel'><xsl:value-of select="fitnesslevel"/></div>
<div class='order'>
<xsl:if test="price != ''"><xsl:value-of select="price"/>euro</xsl:if>
<button class='more' onClick='showInfo("{$theid}")' id='{$theid}'>MEER</button> <button class='buy' onClick='window.location = "buy.html?ID={$theid}"'>KOOP</button>
</div>
</li>
</xsl:for-each>
</ul>
<div style='clear:both'></div>
<div class="page_navigation ui-widget-header ui-corner-all"></div>
</xsl:template>
</xsl:stylesheet>
and here is a sample of the complete xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<schemes lang='nl-BE'>
<scheme id='5E47B7E9'>
<sport>Fietsen</sport>
<author>Energy Lab</author>
<name>Voorbereiding op de Ronde van Vlaanderen</name>
<planduration>16</planduration>
<fitnesslevel>Beginner</fitnesslevel>
<frequency>1-3</frequency>
<longtraining></longtraining>
<rollers>Ja</rollers>
<price>12</price>
<description>
<![CDATA[...]]>
</description>
</scheme>
<scheme id='5E47B7E9'>
<sport>Triatlon</sport>
<author>Energy Lab</author>
<name>Voorbereiding op de Ronde van Vlaanderen</name>
<planduration>16</planduration>
<fitnesslevel>Expert</fitnesslevel>
<frequency>1-3</frequency>
<longtraining></longtraining>
<rollers>Ja</rollers>
<price>12</price>
<description>
<![CDATA[...]]>
</description>
</scheme>
<scheme id='5E47B7E9'>
<sport>Fietsen</sport>
<author>Energy Lab</author>
<name>Voorbereiding op een Triatlon</name>
<planduration>24</planduration>
<fitnesslevel>Beginner</fitnesslevel>
<frequency>1-3</frequency>
<longtraining></longtraining>
<rollers>Ja</rollers>
<price>48</price>
<description>
<![CDATA[...]]>
</description>
</scheme>
</schemes>
Create a function that returns the new value, taking as parameters the old value and the list of values in myxpathstring.
If I understand your XSLT correct you have to use muenchian grouping. Read this article for a description of how this method works.
XML:
<?xml version="1.0" encoding="UTF-8"?>
<schemes lang='nl-BE'>
<scheme id='5E47B7E9'>
<sport>Fietsen</sport>
<author>Energy Lab</author>
<name>Voorbereiding op de Ronde van Vlaanderen</name>
<planduration>16</planduration>
<fitnesslevel>Beginner</fitnesslevel>
<frequency>1-3</frequency>
<longtraining></longtraining>
<rollers>Ja</rollers>
<price>12</price>
<description><![CDATA[...]]></description>
</scheme>
<scheme id='5E47B7E9'>
<sport>Triatlon</sport>
<author>Energy Lab</author>
<name>Voorbereiding op de Ronde van Vlaanderen</name>
<planduration>16</planduration>
<fitnesslevel>Expert</fitnesslevel>
<frequency>1-3</frequency>
<longtraining></longtraining>
<rollers>Ja</rollers>
<price>12</price>
<description><![CDATA[...]]></description>
</scheme>
<scheme id='5E47B7E9'>
<sport>Fietsen</sport>
<author>Energy Lab</author>
<name>Voorbereiding op een Triatlon</name>
<planduration>24</planduration>
<fitnesslevel>Beginner</fitnesslevel>
<frequency>1-3</frequency>
<longtraining></longtraining>
<rollers>Ja</rollers>
<price>48</price>
<description><![CDATA[...]]></description>
</scheme>
</schemes>
XSLT:
I replaced the first jsp-tag with a dot and removed the second because I have no idea what you try to achieve with. I do not recommend dynamic *.xsl. You better put these information in your input.xml and query it with xpath.
<?xml version='1.0' encoding='UTF-8'?>
<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method='xml' indent='yes' omit-xml-declaration='yes'/>
<xsl:key name='schemata' match='scheme' use='name'/>
<xsl:template match='scheme'>
<li class='scheme' id='scheme'>
<div class='schemeSports'>
<xsl:value-of select="sport"/>
</div>
<xsl:variable name="theid" select="#id"/>
<div class='schemeName'>
<xsl:value-of select="name"/>
</div>
<div class='planDuration'>
<xsl:value-of select="planduration"/>
</div>
<div class='fitnessLevel'>
<xsl:value-of select="fitnesslevel"/>
</div>
<div class='order'>
<xsl:if test="price != ''">
<xsl:value-of select="price"/>
euro
</xsl:if>
<button class='more' onClick='showInfo("{$theid}")' id='{$theid}'>MEER</button>
<button class='buy' onClick='window.location = "buy.html?ID={$theid}"'>KOOP</button>
</div>
</li>
</xsl:template>
<xsl:template match='/schemes'>
<xsl:variable name="counter" select="count(.)"/> <!-- jsp -->
<div id='counter' class='ui-state-highlight ui-corner-all'>
<p>
<span style="float: left; margin-right: .3em;" class="ui-icon ui-icon-info"/>
<xsl:value-of select="$counter"/>
<xsl:text> schema's gevonden</xsl:text>
</p>
</div>
<div class="page_navigation ui-widget-header ui-corner-all"/>
<ul id='schemeslist' class="content">
<!-- muenchian grouping -->
<xsl:for-each select='scheme[generate-id() = generate-id(key("schemata", name)[1])]'>
<xsl:sort select='name'/>
<xsl:if test='position() != 1'>
<div class='divider'/>
</xsl:if>
<xsl:apply-templates select='key("schemata", name)'/>
</xsl:for-each>
</ul>
<div style='clear:both'/>
<div class="page_navigation ui-widget-header ui-corner-all"/>
</xsl:template>
</xsl:stylesheet>
Result:
<div id="counter" class="ui-state-highlight ui-corner-all">
<p><span style="float: left; margin-right: .3em;" class="ui-icon ui-icon-info"/>1 schema's gevonden</p>
</div><div class="page_navigation ui-widget-header ui-corner-all"/><ul id="schemeslist" class="content">
<li class="scheme" id="scheme">
<div class="schemeSports">Fietsen</div>
<div class="schemeName">Voorbereiding op de Ronde van Vlaanderen</div>
<div class="planDuration">16</div>
<div class="fitnessLevel">Beginner</div>
<div class="order">12
euro
<button class="more" onClick="showInfo("5E47B7E9")" id="5E47B7E9">MEER</button><button class="buy" onClick="window.location = "buy.html?ID=5E47B7E9"">KOOP</button></div>
</li>
<li class="scheme" id="scheme">
<div class="schemeSports">Triatlon</div>
<div class="schemeName">Voorbereiding op de Ronde van Vlaanderen</div>
<div class="planDuration">16</div>
<div class="fitnessLevel">Expert</div>
<div class="order">12
euro
<button class="more" onClick="showInfo("5E47B7E9")" id="5E47B7E9">MEER</button><button class="buy" onClick="window.location = "buy.html?ID=5E47B7E9"">KOOP</button></div>
</li>
<div class="divider"/>
<li class="scheme" id="scheme">
<div class="schemeSports">Fietsen</div>
<div class="schemeName">Voorbereiding op een Triatlon</div>
<div class="planDuration">24</div>
<div class="fitnessLevel">Beginner</div>
<div class="order">48
euro
<button class="more" onClick="showInfo("5E47B7E9")" id="5E47B7E9">MEER</button><button class="buy" onClick="window.location = "buy.html?ID=5E47B7E9"">KOOP</button></div>
</li>
</ul><div style="clear:both"/><div class="page_navigation ui-widget-header ui-corner-all"/>