Replacing specific character to lowercase using xsl - xslt

Hi i have an xml as below.
<setField identifier=”2”>
<fieldValues>
<fieldValue>
<field>event</field>
<value>
<boundVariable>$event1</boundVariable>
</value>
<type>java.lang.String</type>
</fieldValue>
</fieldValues>
<variable>append</variable>
</setField>
I need to convert to the following format.
<freeForm><text>append.setEvent($event1);</freeForm></text>
I am trying the following approach.
<xsl:template match="setField" name="setFieldTemplate">
<xsl:element name="freeForm">
<xsl:element name="text">
<xsl:value-of select="variable" />
<xsl:text>.set</xsl:text>
<xsl:value-of select="concat(translate(substring(field, 1, 1)"/>
<xsl:text>(</xsl:text>
<xsl:value-of select="boundVariable"/>
<xsl:text>);</xsl:text>
</xsl:element>
</xsl:element>
</xsl:template>
Here my requirment is based on the field name i need to generate corresponding statement as below.For that i need to change the first character of the field name to upper while generating to the following format.
append.setEvent($event1);
Here the field name is "event" and i need to generate setEvent(for which i am concatinating with the string "set").But i need to change the fieldname's first letter to upper one(Event from event).when i try with the above template with translate function i am facing some invalid xpath expression.
Please provide me some pointers to do the same.

<xsl:value-of select="concat(
variable,
'.set',
translate(substring(//field, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
substring(//field, 2),
'(',
//boundVariable,
');'
)"/>

You want:
<xsl:value-of select="concat(
translate(substring(//field, 1, 1),
'abcdefghijklmnstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
substring(//field, 2))"/>
Also you might prefer:
<xsl:template match="setField">
<freeForm>
<text>
<xsl:value-of select="variable" />
<xsl:text>.set</xsl:text>
<xsl:value-of select="concat(
translate(
substring(fieldValues/fieldValue/field, 1, 1),
'abcdefghijklmnstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
substring(fieldValues/fieldValue/field, 2),
'(',fieldValues/fieldValue/value/boundVariable,');')"/>
</text>
</freeForm>
</xsl:template>

Related

How get first name initial and last name in XSLT

I want yo get the first name initial and last name.
Input :
<root>
<ele name="Samp Huwani"/>
<ele name="Gong Gitry"/>
<ele name="Dery Wertnu"/>
</root>
Output
<names>S Huwani</name>
<names>G Gitry</name>
<names>D Wertnu</name>
Tried Code:
<xsl:template match="root/name">
<names>
<xsl:value-of select="#name" />
</name>
</xsl:template>
I am using XSLT 2.0 . Thank you
With the given example, you could use:
<xsl:template match="/root">
<xsl:copy>
<xsl:for-each select="ele">
<name>
<xsl:value-of select="substring(#name, 1, 1)"/>
<xsl:text> </xsl:text>
<xsl:value-of select="substring-after(#name, ' ')"/>
</name>
</xsl:for-each>
</xsl:copy>
</xsl:template>
However, names often do not conform to the same pattern.
In XSLT 2.0, you could simplify(?) this by using regex, e.g.:
<xsl:value-of select="replace(#name, '^(.{1}).* (.*)', '$1 $2')"/>

XSLT 1.0 String Length - 2

I need to check the length of a field and then add . before last two
digits.
Example: the value of Amount is 0001234567, to be replaced as 00012345.67. Here string length will be 10.
But the command fails and is not able to retrieve the value from
($VARAmtLength-2) or ($VARAmtLength-1).
My code as below:
<xsl:variable name="VARAmtLength" select="string-length (ns0:Amount )"/>
<xsl:if test=" ($VARAmtLength> 0)">
<tns:Amount>
<xsl:value-of select="concat(substring(ns0:Amount, 1, ($VARAmtLength- 2)),'.', substring(ns0:Amount, ($VARAmtLength-1, 2)))"/>
</tns:Amount>
</xsl:if>
Any help?
I think your code is working fine.
Just replace this line with existing one:
<xsl:value-of select="concat(substring(ns0:Amount, 1, ($VARAmtLength - 2)),'.', substring(ns0:Amount, ($VARAmtLength - 1), 2))" />
1. There should be a space around subtraction operator '-'. Otherwise it will consider $VARAmtLength- as variable name.
2. You had misplaced round parentheses for second substring() function.
XML
<amount>0001234567</amount>
Xsl
<xsl:template match="/">
<xsl:variable name="length" select="//amount"/>
<xsl:if test="$length>0">
<amount>
<xsl:variable name="ajeet" select="concat(substring(//amount, 1, 8), '.')"/>
<xsl:variable name="kumar" select="substring(//amount, 9, 2)"/>
<xsl:value-of select="concat($ajeet, $kumar)"/>
</amount>
</xsl:if>
</xsl:template>

Partially rename an XML node

Given the XML snippet:
<rng:define name="starting_limits">
<rng:element name="limits">
<rng:ref name="Limits"/>
</rng:element>
</rng:define>
I want this:
<rng:define name="limits">
<rng:element name="limits">
<rng:ref name="Limits"/>
</rng:element>
</rng:define>
For all define elements. So I just want to remove the "starting_" prefix for all define element name attributes in the infoset.
you can use this:
<xsl:template match="#*[starts-with(., 'starting_')]">
<xsl:attribute name="{name()}" select="replace(., 'starting_', '')"/>
</xsl:template>
it matched all attribute start-with 'starting_' and remove it from output
In your XML the attribute is called name and has a value of starting_xxxx, so to match it, you would do this...
<xsl:template match="#name[starts-with(., 'starting_')]">
Or maybe this, in XSLT 2.0 and above
<xsl:template match="#name[matches(., 'starting_.*')]">
To remove the starting_attribute you can do one of the following, for example
<xsl:value-of select="substring-after(., 'starting_')"/>
<xsl:value-of select="substring(., 10)"/>
So, for example, your template may look like this
<xsl:template match="#name[starts-with(., 'starting_')]">
<xsl:attribute name="name">
<xsl:value-of select="substring(., 10)"/>
</xsl:attribute>
</xsl:template>
If you wanted to make it more generic, and match any attribute, not just one called name, you could change it to this
<xsl:template match="#*[starts-with(., 'starting_')]">
<xsl:attribute name="{name()}">
<xsl:value-of select="substring(., 10)"/>
</xsl:attribute>
</xsl:template>

XSL fetch min/max of modified attributes into variables

I would like to find a "nicer" solution to get the minimum and maximum values of attributes and save them into accesible variables. I would love to get away from the for-each-loop too. How is that possible?
My XML:
<Rows>
<Entry value1="16,423" value2="18,123" />
<Entry value1="423" value2="11,588" />
<Entry value1="1,168" value2="521" />
</Rows>
And my XSL:
<xsl:for-each select="Rows/Entry/#value1|Rows/Entry/#value2">
<xsl:sort select="." data-type="number" />
<xsl:choose>
<xsl:when test="position() = 1">
<xsl:variable name="min" select="format-number(translate(.,',',''),'#')" />
</xsl:when>
<xsl:when test="position() = last()">
<xsl:variable name="max" select="format-number(translate(.,',',''),'#')" />
</xsl:when>
</xsl:choose>
</xsl:for-each>
The desired output should be $min=423 and $max=18123 as numbers and accesible outside the for-each-loop
Well there is XSLT 2.0 since 2007 (implemented by XSLT processors like Saxon 9, AltovaXML, XmlPrime) where you can simply do (assuming you have the declaration xmlns:xs="http://www.w3.org/2001/XMLSchema" on your xsl:stylesheet element):
<xsl:variable name="min" select="min(Rows/Entry/(#value1, #value2)/xs:decimal(translate(., ',', ''))"/>
<xsl:variable name="max" select="max(Rows/Entry/(#value1, #value2)/xs:decimal(translate(., ',', ''))"/>
If you really want to store a formatted string in a variable you can of course do that as well with e.g.
<xsl:variable name="min" select="format-number(min(Rows/Entry/(#value1, #value2)/xs:decimal(translate(., ',', '')), '#')"/>
<xsl:variable name="max" select="format-number(max(Rows/Entry/(#value1, #value2)/xs:decimal(translate(., ',', '')), '#')"/>
As for XSLT 1.0, there I think the sorting with for-each is the right approach but you would need to pull the xsl:variable outside the for-each e.g.
<xsl:variable name="min">
<xsl:for-each select="Rows/Entry/#value1|Rows/Entry/#value2">
<xsl:sort select="translate(., ',', '')" data-type="number"/>
<xsl:if test="position() = 1">
<xsl:value-of select="format-number(., '#')"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="max">
<xsl:for-each select="Rows/Entry/#value1|Rows/Entry/#value2">
<xsl:sort select="translate(., ',', '')" data-type="number"/>
<xsl:if test="position() = last()">
<xsl:value-of select="format-number(.,'#')" />
</xsl:if>
</xsl:for-each>
</xsl:variable>
As an alternative you could replace the for-each with apply-templates and then write a template matching #value1 | #value2 but while I think most tasks to transform nodes are better done using push style in XSLT I think for finding a minimum or maximum value the for-each is fine.
I'm not sure if it is absolutely correct but I tried this for min
(/Rows/Entry/#value1|/Rows/Entry/#value2)[not((/Rows/Entry/#value1|/Rows/Entry/#value2) < .)]
and this for max
(/Rows/Entry/#value1|/Rows/Entry/#value2)[not((/Rows/Entry/#value1|/Rows/Entry/#value2) > .)]
and it gave me values you mentioned. But for simplification I worked with xml with values without ",".

Capitalize Element Name in XSL

I am writing a XSL transformation and my source has an element like this - "title". The target xml should contain "Title". Is there a way to capitalize the first letter of a string in XSL?
Following on from the Johannes said, to create a new element using xsl:element you would probably do something like this
<xsl:template match="*">
<xsl:element name="{concat(upper-case(substring(name(), 1, 1)), substring(name(), 2))}">
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
If your are using XSLT1.0, you won't be able to use the upper-case function. Instead, you will have to make-do with the cumbersome translate function
<xsl:element name="{concat(translate(substring(name(), 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), substring(name(), 2))}">
Cleaner: use an existing library: FunctX XSLT http://www.xsltfunctions.com/ There's a function capitalize-first() http://www.xsltfunctions.com/xsl/functx_capitalize-first.html
No need to reinvent the wheel in every XSLT, stick the lib somewhere and xsl:include it.
I guess you have to manually use <xsl:element> and then something like the following beast:
concat(upper-case(substring(name(), 1, 1)), substring(name(), 2))
Here is a pure XLST1 template that creates CamelCase names from ASCII sentences.
<xsl:template name="Capitalize">
<xsl:param name="word" select="''"/>
<xsl:value-of select="concat(
translate(substring($word, 1, 1),
'abcdefghijklmnopqrstuvwxyz',
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
translate(substring($word, 2),
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'abcdefghijklmnopqrstuvwxyz'))"/>
</xsl:template>
<xsl:template name="CamelCase-recursion">
<xsl:param name="sentence" select="''"/>
<xsl:if test="$sentence != ''">
<xsl:call-template name="Capitalize">
<xsl:with-param name="word" select="substring-before(concat($sentence, ' '), ' ')"/>
</xsl:call-template>
<xsl:call-template name="CamelCase-recursion">
<xsl:with-param name="sentence" select="substring-after($sentence, ' ')"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="CamelCase">
<xsl:param name="sentence" select="''"/>
<xsl:call-template name="CamelCase-recursion">
<xsl:with-param name="sentence" select="normalize-space(translate($sentence, ":;,'()_", ' '))"/>
</xsl:call-template>
</xsl:template>