views:

12314

answers:

11

I have a list of bean objects passed into my JSP page, and one of them is a comment field. This field may contain newlines, and I want to replace them with semicolons using JSTL, so that the field can be displayed in a text input. I have found one solution, but it's not very elegant. I'll post below as a possibility.

+6  A: 

Here is a solution I found. It doesn't seem very elegant, though:

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<% pageContext.setAttribute("newLineChar", "\n"); %>

${fn:replace(item.comments, newLineChar, "; ")}
parkerfath
I'm accepting this, even though it's my own answer, because it's simplest and I've found it to actually work.
parkerfath
That's unnecessary. Just escape the backslash: http://stackoverflow.com/questions/58054/how-can-i-replace-newline-characters-using-jsp-and-jstl/1690942#1690942
BalusC
I tried just escaping the backslash, which didn't work either. My above-listed method of setting the pageContext attribute is still the only way I can get it working. Though as BalusC says, you may have better luck with some of the simpler methods. Probably good to have all the options here.
parkerfath
As always, be careful about the different between Windows and Unix newlines (use "\r\n" for the former).
pimlottc
+2  A: 

You should be able to do it with fn:replace.

You will need to import the tag library into your JSP with the following declaration:

<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

Then you can use the following expression to replace occurrences of newline in ${data} with a semicolon:

${fn:replace(data, "\n", ";")}

The documentation is not great on this stuff and I have not had the opportunity to test it.

bmatthews68
I'm pretty sure this is what I tried first, and it didn't work. I don't really have time to re-test it, though, so I may be wrong.
parkerfath
I think this answer is pretty much the same as mine (see below), but without the additional pageContext.setAttribute(). Do you know if there is maybe some setting that I haven't set that causes me to need to call this extra method?
parkerfath
I get this error:org.apache.jasper.JasperException: /WEB-INF/jsp/team/alarms.jsp(11,2) "${fn:replace(blob, "\n", ";")}" contains invalid expression(s): javax.servlet.jsp.el.ELException: Encountered ""\n", expected one of [<INTEGER_LITERAL>, <FLOATING_POINT_LITERAL>, etc.
parkerfath
A: 

You could write your own JSP function to do the replacement.

This means you'd end up with something like:

<%@ taglib prefix="ns" uri="..." %>
...
${ns:replace(data)}

Where ns is a namespace prefix you define and replace is your JSP function.

These functions are pretty easy to implement (they're just a static method) although I can't seem to find a good reference for writing these at the moment.

wrumsby
+2  A: 

You could create your own JSP function. http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JSPTags6.html

This is roughly what you need to do.

Create a tag library descriptor file
/src/META-INF/sf.tld

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd">
  <tlib-version>1.0</tlib-version>
  <short-name>sf</short-name>
  <uri>http://www.stackoverflow.com&lt;/uri&gt;
  <function>
    <name>clean</name>
    <function-class>com.stackoverflow.web.tag.function.TagUtils</function-class>
    <function-signature>
      java.lang.String clean(java.lang.String)
    </function-signature>
  </function>
</taglib>

Create a Java class for the functions logic.
com.stackoverflow.web.tag.function.TagUtils

package com.stackoverflow.web.tag.function;

import javax.servlet.jsp.tagext.TagSupport;

public class TagUtils extends TagSupport {
  public static String clean(String comment) {
    return comment.replaceAll("\n", "; ");
  }
}

In your JSP you can access your function in the following way.

<%@ taglib prefix="sf" uri="http://www.stackoverflow.com"%&gt;
${sf:clean(item.comments)}
Philz
should be ${sf:clean(item.comments)} ... I used this solution.. seems cleaner than the scriptlet
danb
thanks danb, I have updated my post
Philz
@danb: you missed my answer? http://stackoverflow.com/questions/58054/how-can-i-replace-newline-characters-using-jsp-and-jstl/1690942#1690942
BalusC
A: 

In the value while setting the var, press ENTER between the double quotes.

${fn:replace(data, newLineChar, ";")}

+4  A: 

This solution is more elegant than your own solution which is setting the pagecontext attribute directly. You should use the <c:set> tag for this:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

<c:set var="newline" value="\n"/>
${fn:replace(data, newLine, "; ")}

BTW: ${fn:replace(data, "\n", ";")} does NOT work.

This doesn't work for me in Resin 3, whereas the top answer using the pageContext scriptlet does.
pimlottc
I guess that would be a bug because according to the standards it should work.
+1  A: 

\n does not represent the newline character in an EL expression.

The solution which sets a pageContext attribute to the newline character and then uses it with JSTL's fn:replace function does work.

However, I prefer to use the Jakarta String Tab Library to solve this problem:

<%@ taglib prefix="str" uri="http://jakarta.apache.org/taglibs/string-1.1" %>
...
<str:replace var="result" replace="~n" with=";" newlineToken="~n">
Text containing newlines
</str:replace>
...

You can use whatever you want for the newlineToken; "~n" is unlikely to show up in the text I'm doing the replacement on, so it was a reasonable choice for me.

misterbiscuit
A: 

This does not work for me:

<c:set var="newline" value="\n"/>
${fn:replace(data, newLine, "; ")}

This does:

<% pageContext.setAttribute("newLineChar", "\n"); %> 
${fn:replace(item.comments, newLineChar, "; ")}
These are the answers above, right? Maybe it would be better to comment or upvote the answers already given, rather than repeating them.
parkerfath
+1  A: 

Although this is an old topic, but one has kicked this topic and no-one was able to post the right solution, so here it is:

${fn:replace(data, '\\n', ';')}

Yes, just escape the backslash.

BalusC
I'm pretty sure I tried that, too, though I may be wrong. I'll try that when I get some free time.
parkerfath
This didn't work for me... I'm sure I tried it.
danb
Then the problem lies somewhere else. It works here :)
BalusC
@danb....make sure it's not `\n` but `\\n`.
The Elite Gentleman
A: 

For the record, I came across this post while tackling this problem:

A multi-line string in JSTL gets added as the title attribute of a textarea. Javascript then adds this as the default text of the textarea. In order to clear this text on focus the value needs to equal the title... but fails as many text-editors put \r\n instead of \n. So the follownig will get rid of the unwanted \r:

<% pageContext.setAttribute("newLineChar", "\r"); %> 
<c:set var="textAreaDefault" value="${fn:replace(textAreaDefault, newLineChar, '')}" />
wheresrhys
A: 

More easily:

<str:replace var="your_Var_replaced" replace="\n" with="Your ney caracter" newlineToken="\n">${your_Var_to_replaced}</str:replace>  
brunohop