replace string in xslt 2.0 with replace function - xslt

I have a string like this
"My string"
Now I want to replace my with best so that the output will be like best string.
I have tried some thing like this
<xsl:value-of select="replace( 'my string',my,best)"/>
but probably its a wrong syntax
I have googled a lot but found nothing..every where the mechanism to do this XSLT 1.0 is explained.Can any one tell me how to do it in XSLT 2.0 ,The easy way compared to 1.0

Given:
<xsl:variable name="s1" select="'My string'"/>
Simply use:
<xsl:value-of select="replace($s1, 'My', 'best')"/>
Note that a regular expression is applied. Meaning:
<xsl:value-of select="replace('test.replace', '.', ':')"/>
Becomes:
::::::::::::
Be sure to escape the characters that have special meaning to the regular expression interpreter:
<xsl:value-of select="replace('test.replace', '\.', '::')"/>
Becomes:
test::replace

First check, if your xslt processor (saxxon) is the latest release. Then you have to set
<xsl:stylesheet version="2.0" in the head of your xslt-stylesheet. That's it.
Your code was fine, besides you forgot the apostrophs:
<xsl:value-of select="replace( 'my string',my,best)"/>
must be
<xsl:value-of select="replace('my string','my','best')"/>

Related

apostrophe in xsl:format-number

I parse an xml with my xslt and get the result as a xml.
i need to format numbers with apostrophe as delimiter for a tousand, million, etc...
eg: 1234567 = 1'234'567
now the problem is how do i get these apostrophes in there?
<xsl:value-of select="format-number(/path/to/number, '###'###'###'###')" />
this doesn't work because the apostrophe itself is already delimiting the start of the format.
is there a simple solution to that (maybe escaping the apostrophe like in c#?
The answer depends on whether you are using 1.0 or 2.0.
In 2.0, you can escape the string delimiter by doubling it (for example 'it''s dark'), and you can escape the attribute delimiter by using an XML entity such as ". So you could write:
<xsl:value-of select="format-number(/path/to/number, '###''###''###''###')" />
In 1.0, you can escape the attribute delimiter by using an XML entity, but there is no way of escaping the string delimiter. So you could switch your delimiters and use
<xsl:value-of select='format-number(/path/to/number, "###&apos;###&apos;###&apos;###")' />
The other way - probably easier - is to put the string in a variable:
<xsl:variable name="picture">###'###'###'###</xsl:variable>
<xsl:value-of select="format-number(/path/to/number, $picture)" />
After some research we came up with this solution:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:decimal-format name='ch' grouping-separator="'" />
<xsl:template match="/">
<xsl:value-of select='format-number(/the/path/of/the/number, "###&apos;###&apos;###", "ch")'/>
...

XSL - Escaping an apostrophe during xsl:when test

I have the following code which appears to be failing.
<xsl:when test="$trialSiteName = 'Physician&apos;s Office'">
Also, visual studio is complaining saying
"Expected end of expression, found 's"
How am I supposed to escape the character?
XSLT v1.0. Apache XSL-FO processor.
Much more simple -- use:
<xsl:when test="$trialSiteName = "Physician&apos;s Office"">
Declare a variable:
<xsl:variable name="apos" select='"&apos;"'/>
Use the variable like this in the <xsl:when> clause:
<xsl:when test="$trialSiteName = concat('Physician', $apos, 's Office')">
&apos; works for XPath 1.0. If you are using XSLT 2.0 with XPath 2.0 try double apostrophe:
<xsl:when test="$trialSiteName = 'Physician''s Office'">
Look for a full explanation by Dimitre Novatchev in his answer Escape single quote in xslt concat function
in between " you can add what ever special characters you want.
<xsl:when test="$trialSiteName = "Physician's what ever special charactors plainly add Office"">

XSLT shorter version of OR conditional statement

I was wondering if someone remembers how to write a shorter OR statements in XSLT. I'm sure there was a way but I can't remember.
So instead of
test="$var = 'text1' or $var = 'text2'"
I'd like to use a shorter version like test="$var =['text1','text2']" However, I can't remember or find the right shorthand syntax for such cases.
Would really appreciate if someone could help with that!
Many thanks
With XSLT 2.0 (but not with XSLT 1.0) you can do
<xsl:if test="$var = ('text1','text2')">
Maybe that is the syntax you are looking for.
For string values as you appear to be using you can use a concat trick:-
test="contains('__text1____text2__', concat('__', $var, '__'))"
Not shorter for just two items but given 5 or more it starts to look better.
Having said that you probably can multi-line when using or's so it may be better just to use a series of or's:-
test = "
$var = 'text1'
or $var = 'text2'
or $var = 'text3'
or $var = 'text3'"
More text but clearer solution.
If you find that you do many comparisons against a fixed set of values, you can also do this:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:cfg="http://tempuri.org/config"
exclude-result-prefixes="cfg"
>
<xsl:output method="text" />
<!-- prepare a fixed list of possible values; note the namespace -->
<config xmlns="http://tempuri.org/config">
<val>text1</val>
<val>text2</val>
<!-- ... -->
</config>
<!-- document('') lets you access the stylesheet itself -->
<xsl:variable name="cfg" select="document('')/*/cfg:config/cfg:val" />
<xsl:template match="/">
<xsl:variable name="var" select="'text2'" />
<!-- check against all possible values in one step -->
<xsl:if test="$cfg[.=$var]">
<xsl:text>Match!</xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
The above would print
Match!
The [] operator only works on a nodeset. Maybe you're thinking of when you say something like [a|b] to select nodes from your nodeset that have a child element a or a child element b. But for string comparison I don't know of any way other than using "or".
There is no 'contains' function for sequences, but you could use index-of or intersect:
fn:exists(('test1', 'test2') intersect $var))
or
fn:exists(fn:index-of(('test1', 'test2'), $var))
With only two strings, your original solution is shorter though.

How do I convert strings starting with numbers to numeric data in XSLT?

Given the following XML:
<table>
<col width="12pt"/>
<col width="24pt"/>
<col width="12pt"/>
<col width="48pt"/>
</table>
How can I convert the width attributes to numeric values that can be used in mathematical expressions? So far, I have used substring-before to do this. Here is an example template (XSLT 2.0 only) that shows how to sum the values:
<xsl:template match="table">
<xsl:text>Col sum: </xsl:text>
<xsl:value-of select="sum(
for $w
in col/#width
return number(substring-before($w, 'pt'))
)"/>
</xsl:template>
Now my questions:
Is there a more efficient way to do the conversion than substring-before?
What if I don't know the text after the numbers? Any way to do it without using regular expressions?
This is horrible, but depending on just how much you know about the potetntial set of non-numeric characters, you could strip them with translate():
translate("12jfksjkdfjskdfj", "abcdefghijklmnopqrstuvwxyz", "")
returns
"12"
which you can then pass to number() as currently.
(I said it was horrible. Note that translate() is case sensitive, too)
I found this answer from Dimitre Novatchev that provides a very clever XPATH solution that doesn't use regex:
translate(., translate(.,'0123456789', ''), '')
It uses the nested translate to strip all the numbers from the string, which yields all other characters, which are used as the values for the wrapping translate function to strip out and return just the number characters.
Applied to your template:
<xsl:template match="table">
<xsl:text>Col sum: </xsl:text>
<xsl:value-of select="sum(
for $w
in col/#width
return number(translate($w, translate($w,'0123456789', ''), ''))
)"/>
</xsl:template>
If you are using XSLT 2.0 is there a reason why you want to avoid using regex?
The most simple solution would probably be to use the replace function with a regex pattern to match on any non-numeric character and replace with empty string.:
replace($w,'[^0-9]','')

XSL - Invalid Xpath Extension on Replace

Im getting on error when I try and use the following:
<xsl:variable name="url" select="guid"/>
<xsl:variable name="vid" select="substring-after($url,'podcast/')"/>
<xsl:variable name="pre" select="substring-before($vid,'.mp4')"/>
<<xsl:variable name="p" select="replace($pre,'_','-')"/>
<xsl:variable name="p1" select="concat($p,'.embed_thumbnail.jpg')"/>
<xsl:variable name="p2" select="concat('http://images.ted.com/images/ted/tedindex/embed-posters/',$p1)"/>
Can anyone see a problem, it all looks good to me?
Are you using an XSLT 1 processor? The replace function appeared in XPath 2.0 and is therefore not available in XSLT 1.
In this case you could just use the translate function instead.
You have an extra unescaped less-than sign before your p variable's definition:
<<xsl:variable name="p" select="replace($pre,'_','-')"/>
That's not valid syntax.
You should either remove it:
<xsl:variable name="p" select="replace($pre,'_','-')"/>
Or escape it:
<<xsl:variable name="p" select="replace($pre,'_','-')"/>
I see a '<<' at the start of line 4, is that it?