2
\$\begingroup\$

I have a situation where I am receiving data from a web service and the data is in all caps. I have to convert to HTML and format for display. In this case, we need the string to be normalized. The XML we receive has the possibility, and most of the time is, large, sometimes being over a MB in size. Performance is an issue.

I have the below templates that I use for normalizing the string. I'm limited to XSLT 1.0.

<xsl:template name="CamelCase">
    <xsl:param name="text"/>

    <xsl:variable name="checkNBSP" select="translate($text, '&nbsp;', ' ')"/>
    <xsl:variable name="check160" select="translate($checkNBSP, '&#160;', ' ')"/>

    <xsl:choose>
        <xsl:when test="contains($check160,' ')">
            <xsl:call-template name="CamelCaseWord">
                <xsl:with-param name="text" select="substring-before($check160,' ')"/>
            </xsl:call-template>
            <xsl:text> </xsl:text>
            <xsl:call-template name="CamelCase">
                <xsl:with-param name="text" select="substring-after($check160,' ')"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:call-template name="CamelCaseWord">
                <xsl:with-param name="text" select="$check160"/>
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template name="CamelCaseWord">
    <xsl:param name="text"/>
    <xsl:value-of select="translate(substring($text,1,1),'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')" />
    <xsl:value-of select="translate(substring($text,2,string-length($text)-1),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')" />
</xsl:template>

I initially found the below template on Stack Overflow and made some slight modifications to it to meet my purposes. Is this way the optimal way to format the string, or can this be cleaned up?

\$\endgroup\$
  • \$\begingroup\$ Do you mean CamelCaseLikeThis? Or Title Case Like This? \$\endgroup\$ – 200_success Nov 28 '14 at 23:00
  • \$\begingroup\$ However I get the data in. My be a sentence or single words. \$\endgroup\$ – Loren Shaw Nov 28 '14 at 23:01
  • \$\begingroup\$ I don't think that your use of the term CamelCase is standard. \$\endgroup\$ – 200_success Nov 28 '14 at 23:04
  • \$\begingroup\$ It's because text can run through multiple format templates before reaching mine, each written by other developers and in use in other areas. I sometimes get text that has already been formed through nude concatenation and other styling \$\endgroup\$ – Loren Shaw Nov 28 '14 at 23:06
  • \$\begingroup\$ The name I just retained from the original code I pulled from stack overflow \$\endgroup\$ – Loren Shaw Nov 28 '14 at 23:06
1
\$\begingroup\$

The solution looks near optimal to me. If performance is an issue I would suggest the two following minor modifications:

  1. The cleaning of the string regarding the special characters (&nbsp; and &#160;) is done at every calling level. You could introduce a third template called CamelCaseRecursive which would look like CamelCase but it would not contain the cleaning methods. So, CamelCase would be official external interface which would call CamelCaseRecursive which would call itself recursively. This change may save the more time the more words a text has on the average.

  2. In CamelCaseWord you could contract the two <xsl:value-of> tags into one by using the concat() function:

    <xsl:value-of 
        select="concat(translate(substring($text,1,1),
                                 'abcdefghijklmnopqrstuvwxyz',
                                 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 
                       ' ',
                       translate(substring($text,2,string-length($text)-1), 
                                 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 
                                 'abcdefghijklmnopqrstuvwxyz')
                       )" />
    

I would assume that the performance gains will be minimal with today's highly optimized XSLT processors. However, if this actually helps it would be great to learn about it!

\$\endgroup\$
  • \$\begingroup\$ These did help a bit. I did notice some improvement in processing time. The large XML that we receive along with the heavy use of these templates has our hands bound a bit and the XML processing, along with web service request/response times are causing a bottleneck. Eventually, we will be moving this kind of formatting out of XSLT and will begin minimizing XSLT use to just structuring HTML, but until we can get that done, this will be a big player in our display. \$\endgroup\$ – Loren Shaw Dec 1 '14 at 14:39
0
\$\begingroup\$

As noted in the comments, I was confused by the naming of the template and by the wording of the question. The template is actually taking Strings with CamelCase words like ThisOne and normalizing it into Strings With Titlecase Words Like Thisone. Therefore, I suggest renaming the template to normalize-to-titlecase (using hyphens in keeping with the XSLT naming convention for functions like substring-after()).

If your XSLT processor allows it, consider defining an external function instead.

Why do you need to handle &nbsp; manually? XML tools should either handle it for you automatically as a non-breaking space character (if the entity is defined as &#160;) or not at all (if you didn't define it).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.