tags:

views:

95

answers:

3

Take the following JSP fragment:

<c:forEach items="${items}" varStatus="status">
   ${'A' + status.index}
</c:forEach>

The intent should clear, I'm trying to generate an 'A'-based character index for each iterations through the loop. In Java, this is fine (e.g. 'A' + 1 == 'B'), but JSP EL on Tomcat 6 barfs with java.lang.NumberFormatException: For input string: "A". It seems it cannot handle characters as ordinal values.

The current solution breaks this out into a custom taglib, but this is absurd for something so trivial.

Can anyone see how to persuade EL to do this calculation?

+1  A: 

That's not possible with pure EL. It basically only understands strings, numbers and javabeans. If it didn't have thrown a NumberFormatException, you would still end up with A1, A2, A3, etc. Semantically seen, your best bet is likely using HTML <ol> element with a little shot of CSS to make it a fullworthy alphabetical-indexed list:

<ol style="list-style-type: upper-alpha;">
    <c:forEach items="${items}" var="item">
        <li>${item}</li>
    </c:forEach>
</ol>

This will generate

A. item1
B. item2
C. item3
...

If that's also not what you want, consider an EL function which returns the desired char for the given index. Or have a look at Pointy's clever solution which basically generates XML entities on the fly.

BalusC
Unfortunately, I need the result value as a JSP variable, so I can pass it to other tags. Thanks for the lateral thinking, though :)
skaffman
+3  A: 

Try this

<c:forEach items="${items}" varStatus="status">
  &#${65 + status.index};
</c:forEach>
Pointy
Clever! (15 chars)
BalusC
thanks man :-) (or woman :-)
Pointy
Very crafty! 2 characters of well-localised cleverness.
skaffman
+3  A: 

First create the alphabet:

<c:set var="alphabet" value="ABCDEFGHIJKLMNOPQRSTUVWXYZ"/>

Then you can use fn:substring to access letters.

${fn:substring(alphabet, status.index, status.index + 1)}

Your example would become:

<c:forEach items="${items}" varStatus="status">
    <c:set var="indexOfLetter" value="${fn:indexOf('A', alphabet) + status.index}"/>
    ${fn:substring(alphabet, indexOfLetter, indexOfLetter + status.index + 1}
</c:forEach>

You'll probably need some edge case checking, but this should work.

BacMan
I'm going to pick this one, since it's the most general-purpose of the 3 answers so far, allowing me to set a JSP variable with the result. The other two rely on HTML or CSS to render to render the ordinal into a character, which is appealing in many situations, but not what I need for my current problem.
skaffman
Glad I could help!
BacMan