Reputation: 10524
If have a following element in my XSL file:
<xsl:value-of select="replace(lower-case(@name), '_([a-z0-9])', '$1')" />
For example from 'get_polygene_lubricants' it makes 'getpolygenelubricants'.
What I want to do is to replace the first letter after '_' with the uppercase variant of the letter. I googled, read documentation, but I was not able to found any solution in XSLT for that simple replacement.
Maybe somebody knows whether it is possible in XSLT 2.0?
Upvotes: 2
Views: 12974
Reputation: 9235
Although already answered, here's my solution:
<xsl:template name="camel-case">
<xsl:param name='value'/>
<xsl:analyze-string regex="^(.)" select="$value">
<xsl:matching-substring><xsl:value-of select="upper-case(regex-group(1))"/></xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:analyze-string regex="[_-](.)" select=".">
<xsl:matching-substring><xsl:value-of select="upper-case(regex-group(1))"/></xsl:matching-substring>
<xsl:non-matching-substring><xsl:value-of select="."/></xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
Use:
<xsl:call-template name="camel-case">
<xsl:with-param name='value' select="."/>
</xsl:call-template>
Upvotes: 0
Reputation: 243479
Edited: Per clarification from the original poster, the first string delimited by the underscores should not have its starting letter capitalized.
This solution does not use recursion and should be quite more efficient.
Here is the new solution:
string-join(
(for $i in 1 to count(tokenize(.,'_')),
$s in tokenize(.,'_')[$i],
$fl in substring($s,1,1),
$tail in substring($s,2)
return
if($i eq 1)
then $s
else concat(upper-case($fl), $tail)
),
''
)
The result is now exactly as required:
underLinedString
Below is the old solution.
The replace() function supposes that you have a fixed replacement -- therefore it is not the best tool for solving this problem.
Here is a one-liner XPath 2.0 solution (and it certainly can be used as part of an XSLT 2.0 transformation :) ):
string-join(
(for $s in tokenize(.,'_'),
$fl in substring($s,1,1),
$tail in substring($s,2)
return
concat(upper-case($fl), $tail)
),
''
)
When we use the above expression in an XSLT 2.0 transformation like this:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="/">
<xsl:sequence select=
"string-join(
(for $s in tokenize(.,'_'),
$fl in substring($s,1,1),
$tail in substring($s,2)
return
concat(upper-case($fl), $tail)
),
''
)
"/>
</xsl:template>
</xsl:stylesheet>
and apply it on this XML document:
<t>under_lined_String</t>
the wanted result is produced:
UnderLinedString
Upvotes: 7
Reputation: 7595
You could do this using a template, recursively calling itself to iterate through the characters in the string. This template should take a position parameter, starting at 1 and increasing for each call to the template. When '_' is found, transform next char to upper case using translate(1.0) or upper-case(2.0)
Upvotes: 1