Reputation: 27
I am working on XSLT2 script where the variable contains following text:
<xsl:variable name="urlparams" select="'color=red;rating=5;page=8;product=xyz'"/>
I want to construct below url. The equal to (=) values are dynamic, so next time it may change. For example (color=blue or product=abc).
<a href="www.google.com/?color=red&product=xyz"/>
Here is my xslt but it is not working :(
<xsl:template match="/">
<xsl:variable name="urlparams" select="'color=red;rating=5;page=8;product=xyz'"/>
<xsl:value-of select="'www.google.com/?'"/>
<xsl:for-each select="tokenize($urlparams, ';')">
<xsl:if test=". = 'color'">
<xsl:value-of select="."/><xsl:text>&</xsl:text>
</xsl:if>
<xsl:if test=". = 'product'">
<xsl:value-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:template>
Upvotes: 2
Views: 402
Reputation: 243449
Here is a pure XPath 2.0 expression whose evaluation produces the wanted result:
for $host in 'www.google.com/',
$qParams in 'color=red;rating=5;page=8;product=xyz',
$qString in string-join(tokenize($qParams, ';')
[starts-with(., 'color=') or starts-with(., 'product=')],
'&')
return
concat($host, '?'[$qString], $qString)
XSLT 2.0 based validation:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<xsl:variable name="vUrl" select=
"for $host in 'www.google.com/',
$qParams in 'color=red;rating=5;page=8;product=xyz',
$qString in string-join(tokenize($qParams, ';')
[starts-with(., 'color=') or starts-with(., 'product=')],
'&')
return
concat($host, '?'[$qString], $qString)
"/>
<a href="{$vUrl}"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on any source XML document (not used), it evaluates the XPath expression and inserts the result as AVT as the value of the href
attribute of the wanted <a>
element, producing the wanted, correct result:
<a href="www.google.com/?color=red&product=xyz"></a>
Part II
One can even avoid hard-coding the wanted QS parameter -names, by presenting them within a parameter, like this:
for $host in 'www.google.com/',
$wantedPNames in '|color|product|',
$qParams in 'color=red;rating=5;page=8;product=xyz',
$qString in string-join(tokenize($qParams, ';')
[contains($wantedPNames, concat('|',tokenize(., '=')[1], '|'))],
'&')
return
concat($host, '?'[$qString], $qString)
Evaluating the XPath expression above, again produces the wanted, correct result:
www.google.com/?color=red&product=xyz
Here is again the XSLT 2.0 - based verification:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:param name="wantedPNames" select="'|color|product|'"/>
<xsl:template match="/">
<xsl:variable name="vUrl" select=
"for $host in 'www.google.com/',
$qParams in 'color=red;rating=5;page=8;product=xyz',
$qString in string-join(tokenize($qParams, ';')
[contains($wantedPNames, concat('|',tokenize(., '=')[1], '|'))],
'&')
return
concat($host, '?'[$qString], $qString)
"/>
<a href="{$vUrl}"/>
</xsl:template>
</xsl:stylesheet>
Again the same correct and wanted result is produced:
<a href="www.google.com/?color=red&product=xyz"></a>
The OP asked additionally: "Question: If there is only 'color' param then there is no need of '&' at the end. How to conditionalize that so it wont be added in url? "
Answer: This same solution works correctly in such cases:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:param name="wantedPNames" select="'|color|'"/>
<xsl:template match="/">
<xsl:variable name="vUrl" select=
"for $host in 'www.google.com/',
$qParams in 'color=red;rating=5;page=8;product=xyz',
$qString in string-join(tokenize($qParams, ';')
[contains($wantedPNames, concat('|',tokenize(., '=')[1], '|'))],
'&')
return
concat($host, '?'[$qString], $qString)
"/>
<a href="{$vUrl}"/>
</xsl:template>
</xsl:stylesheet>
Again the correct result is produced:
<a href="www.google.com/?color=red"></a>
Even if no parameters are passed, the result of this same solution will still be correct:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:param name="wantedPNames" select="'||'"/>
<xsl:template match="/">
<xsl:variable name="vUrl" select=
"for $host in 'www.google.com/',
$qParams in 'color=red;rating=5;page=8;product=xyz',
$qString in string-join(tokenize($qParams, ';')
[contains($wantedPNames, concat('|',tokenize(., '=')[1], '|'))],
'&')
return
concat($host, '?'[$qString], $qString)
"/>
<a href="{$vUrl}"/>
</xsl:template>
</xsl:stylesheet>
Again the correct result:
<a href="www.google.com/"></a>
Upvotes: 1