XSLT- Get substring and pass it as parameters to java function - xslt

In the below code snippet, I am trying to get the substring of my #imageMeta node, append some more path location and pass it as a parameter to my java method through XSLT.
<xsl:variable name="imagePathFrom" select="/config/assets/images/{substring-after(#imageMeta,'/')}" />
<xsl:variable name="imagePathTo" select="'/dev/svn_root/platform/system'" />
<xsl:value-of select="filecopy:copyFile($imagePathFrom, $imagePathTo)"/>
My #imageMeta node data looks like Images/common/dialog/dialogue_black.png.
I have to convert the above path to images/common/dialog/dialogue_black.png (note the change of capital 'I' to small 'i') and append some more path data.
So my final path entry should look like "/config/assets/images/common/dialog/dialogue_black.png". When i run my code snippet i get an error stating:
line 51: Error parsing XPath expression '/config/assets/images/{substring-after(#imageMeta,'/')}'.'
Please help.

<xsl:variable name="imagePathFrom" select="/config/assets/images/{substring-after(#imageMeta,'/')}" />
There are two problems here:
A syntax error -- a select is probably the only attribute attribute in XSLT that cannot contain an AVT.
Even without the AVT, this would attempt to select all /config/assets/images nodes, but the intent is that the variable must contain the string "/config/assets/images"
Solution to both problems:
<xsl:variable name="imagePathFrom" select=
"concat('/config/assets/images/', substring-after(#imageMeta,'/')" />
Alternative solution:
<xsl:variable name="imagePathFrom" select=
"concat('/config/assets/',
translate(substring(#imageMeta, 1, 1),
$vUpper,
$vLower
),
substring(#imageMeta, 2)
)" />
where $vLower and $vUpper are defined, respectively, as:
'abcdefghijklmnopqrstuvwxyz'
and
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

There is one problem in your code:
<xsl:variable name="imagePathFrom" select="/config/assets/images/{substring-after(#imageMeta,'/')}" />
It suppose to be ..
<xsl:variable name="imagePathFrom" select="substring-after(/config/assets/images/#imageMeta,'/')" />

infant programmer 'Aravind' suggestion will solve your parse error.
You also mentioned you wanted to lower-case the capital i. Two options here:
Using XSLT 1.0, this StackOverflow answer explains how to lower-case the first character of a string. It won't work for Unicode characters such as 'Í' but you probably don't need it.
XSLT 2.0 has a lower-case function, which will lower-case your entire string, and may not be what you're looking for.

Related

replace string in xslt 2.0 with replace function

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')"/>

XSLT - Check if pattern exists in an element string

I have the following element as part of a larger XML
<MT N="NonEnglishAbstract" V="[DE] Deutsch Abstract text [FR] French Abstract text"/>
I need to do some formatting of the value in #V attribute, only if it contains anything like [DE], [FR] or any two capital letters representing a country code within square brackets.
If no such pattern exist, I need to simply write the value of #V without any formatting.
I can use an XSLT 2.0 solution
I was hoping that I could use the matches() function something like
<xsl:choose>
<xsl:when test="matches(#V,'\[([A-Z]{{2}})\]([^\[]+'">
//Do something
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="#V"/>
</xsl:otherwise>
</xsl:choose>
I think all you need is:
matches(#V,'\[[A-Z][A-Z]\]')
You don't have to match the entire string to get a true() ... I tell my students to write as short a reg-ex as possible.
You have not posted anything about what you have tried. How about looking up translate function and translating the strings capital letters to something like "X". Then test that string result for the existence of [XX]. That alone would tell you whether you need to process it.
<xsl:variable name="result">
<xsl:value-of select="translate(#V,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','XXXXXXXXXXXXXXXXXXXXXXXXX')"/>
</xsl:variable>
Then use that result and then test:
contains($result, "[XX]")
No regex required, pure XSL 1.1

Concatenate with escaped chars in xslt?

I'm writing xslt code which concatenates some string:
<xsl:attribute name='src'>
<xsl:value-of select="concat('url(&apos;', $imgSrc, '&apos;)')" />
</xsl:attribute>
For some reason I can't use it, I keep getting this error:
Unknown function - Name and number of arguments do not match any function signature in the static context - 'http://www.w3.org/2005/xpath-functions:concat'
while evaluating the expression:
select="concat('url(&apos;', $imgSrc, '&apos;)')"
Any idea?
thx
====================
EDIT
I'm trying to get:
url('some_path')
Was having trouble with the apostrophes, but now it just doesn't work.
The &apos; references are resolved by the XML parser that parses your XSLT. Your XSLT processor never sees them. What your XSLT processor sees is:
concat('url('', $imgSrc, '')')
Which is not valid because the commas don't end up in the right place to separate the arguments. However, this might work for you, depending on the serializer your XSLT processor uses:
concat("url('", $imgSrc, "')")
This surrounds the arguments in double-quotes, so that your single-quotes do not conflict. The XSLT processor should see this:
concat("url('", $imgSrc, "')")
Another option is to define a variable:
<xsl:variable name="apos" select='"&apos;"'/>
Which can be used like this:
concat('url(', $apos, $imgSrc, $apos, ')')
More here:
When you apply an XSLT stylesheet to a
document, if entities are declared and
referenced in that document, your XSLT
processor won't even know about them.
An XSLT processor leaves the job of
parsing the input document (reading it
and figuring out what's what) to an
XML parser; that's why the
installation of some XSLT processors
requires you to identify the XML
parser you want them to use. (Others
include an XML parser as part of their
installation.) An important part of an
XML parser's job is to resolve all
entity references, so that if the
input document's DTD declares a cpdate
entity as having the value "2001" and
the document has the line "copyright
&cpdate; all rights reserved", the XML
parser will pass along the text node
"copyright 2001 all rights reserved"
to put on the XSLT source tree.
From http://www.w3.org/TR/xpath/#NT-Literal
[29] Literal ::= '"' [^"]* '"' | "'" [^']* "'"
Meaning that an XPath literal string value can't have the delimiter as also part of the content.
For this you should use the host language. In XSLT:
<xsl:variable name="$vPrefix">url('</xsl:variable>
<xsl:variable name="$vSufix">')</xsl:variable>
<xsl:attribute name="src">
<xsl:value-of select="concat($vPrefix, $imgSrc, $vSufix)" />
</xsl:attribute>
Or more proper:
<xsl:attribute name="src">
<xsl:text>url('</xsl:text>
<xsl:value-of select="$imgSrc"/>
<xsl:text>')</xsl:text>
</xsl:attribute>

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?