On the variable "urgent", I have put a "replace" on it, so if the string in the variable are "Urgent - 2 arbejdsdage" its changes it to "YES". But if the string are "Overnight" it must also changes it to "YES", can i put a "or" in the style, or must I use "xsl:if" How can i do it ?
<variable name="urgent">
<xsl:variable name ="urgent" select="OrderCustomReferences/CustomReference/ReferenceValue"/>
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:value-of select="replace($urgent, 'Urgent - 2 arbejdsdage', 'Yes')"/>
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</variable>
Related
i've the below xml
<para>A number of the offences set out in the Companies Ordinance are expressed to apply to "officers" of the company. "Officer" includes directors, managers and the company secretary: Companies Ordinance, s.2(1).</para>
here actually the in the input the quotes given are " but i want to convert it to smart quotes. i used the below xslt for this.
<xsl:template match="para/text()">
<xsl:when test="contains(.,$quot)">
<xsl:value-of select="translate(.,$quot,'“')"/>
<xsl:value-of select="translate(substring-after(.,$quot),$quot,'”')"/>
</xsl:when>
</xsl:template>
but i am getting below ooutput.
A number of the offences set out in the Companies Ordinance are expressed to apply to “officers“ of the company. “Officer“ includes directors, managers and the company secretary: Companies Ordinance, s.2(1).
but i want to get it as below.
A number of the offences set out in the Companies Ordinance are expressed to apply to “officers” of the company. “Officer” includes directors, managers and the company secretary: Companies Ordinance, s.2(1).
please let me know how do i solve this.
Thanks
The main problem with your approach is that the translate function will replace all occurrences of the quotation mark with your smart-opening quote. Therefore, the subsequent substring-after function won't actually find anything because there won't be any more quotation marks to find.
What you really need in this case is a recursive template, together with a combination of both substring-before and substring-after. The named template could actually be combined with your existing template, with default parameters to be used in the initial match
<xsl:template match="para/text()" name="replace">
<xsl:param name="text" select="."/>
<xsl:param name="usequote" select="$openquote"/>
($openquote will be a variable containing the opening quote)
You would then check if the selected text contains a quotation mark
<xsl:when test="contains($text,$quot)">
If so, you would first output the text before the quotation mark, following by the new open quote
<xsl:value-of select="concat(substring-before($text, $quot), $usequote)"/>
The template would then be recursively called with the text after the quote, and with the close quote as a parameter, so the next quote find will be closed.
<xsl:call-template name="replace">
<xsl:with-param name="text" select="substring-after($text,$quot)"/>
<xsl:with-param name="usequote"
select="substring(concat($openquote, $closequote), 2 - ($usequote=$closequote), 1)"/>
</xsl:call-template>
Note: the selecting of the usequote will basically switch between open and close quotes. It takes advantage of the fact 'true' evaluates to 1 in a numeric expression, and 'false' to 0.
Try this XSLT. Note, I am using open and close brackets in this case, just to make the output clearer, but you can easily change the variables to your smart quotes as required. (You may have to specify an encoding for the output in this case though).
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:variable name="quot">"</xsl:variable>
<xsl:variable name="openquote">[</xsl:variable>
<xsl:variable name="closequote">]</xsl:variable>
<xsl:template match="para/text()" name="replace">
<xsl:param name="text" select="."/>
<xsl:param name="usequote" select="$openquote"/>
<xsl:choose>
<xsl:when test="contains($text,$quot)">
<xsl:value-of select="concat(substring-before($text, $quot), $usequote)"/>
<xsl:call-template name="replace">
<xsl:with-param name="text" select="substring-after($text,$quot)"/>
<xsl:with-param name="usequote"
select="substring(concat($openquote, $closequote), 2 - ($usequote=$closequote), 1)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When applied to your XML, the following is output
A number of the offences set out in the Companies Ordinance are expressed to apply to [officers] of the company. [Officer] includes directors, managers and the company secretary: Companies Ordinance, s.2(1).
for performance testing purposes I want to take a small XML file and create a bigger one from it - using XSLT. Here I plan to take each entity (Campaign node in the example below) in the original XML and copy it n times, just changing its ID.
The only way I can think of to realize this, is a xsl:for-each select "1 to n". But when I do this I do not seem to be able to access the entity node anymore (xsl:for-each select="campaigns/campaign" does not work in my case). I am getting a processor error: "cannot be used here: the context item is an atomic value".
It seems that by using the "1 to n" loop, I am loosing the access to my actual entity. Is there any XPath expression that gets me access back or does anyone have a completely different idea how to realize this?
Here is what I do:
Original XML
<campaigns>
<campaign id="1" name="test">
<campaign id="2" name="another name">
</cmpaigns>
XSLT I try to use
<xsl:template match="/">
<xsl:element name="campaigns">
<xsl:for-each select="1 to 10">
<xsl:for-each select="campaigns/campaign">
<xsl:element name="campaign">
<xsl:copy-of select="#*[local-name() != 'id']" />
<xsl:attribute name="id"><xsl:value-of select="#id" /></xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:for-each>
</xsl:element>
</xsl:template>
Define a variable as the first thing in the match, like so:
<xsl:variable name="foo" select="."/>
This defines a variable $foo of type nodeset. Then access it like this
<xsl:for-each select="$foo/campaigns/campaign">
...
</xsl:for-each>
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.
I seem to be having an issue preserving the disable-output-escaping when using that value inside of an xsl:copy-of.
Here's my code:
<xsl:call-template name="Display">
<xsl:with-param name="text">
<xsl:value-of select="content" disable-output-escaping="yes" />
</xsl:with-param>
</xsl:call-template>
<xsl:template name="Display">
<xsl:param name="text" />
<span><xsl:copy-of select="$text" /></span>
</xsl:template>
Any special characters that were kept as-is from the xsl:value-of statement are escaped when they're used in the xsl:copy-of statement.
For example:
<xsl:value-of select="$text" disable-output-escaping="yes"> will display this: è
<xsl:copy-of select="$text"> will display è
I'd like to know if there is any way around this?
As per Spec, the disable-output-escaping attribute can be specified only on <xsl:value-of> and the <xsl:text> instructions.
You need the DOE only on the xslt instruction that actually outputs the value, not on one that sets a parameter value.
Solution:
Replace:
<span><xsl:copy-of select="$text"/></span>
with:
<span><xsl:value-of select="$text" disable-output-escaping="yes"/></span>
Do note: Typically one should avoid using DOE, as it breaks the XSLT architectural model and usually isn't needed. Also, the DOE feature isn't mandatory and not all XSLT 1.0 processors support it.
Note 2: You don't actually need DOE in your case at all. The output from the XSLT transformation should be displayed by the browser as expected.
disable-output-escaping controls the action of the serializer when handed a text node. It's meaningless when the text node isn't being handed to a serializer, for example when it is added to a temporary tree.
I have a variable in XSLT called variable_name which I am trying to set to 1, if the Product in question has attributes with name A or B or both A & B.
<xsl:variable name="variable_name">
<xsl:for-each select="product/attributes">
<xsl:if test="#attributename='A' or #attributename='B'">
<xsl:value-of select="1"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
Is there any way to match multiple strings using the if statement, as mine just matches if A is present or B is present. If both A & B are present, it does not set the variable to 1. Any help on this would be appreciated as I am a newbie in XSLT.
You can use xsl:choose statement, it's something like switch in common programming languages:
Example:
<xsl:variable name="variable_name">
<xsl:for-each select="product/attributes">
<xsl:choose>
<xsl:when test="#attributename='A'">
1
</xsl:when>
<xsl:when test=" #attributename='B'">
1
</xsl:when>
<!--... add other options here-->
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
This will set new variable with name variable_name with the value of attribute product/attributes.
For more info ... http://www.w3schools.comwww.w3schools.com/xsl/el_choose.asp
EDIT: And another way (a little dirty) by OP's request:
<xsl:variable name="variable_name">
<xsl:for-each select="product/attributes">
<xsl:if test="contains(text(), 'A') or contains(text(), 'B')">
1
</xsl:if>
</xsl:for-each>
</xsl:variable>
It will be helpful if you provide the xml you're writing your xslt against.
This might not help...
Is it 'legal' to have two XML element attributes with the same name (eg. <element x="1" x="2" />)?
Is this what you are trying to process? Try parsing your XML file through xmllint or something like it to see if it is valid.
xmllint --valid the-xml-file.xml
My guess is that you will get a 'attribute redefined' error.