How to avoid creating hyperlink in XSL on some values? - xslt

I have a report that is being generated from the following XSL code. The code generates hyperlink on each number, but I want to avoid creating hyperlink if the value of the variable is zero. Here is my code. Please let me know how can I avoid creating hyperlink when the value is zero
<xsl:choose>
<xsl:when test="Image = '' and not(ValueId = '0')">
<TD style='background-color:#FF6360'>
<xsl:variable name="value">
<xsl:value-of select="ValueId"/>
</xsl:variable>
<xsl:variable name="URL">
<xsl:value-of select="concat('https://google.com/imp/values.aspx?id=', $value)"/>
</xsl:variable>
<a href="{$URL}">
<xsl:value-of select="ValueId"/>
</a>
</TD>
</xsl:when>
</xsl:choose>

The following would test if the value of variable $value is 0 and only if it is not equal to 0 it would create the link:
<xsl:if test="$value!=0">
<a href="{$URL}">
<xsl:value-of select="ValueId"/>
</a>
</xsl:if>
If the type of $value is not a number, the test should be
test="$value!='0'"
Problem in your current code is that you do not generate a table cell if the value is zero - surely you'll want to generate the td even if the value is zero?
Als you seem to have some unnecessary code: first you make a variable for $value that gets initialized by ValueId. You could have done all that in one go directly with ValueId.

Related

XSL stylesheet: creating Hyperlink based of query item_id

I am new to coding. Started XSL coding from past 1 month.
I want to creat a hyperlink according to the item_id.
But my concat is not working as desired.
My requirement is that i have to get create hyperlinks based on the variable item_id
For example:
https://xyz.com/webpr/webpr.php?objtype=frames&g_startlink=maintain&g_startdata=194970&g_userid=msbzzh&g_session_id=6017650`
https://xyz.com/webpr/webpr.php?objtype=frames&g_startlink=maintain&g_startdata=194971&g_userid=msbzzh&g_session_id=6017650
where the variable item_id comes inbetween the link. (194970, 194971 and so on)
So here is my code:
<xsl:when test ="$propName ='item_id'">
<td>
<xsl:variable name="itemId" select="$occRef/#*[local-name()=$propName]" />
<xsl:value-of select="$itemId" />
<xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>
</td>
</xsl:when>
and i also tried like this.. But both of them didn't work out.
<xsl:value-of select="$itemId" />
UPDATED: You forgot to escape ampersands and indeed the variable was used incorrectly. See below the correct syntax.
<xsl:when test="$propName='item_id'">
<td>
<xsl:variable name="itemId" select="$occRef/#*[local-name()=$propName]"/>
<a href="{concat('https://xyz.com/webpr/webpr.php?objtype=frames&g_startlink=maintain&g_startdata=', $itemId, '&g_userid=msbzzh&g_session_id=6017650')}" target="_blank">
<xsl:value-of select="$itemId"/>
</a>
<xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>
</td>
</xsl:when>

XSL transformation with link in variable name

I have the following XSL which I render into my HTML:
<xsl:for-each select="user">
<xsl:variable name="exampleurl">
<xsl:choose>
<xsl:when test="objecttype='2'">
Check this out: 
<strong><a class="link" href="http://www.example.com/beinspired">Inspiration</a></strong>.
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="$exampleurl" />
</xsl:for-each>
However, when I print the variable $exampleurl only the text "Check this out: Inspiration." is printed. But the word "Inspiration" is not a clickable URL like I would want.
How to fix this?
value-of creates a text node, you want
<xsl:copy-of select="$exampleurl" />
(or of course in this case you don't need a variable at all, but I assume that's just the small example?

xslt assigning variable value to string literal

I have
<xsl:for-each select="ancestor-or-self::*">
<xsl:variable name="expression" select="name()" ></xsl:variable>
</xsl:for-each>
below I have href and i want to set the value this expression variable in href #######
Delete
I also tried with :
Delete
None of them worked.
Can Anybody help me out how to do that?
Basically my task is to find the expression for current node and send the expression for the same in href?
Adding More Info :
<br/><xsl:for-each select="ancestor-or-self::*">
<xsl:variable name="expression" select="name()" />
</xsl:for-each>
<b>Click Me</b>
when above xsl code is transformed it is giving below error:
Variable or parameter 'expression' is undefined.
In XSLT1.0, you could try setting the variable like so:
<xsl:variable name="expression">
<xsl:for-each select="ancestor-or-self::*">
<xsl:text>/</xsl:text>
<xsl:variable name="name" select="name()"/>
<xsl:value-of select="$name"/>
</xsl:for-each>
</xsl:variable>
So, assuming the following XML structure
<As>
<a>
<Bs>
<b>5</b>
</Bs>
</a>
<a>
<Bs>
<b>9</b>
</Bs>
</a>
<a/>
<a>
<Bs>
<b>12</b>
<b>14</b>
<b>15</b>
</Bs>
</a>
</As>
If you were positioned on the b element with the value of 14, then expression would be set to /As/a/Bs/b
However, this does not take into account multiple nodes with the same name, and so would not be sufficient if you wanted accurate XPath to select the node.
Instead, you could try the following:
<xsl:variable name="expression">
<xsl:for-each select="ancestor-or-self::*">
<xsl:text>/</xsl:text>
<xsl:variable name="name" select="name()"/>
<xsl:value-of select="$name"/>
<xsl:text>[</xsl:text>
<xsl:value-of select="count(preceding-sibling::*[name() = $name]) + 1"/>
<xsl:text>]</xsl:text>
</xsl:for-each>
</xsl:variable>
This would return /As[1]/a[4]/Bs[1]/b[2], which may be what you want.
Very simply, variables are scoped in XSL and exist only within the containing tag. Thus the variable named expression exists only within the for-each block. Also, variables can only be set once. Attempting to set a variable value a second time has no effect.
Therfore you have to declare the variable at or above the level where you want to use it, and put all the code to generate the value inside the variable declaration. If you can use XSLT2, the following will do what you want:
string-join(for $n in ancestor-or-self::* return name($n), '/')
I know it can also be done in XSLT 1 with a recursive template, but I don't have an example handy.

xslt comma separate list of values

I am creating a summary view of Microsoft InfoPath form(s) using a custom XSLT Stylesheet.
I have a selection of the radio buttons on the form which are clicked "Yes", "No"
e.g.
What is the primary construction of the building?
Steel Yes
No
Timber Yes
NO
etc....
In the stylesheet I have
<tr>
<td>
The primary contruction of the building is
<xsl:choose>
<xsl:when test="/my:myFields/my:BrickPrimaryConstruction= 'true'">
Brick
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="/my:myFields/my:TimberPrimaryConstruction = 'true'">
Timber Framed
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="/my:myFields/my:ConcretePrimaryConstruction = 'true'">
Concrete Framed
</xsl:when>
</xsl:choose>
etc....
What I want to achieve in the final HTML output is something like:
The primary construction of the building is Brick, Concrete Framed, Prefabricated
I have not got much experience of XSLT, but what is the best way of achieving this?
Avoiding this:
, Concrete Framed, Prefabricated,
or
Brick, , Prefabricated
Normally in C# I would assign to a string and check if it is empty before appending a comma and then trim commas on the ends however I know that I cannot assign variables in xslt.
EDIT
I also mentioned that I wanted to be able to reuse the function in other situations such as
<xsl:value-of select="/my:myFields/my:Road"/>,
<xsl:value-of select="/my:myFields/my:District"/>,
<xsl:value-of select="/my:myFields/my:City"/>,
<xsl:value-of select="/my:myFields/my:County"/>,
<xsl:value-of select="/my:myFields/my:Postcode"/>
where these would be separated by comma or a new line character, but there is the possibility that the "District" for example might be blank resulting in "Road, , City" etc.
Try this:
<tr>
<td>
The primary contruction of the building is
<xsl:for-each select="/my:myFields/my:*[ends-with(local-name(), 'PrimaryConstruction') and (.='true')]">
<xsl:if test="position()!=1" xml:space="preserve">, </xsl:if>
<xsl:choose>
<xsl:when test="self::my:BrickPrimaryConstruction">Brick</xsl:when>
<xsl:when test="self::my:TimberPrimaryConstruction">Timber Framed</xsl:when>
<xsl:when test="self::my:ConcretePrimaryConstruction">Concrete Framed</xsl:when>
etc...
</xsl:choose>
</xsl:for-each>
Basically, the for-each loops over all the relevant fields, so that you can check their position and only emit the comma if you're not on the first item (XSLT has a 1-based index). Since the for-each already filters only the relevant entries, we then only have to check the type, not whether the value is true or not.
Note that you can extend the same principle to emit an "and" for the last item instead of a comma if you like to do so.
Maybe look at Implode.
Then, you could do
<xsl:variable name="theItems">
<xsl:if test="/my:myFields/my:BrickPrimaryConstruction= 'true'">
<foo>Brick</foo>
</xsl:if>
</xsl:variable>
<xsl:call-template name="implode">
<xsl:with-param name="items" select="exsl:node-set($theItems)" />
</xsl:call-template>
You have to convert $theItems, which is a xml fragment, to a node-set. This can only be archived using non-standart methods. XML.com shows some methods to archive it using various XML processors.

xsl:variable contains nodeset. How to output nth node of variable?

I am transforming an XML document. There is an attribute #prettydate that is a string similar to "Friday, May 7, 2010". I want to split that string and add links to the month and the year. I am using the exslt:strings module and I can add any other necessary EXSLT module.
This is my code so far:
<xsl:template match="//calendar">
<xsl:variable name="prettyparts">
<xsl:value-of select="str:split(#prettydate,', ')"/>
</xsl:variable>
<table class='day'>
<thead>
<caption><xsl:value-of select="$prettyparts[1]"/>,
<a>
<xsl:attribute name='href'><xsl:value-of select="$baseref"/>?date=<xsl:value-of select="#highlight"/>&per=m</xsl:attribute>
<xsl:value-of select='$prettyparts[2]'/>
</a>
<xsl:value-of select='$prettyparts[3]'/>,
<a>
<xsl:attribute name='href'><xsl:value-of select="$baseref"/>?date=<xsl:value-of select="#highlight"/>&per=y</xsl:attribute>
<xsl:value-of select='$prettyparts[4]'/>
</a>
</caption>
<!--etcetera-->
I have verified, by running $prettyparts through a <xml:for-each/> that I am getting the expected nodeset:
<token>Friday</token>
<token>May</token>
<token>7</token>
<token>2010</token>
But no matter which way I attempt to refer to a particular <token> directly (not in a foreach) I get nothing or various errors to do with invalid types. Here's some of the syntax I've tried:
<xsl:value-of select="$prettyparts[2]"/>
<xsl:value-of select="$prettyparts/token[2]"/>
<xsl:value-of select="exsl:node-set($prettyparts/token[2])"/>
<xsl:value-of select="exsl:node-set($prettyparts/token)[2]"/>
Any idea what the expression ought to be?
ETA: Thanks to #DevNull's suggestion, the correct expression is:
<xsl:value-of select="exsl:node-set($prettyparts)[position()=2]"/>
and, I have to set the variable this way:
<xsl:variable name="prettyparts" select="str:split(#prettydate,', ')" />
Try using [position()=2] instead of [2] in your predicates.
Example:
<xsl:value-of select="$prettyparts[position()=2]"/>