I have the following bit of xsl inside a template:
<xsl:variable name="current_x" select="position_x" />
<xsl:variable name="current_y" select="position_y" />
<xsl:if test="units_display='true'">
<xsl:call-template name="DisplayBox">
<xsl:with-param name="value"><xsl:value-of select="units" /></xsl:with-param>
<xsl:with-param name="text" select="'Units'" />
</xsl:call-template>
</xsl:if>
<xsl:if test="sensor_display='true'">
<xsl:call-template name="DisplayBox">
<xsl:with-param name="value"><xsl:value-of select="sensor" /></xsl:with-param>
<xsl:with-param name="text" select="'Type'" />
</xsl:call-template>
</xsl:if>
My call-template is like this:
<xsl:template name="DisplayBox">
<xsl:param name="current_x" select="0"/>
<xsl:param name="current_y" select="0"/>
<xsl:param name="value" />
<xsl:param name="text" />
<g transform="translate({$current_x},{$current_y})">
<rect x="20" y="150" width="220" height="20" fill="#FFFFFF" stroke="black" stroke-width="1" />
<text x="25" y="168" font-family="arial" font-size="20px" fill="black">
<xsl:value-of select="$value"/>
</text>
<line x1="90" y1="150" x2="90" y2="170" stroke="black" stroke-width="1" />
<text x="95" y="168" font-family="arial" font-size="20px" fill="black">
<xsl:value-of select="$text" />
</text>
</g>
</xsl:template>
This displays the value of 'value' and 'text' inside a rectangle. The thing I cannot work out how to do, however, is to not have them write on top of each other. I want to increase the current_y value if the test="xxxx_display=true. But I am at a loss of how to achieve this.
I can't work out how I can increase the value of current_y outside of the call-template.
EDIT:
There seems to be a problem in using transform translate in the call-template. It seems to ignore those values.
I have modded the code to now be:
<xsl:if test="units_display='true'">
<g transform="translate({position_x},{position_y})">
<xsl:call-template name="DisplayBox">
<xsl:with-param name="value">
<xsl:value-of select="units" />
</xsl:with-param>
<xsl:with-param name="text" select="'Units'" />
</xsl:call-template>
</g>
</xsl:if>
<xsl:if test="sensor_display='true'">
<g transform="translate({position_x},{position_y + 20})">
<xsl:call-template name="DisplayBox">
<xsl:with-param name="value">
<xsl:value-of select="sensor" />
</xsl:with-param>
<xsl:with-param name="text" select="'Type'" />
</xsl:call-template>
</g>
</xsl:if>
But, I don't want to hard-code 'position_y + 20'. I would like the 2nd value to be at position_y if the first value display was not true, but the 2nd value to be at position_y + 20 if the first value display was true. This must be possible somehow I would hope.
By the way, don't do this:
<xsl:with-param name="value"><xsl:value-of select="sensor" /></xsl:with-param>
when you mean this:
<xsl:with-param name="value" select="sensor" />
It's not only verbose, it's also incredibly inefficient: instead of simply passing a reference to a value, you are constructing a temporary tree containing a text node that holds a copy of the value. Creating new trees is an expensive operation.
Simply pass the the parameters current_x and current_y with the adjusted values like this:
<xsl:if test="units_display='true'">
<xsl:call-template name="DisplayBox">
<xsl:with-param name="value"><xsl:value-of select="units" /></xsl:with-param>
<xsl:with-param name="text" select="'Units'" />
<xsl:with-param name="current_x" select="position_x"/>
<xsl:with-param name="current_y" select="position_y + 100"/>
</xsl:call-template>
</xsl:if>
<xsl:if test="sensor_display='true'">
<xsl:call-template name="DisplayBox">
<xsl:with-param name="value"><xsl:value-of select="sensor" /></xsl:with-param>
<xsl:with-param name="text" select="'Type'" />
<xsl:with-param name="current_x" select="position_x"/>
<xsl:with-param name="current_y" select="position_y + 200"/>
</xsl:call-template>
</xsl:if>
EDIT: If you want to go with the second approach, try to change the sensor_display part to:
<xsl:if test="sensor_display='true'">
<xsl:variable name="offset">
<xsl:choose>
<xsl:when test="units_display='true'">20</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<g transform="translate({position_x},{position_y + $offset})">
<xsl:call-template name="DisplayBox">
<xsl:with-param name="value">
<xsl:value-of select="sensor" />
</xsl:with-param>
<xsl:with-param name="text" select="'Type'" />
</xsl:call-template>
</g>
</xsl:if>
BTW, if you rephrase your question like this, it's better to start a new question.
Related
I want to create an element(Parameter) n number of times. I used the following method to create an element "Parameter" which contain the value from the Split template. Each recursion create the element "Parameter". How can I check how many time was the element "Parameter" created and and if it was less than n then how can I create it n number of times with no values.
<xsl:call-template name="Split">
<xsl:with-param name="text" select="Set string "{attribute}" value "{stringValue}"" />
</xsl:call-template>
<xsl:template name="Split">
<xsl:param name="text" select="''" />
<xsl:variable name="tag" select="substring-before(substring-after($text, '"'), '"')" />
<xsl:variable name="tail" select="substring-after($text, '"')" />
<xsl:choose>
<xsl:when test="$tag != ''">
<xsl:element name = "Paramter">
<xsl:value-of select = "$tag"/>
</xsl:element>
<!--recursive step start: process the remainder of the string -->
<xsl:call-template name="Split">
<xsl:with-param name="text" select="$tail" />
</xsl:call-template>
<!--recursive step end: process the remainder of the string -->
</xsl:when>
</xsl:choose>
</xsl:template>
the Output (for n=9) should look something like this,
<Parameter>attribute</Parameter>
<Parameter>value</Parameter>
<Parameter>StringValue</Parameter>
<Parameter></Parameter>
<Parameter></Parameter>
<Parameter></Parameter>
<Parameter></Parameter>
<Parameter></Parameter>
<Parameter></Parameter>
If you call the template like this:
<xsl:call-template name="Split">
<xsl:with-param name="text" select="'Set string "{attribute}" value "{stringValue}"'" />
<xsl:with-param name="n" select="9" />
</xsl:call-template>
and adjust it so:
<xsl:template name="Split">
<xsl:param name="text"/>
<xsl:param name="n"/>
<xsl:if test="$n > 0">
<Parameter>
<xsl:value-of select="substring-before(substring-after($text, '"'), '"')" />
</Parameter>
<!--recursive call -->
<xsl:call-template name="Split">
<xsl:with-param name="text" select="substring-after($text, '"')" />
<xsl:with-param name="n" select="$n - 1" />
</xsl:call-template>
</xsl:if>
</xsl:template>
Then the result will be:
<Parameter>{attribute}</Parameter>
<Parameter> value </Parameter>
<Parameter>{stringValue}</Parameter>
<Parameter/>
<Parameter/>
<Parameter/>
<Parameter/>
<Parameter/>
<Parameter/>
Note that this exits after 9 iterations. If the string has more than 9 tokens, only the first 9 will appear in the output.
I want to Increment variable in for-each loop. Here is my code.
<xsl:variable name="i" select="1" />
<xsl:variable name="oddEven" select="1" />
<xsl:for-each select="//ProfileBR">
<xsl:variable name="j" select="$i + 1" />
sharad j :: <xsl:value-of select="$j"></xsl:value-of>
<xsl:variable name="iBR" select="substring(//BRValue,$i,1)" />
<xsl:variable name="jBR" select="substring(//BRValue,$j,1)" />
<xsl:if test="$iBR='1' or $jBR='1'">
<xsl:choose>
<xsl:when test="$oddEven='1'">
<tr class="sbListOddCell">
<xsl:call-template name="JobInfoSection">
<xsl:with-param name="ii" select="$i"/>
<xsl:with-param name="jj" select="$j"/>
<xsl:with-param name="iiBR" select="$iBR"/>
<xsl:with-param name="jjBR" select="$jBR"/>
</xsl:call-template>
</tr>
<xsl:variable name="oddEven" select="0" />
</xsl:when>
<xsl:otherwise>
<tr class="sbListEvenCell">
<xsl:call-template name="JobInfoSection">
<xsl:with-param name="ii" select="$i"/>
<xsl:with-param name="jj" select="$j"/>
<xsl:with-param name="iiBR" select="$iBR"/>
<xsl:with-param name="jjBR" select="$jBR"/>
</xsl:call-template>
</tr>
<xsl:variable name="oddEven" select="1" />
</xsl:otherwise>
</xsl:choose>
</xsl:if>
<xsl:variable name="i" select="$j + 1" />
</xsl:for-each>
I want to increment i and j in every iteration but it ends up with 3 and 2 respectively after each iteration.
How can I increment i and j.
Thanks,
Sharad
Use position() to get the count of the iteration inside the for-each like this:
<xsl:variable name="j" select="$i + position()" />
I am using XSLT 2.0 and have a variable who contains dates separated by comma. I try to tokenize this variable in a for-each but in execution, I have the error: "Cannot select a node here: the context item is an atomic value"
Here is my code:
<xsl:variable name="datesMois">
<xsl:call-template name="dayOfMonth">
<xsl:with-param name="pDay" select="01" />
<xsl:with-param name="pMonth" select="/workfile/query/#month" />
<xsl:with-param name="pYear" select="/workfile/query/#year" />
</xsl:call-template>
</xsl:variable>
<xsl:variable name="currentstartdate" select="substring-before(., 'T')" />
<xsl:for-each select="tokenize($datesMois,',')">
<xsl:variable name="dateJour" select="." />
...
The template dayOfMonth returns the days for the month given in parameters.
I don't understand what is wrong in my code, could you please help me?
Thanks.
Assuming you have something like
<xsl:variable name="datesMois">
<xsl:call-template name="dayOfMonth">
<xsl:with-param name="pDay" select="01" />
<xsl:with-param name="pMonth" select="/workfile/query/#month" />
<xsl:with-param name="pYear" select="/workfile/query/#year" />
</xsl:call-template>
</xsl:variable>
<xsl:variable name="currentstartdate" select="substring-before(., 'T')" />
<xsl:for-each select="tokenize($datesMois,',')">
<xsl:variable name="dateJour" select="." />
<xsl:value-of select="foo[date = $dateJour]"/>
you would get the error you describe, to avoid that you would need to store the context node outside of the for-each in a variable as in
<xsl:variable name="datesMois">
<xsl:call-template name="dayOfMonth">
<xsl:with-param name="pDay" select="01" />
<xsl:with-param name="pMonth" select="/workfile/query/#month" />
<xsl:with-param name="pYear" select="/workfile/query/#year" />
</xsl:call-template>
</xsl:variable>
<xsl:variable name="currentstartdate" select="substring-before(., 'T')" />
<xsl:variable name="context" select="."/>
<xsl:for-each select="tokenize($datesMois,',')">
<xsl:variable name="dateJour" select="." />
<xsl:value-of select="$context/foo[date = $dateJour]"/>
I had to guess how your code might look that causes the error, if you still have problems then post the exact line of your code that causes the error.
I need to make a CSV-parser using XSLT 1.0. I have tried a recursive approach, but I can't seem to match the line endrings, so the input to the printLine-template is always empty.
<xsl:template match="/">
<xsl:call-template name="printLine">
<xsl:with-param name="line">
<xsl:value-of select="substring-before(//csvText, '\n')"/>
</xsl:with-param>
<xsl:with-param name="remaining">
<xsl:value-of select="substring-after(//csvText, '\n')"/>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="printLine">
<xsl:param name="line"/>
<xsl:param name="remaining"/>
<xsl:value-of select="$line"/><br />
<xsl:if test="remaining != ''">
<xsl:call-template name="printLine">
<xsl:with-param name="line">
<xsl:value-of select="substring-before($remaining, '\n')"/>
</xsl:with-param>
<xsl:with-param name="remaining">
<xsl:value-of select="substring-after($remaining, '\n')"/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
I found a solution to this:
<xsl:variable name="ls"><xsl:text>
</xsl:text></xsl:variable>
<xsl:variable name="fs"><xsl:text> </xsl:text></xsl:variable>
<xsl:template match="/">
<xsl:call-template name="printLine">
<xsl:with-param name="line" select="substring-before(//csvText, $ls)"/>
<xsl:with-param name="remaining" select="substring-after(//csvText, $ls)"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="printLine">
<xsl:param name="line"/>
<xsl:param name="remaining"/>
<xsl:call-template name="printFields">
<xsl:with-param name="line" select="$line"/>
</xsl:call-template>
<xsl:if test="$remaining != ''">
<xsl:call-template name="printLine">
<xsl:with-param name="line" select="substring-before($remaining, $ls)"/>
<xsl:with-param name="remaining" select="substring-after($remaining, $ls)"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="printFields">
<xsl:param name="line"/>
<!-- render each line and access each field using the getFieldByIndex-template. Example: -->
<div>
<h3>
<xsl:call-template name="getFieldByIndex">
<xsl:with-param name="index" select="1"/>
<xsl:with-param name="line" select="$line"/>
</xsl:call-template>
</h3>
<p>
<xsl:call-template name="getFieldByIndex">
<xsl:with-param name="index" select="4"/>
<xsl:with-param name="line" select="$line"/>
</xsl:call-template>
</p>
</div>
</xsl:template>
<xsl:template name="getFieldByIndex">
<xsl:param name="index"/>
<xsl:param name="line"/>
<xsl:choose>
<xsl:when test="$index > 0">
<xsl:call-template name="getFieldByIndex">
<xsl:with-param name="index" select="$index -1"/>
<xsl:with-param name="line" select="substring-after($line, $fs)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-before($line,$fs)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
The line- and field separators are stored in the ls and fs variables. This example traverses a tab-serparated file. The printFields-template has to be customized for each use.
In XPATH 2.0 there is a function that allows me to replace a substring in a string with another string. I'd like to do this using xalan. Unfortunately, it doesn't support the EXSLT method str:replace and it only uses XSLT 1.0 stylesheets. Including the function from exslt.org doesn't seem to work. If I try using the function style, it complains that it can't find str:replace. If I try using the template style, it complains that it can't find node-set, even though it is supported. translate is useless since it's just a character swap. Any ideas?
You can write your own function which can immitate xslt 2.0 replace :
<xsl:template name="replace">
<xsl:param name="text" />
<xsl:param name="replace" />
<xsl:param name="by" />
<xsl:choose>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text,$replace)" />
<xsl:value-of select="$by" />
<xsl:call-template name="replace">
<xsl:with-param name="text"
select="substring-after($text,$replace)" />
<xsl:with-param name="replace" select="$replace" />
<xsl:with-param name="by" select="$by" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
If you call it like this :
<xsl:variable name="replacedString">
<xsl:call-template name="replace">
<xsl:with-param name="text" select="'This'" />
<xsl:with-param name="replace" select="'This'" />
<xsl:with-param name="by" select="'That'" />
</xsl:call-template>
Your resulting $replacedString will have the value "That"