XSL concatenation with nested if conditions - xslt

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>

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>

xslt mapping to find substring between

I have my string as below
<Text>Pack:NA Lead:20 Dimension:235</Text>
And need to map
NA to outputfield1
20 to outputfield2
235 to outputfield3
How to do this correctly in xslt mapping where the values 'NA,20,235' could be different each time?
I could only see substring component which takes length as second parameter.
That leads requires several steps to achieve this.
Any better solution to just take the value between Lead: and Dimension for outputfield2?
To extract the Pack value, you can use:
<xsl:value-of select="substring-before(substring-after(Text, 'Pack:'), ' ')" />
To extract the Lead value, use:
<xsl:value-of select="substring-before(substring-after(Text, 'Lead:'), ' ')" />
To extract the Dimension:
<xsl:value-of select="substring-after(Text, 'Dimension:')" />

how to parse the value from xml through xsl

<block4>
<tag>
<name>50K</name>
<value>/001/002/300060000120135670
CREDIT AGRICOLE ASSET MANAGEMENT</value>
</tag>
</block4>
I need to get output that looks like:
/001/002,/300060000120135670,CREDIT AGRICOLE ASSET MANAGEMENT
I have done like this in XSL, but I didn't get the output I wanted. Can anyone please give me some idea how I could get that output?
<xsl:for-each select ="block4/tag[name = '50K']">
<xsl:value-of select="
concat(
substring(value,1,8),
(concat(substring(value,9,'
'),',')),
substring-after(value,'
')
)
" />,<xsl:text/>
</xsl:for-each>
concat takes any number of arguments, no need to nest those calls. Besides, substring takes a beginning and an optional length, not a terminating character. Try something like this instead:
<xsl:for-each select ="block4/tag[name = '50K']">
<xsl:value-of select="
concat(
substring(value, 1, 8), ',',
substring(substring-before(value,'
'),9), ',',
substring-after(value,'
')
)
" />,<xsl:text/>
</xsl:for-each>
I've kept the final comma in, which is one of the many things you did not really specify.
Why not use XSLT 2.0 tokenize() function?
See Here

Check how many characters are in a variable XSL

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.

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...