Check how many characters are in a variable XSL - xslt

Hi there basically I need to find how many characters are in a variable using XSL
if characters($Title == 12) {
execute code;
}
Basically something like above obviously this is incorrect can any one help?

Alternatively you can do the equivalent to and if/else statement in XSL:
<xsl:choose>
<xsl:when test="string-length($Title) = 12">
<!-- code when the check is true -->
</xsl:when>
<xsl:otherwise>
<!-- code when it's false -->
</xsl:otherwise>
</xsl:choose>

In XPath 1.0:
string-length($title) = 12
Take notice that diacritical marks also would be counted.
In XPath 2.0 you cuold use:
string-length(normalize-unicode($title)) = 12

basically I need to find how many
characters are in a variable using XSL
if characters($Title == 12) { execute code; }
Use:
<xsl:if test="string-length($Title) = 12">
<!-- Your code here -->
</xsl:if>

string-length($varname) will tell you the length of a variable containing data that can be interpreted as a string.

Related

XSL 2.0: Format String with _ to CamelCase

I am using XSLT (2.0) as a java code generator. At the moment I have a XML which describes a database table and I want to generate the entity class for it.
The column names of the table are always lowercase with _ between the words.
Example: bat_valid_from
I want to rename it in the Java class to camelcase with first letter lowercase
Example: batValidFrom
Because I need this quiet often in my codeGen I like to have a function for it.
But I only could achieve this with two sub functions.
<xsl:function name="local:VarName">
<xsl:param name="columnName"/>
<xsl:value-of select="lower-case(substring($columnName,1,1))"/>
<xsl:value-of select="substring(local:VarName_sub($columnName),2)"/>
</xsl:function>
<xsl:function name="local:VarName_sub">
<xsl:param name="columnName"/>
<xsl:value-of select="local:VarName_sub_sub($columnName)"/>
</xsl:function>
<xsl:function name="local:VarName_sub_sub">
<xsl:param name="columnName"/>
<xsl:for-each select="tokenize($columnName, '_')">
<xsl:value-of select="upper-case(substring(.,1,1))"/>
<xsl:value-of select="substring(.,2)"/>
</xsl:for-each>
</xsl:function>
Maybe someone has an idea to simplify this?
Without the sub functions I get the following error:
A sequence of more than one item is not allowed as the first argument of fn:substring()
PS: I haven't posted the whole code to shorten the question
XSLT/XPath 2.0 has supports for expressions. You could do this:
string-join(
for $part in tokenize($input, '_')
return concat(
upper-case(substring($part, 1, 1)),
substring($part, 2)
)
, '')
with $input set to 'bat_valid_from', this expression would produce 'BatValidFrom'.
I'm leaving lower-casing (or not upper-casing) the initial letter as an exercise.
With the hint from Tomalak i was able to make all in one function.
Maybe not light weighted but works like a charm.
<xsl:function name="local:VarName">
<xsl:param name="columnName"/>
<xsl:value-of select="
concat(
lower-case(substring($columnName, 1, 1)),
substring(string-join(for $word in tokenize($columnName, '_')
return concat(
upper-case(substring($word, 1, 1)),
substring($word, 2)), '')
, 2))" />
</xsl:function>

XSL concatenation with nested if conditions

I have following xml
<string1>Y</string1>
<string2>aaabbbcccddd</string2>
<string3>I have to concatentate this</string3>
I have to concatenate those three elements as follows.
If flag Y exists for string1 then hard code 'Flag Y exists' + string2 (if exists) + string3.
Please help me with the xsl phrase
Thank you in advance
I don't see a need for nesting here:
<xsl:if test="string1='Y'">
<xsl:value-of select="concat('Flag Y exists', string2, string3)"/>
</xsl:if>
Those three are working, but now in xml i have additional
<string4>string4</string4>. which also should be added to the
concatenation, but only if it is not empty. If this condition is
matched then the hard code 'string4 is not empty' should be added
Here the nesting is needed I suppose...
Yes, but it's fairly trivial:
<xsl:if test="string1='Y'">
<xsl:value-of select="concat('Flag Y exists', string2, string3)"/>
<xsl:if test="string(string4)">string4 is not empty</xsl:if>
</xsl:if>

Space in number format for xsl

I have a number such as: 457342137 but i want to display it as a 457 342 137.
I have something like this:
<xsl:template match="klient/#numer_telefonu">
<xsl:variable name="numer" select="." />
<xsl:value-of select="format-number($numer, '### ### ###')" />
</xsl:template>
but it does not work.
If you want to use a non-standard 'grouping' separator, you first need define the symbols you are going to use in your format command as follows:
<xsl:decimal-format name="spaces" grouping-separator=" " />
Then, you can reference this format in the command itself as follows:
<xsl:value-of select="format-number($numer, '# ###', 'spaces')" />
Further information about decimal-format can be found at http://www.w3.org/TR/xslt#format-number
A telephone number is a string, not a number and you shouldn't try formatting it as one. Technically, you could do:
<xsl:value-of select="translate(format-number(., '#,###'), ',', ' ' )" />
to achieve the desired result in your example. However, given a "number" such as "057342137" the result will be "57 342 137" (leading zeros stripped). You should be using string functions to manipulate a string.

Dynamic choose condition in XSLT

How to use the choose condition in XSLT when the below requirement is needed
<xsl:choose>
<xsl:when test="contains(#name,'top %d holdings' ) ">
<!--code-->
</xsl:when>
</xsl:choose>
It should select all the data containing....
top 5 holdings
top 10 holdings
top 30 holdings
top 27 holdings
top * holdings
If you were using XSLT2.0 here, you could use the matches function which allows you to match text by means of a regular expression
<xsl:when test="matches(#name, '.*top \d+ holdings.*')">
On the other hand, if you were using XSLT 1.0, then the matches function is not available. One way you could do it in your very specific case is extract the text before "holdings" that occurs before "top" and check it is a number:
<xsl:when test="string(number(substring-before(substring-after(#name, 'top '), ' holdings' ) )) != 'NaN'">
You can use substring-before() and substring-after() to get the text between top and holdings, and then use the translate() function to remove numbers and the * character, and then verify that the result is an empty string.
<xsl:choose>
<xsl:when
test="translate(
substring-before(substring-after(#name, 'top '), ' holdings' ),
'0123456789*',
'') = '' ">
<!--code-->
</xsl:when>
</xsl:choose>

Can you put two conditions in an xslt test attribute?

Is this right for When 4 < 5 and 1 < 2 ?
<xsl:when test="4 < 5 AND 1 < 2" >
<!-- do something -->
</xsl:when>
Not quite, the AND has to be lower-case.
<xsl:when test="4 < 5 and 1 < 2">
<!-- do something -->
</xsl:when>
It does have to be wrapped in an <xsl:choose> since it's a when. And lowercase the "and".
<xsl:choose>
<xsl:when test="4 < 5 and 1 < 2" >
<!-- do something -->
</xsl:when>
<xsl:otherwise>
<!-- do something else -->
</xsl:otherwise>
</xsl:choose>
From XML.com:
Like xsl:if instructions, xsl:when
elements can have more elaborate
contents between their start- and
end-tags—for example, literal result
elements, xsl:element elements, or
even xsl:if and xsl:choose elements—to
add to the result tree. Their test
expressions can also use all the
tricks and operators that the xsl:if
element's test attribute can use, such
as and, or, and function calls, to
build more complex boolean
expressions.
Maybe this is a no-brainer for the xslt-professional, but for me at beginner/intermediate level, this got me puzzled. I wanted to do exactly the same thing, but I had to test a responsetime value from an xml instead of a plain number. Following this thread, I tried this:
<xsl:when test="responsetime/#value >= 5000 and responsetime/#value <= 8999">
which generated an error. This works:
<xsl:when test="number(responsetime/#value) >= 5000 and number(responsetime/#value) <= 8999">
Don't really understand why it doesn't work without number(), though. Could it be that without number() the value is treated as a string and you can't compare numbers with a string?
Anyway, hope this saves someone a lot of searching...