Search code examples
javajspsplitjstl

JSP JSTL funciton fn:split is not working properly


Today, I come across one issue and need your help to fix it.

I am trying to split the string using JSTL fn:split function that is likewise,

<c:set var="stringArrayName" value="${fn:split(element, '~$')}" />

Actual String :- "abc~$pqr$xyz"

Expected Result :-

abc 
pqr$xyz

only 2-string part expecting, but it gives

abc
pqr
xyz

here, total 3-string parts returning, which is wrong.

NOTE :- I have added <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%> at the top of JSP.

any help really appreciates!!


Solution

  • JSTL split not work like the Java split you can check the difference from the code source :

    org.apache.taglibs.standard.functions.Functions.split

    public static String[] split(String input, String delimiters) {
        String[] array;
        if (input == null) {
            input = "";
        }
        if (input.length() == 0) {
            array = new String[1];
            array[0] = "";
            return array;
        }
    
        if (delimiters == null) {
            delimiters = "";
        }
    
        StringTokenizer tok = new StringTokenizer(input, delimiters);
        int count = tok.countTokens();
        array = new String[count];
        int i = 0;
        while (tok.hasMoreTokens()) {
            array[i++] = tok.nextToken();
        }
        return array;
    }
    

    java.lang.String.split

    public String[] split(String regex, int limit) {
        return Pattern.compile(regex).split(this, limit);
    }
    

    So it's clearly that fn:split use StringTokenizer

        ...
        StringTokenizer tok = new StringTokenizer(input, delimiters);
        int count = tok.countTokens();
        array = new String[count];
        int i = 0;
        while (tok.hasMoreTokens()) {
            array[i++] = tok.nextToken();
        }
        ...
    

    Not like java.lang.String.split which use regular expression

    return Pattern.compile(regex).split(this, limit);
    //-----------------------^
    

    from the StringTokenizer documentation it says :

    Constructs a string tokenizer for the specified string. The characters in the delim argument are the delimiters for separating tokens. Delimiter characters themselves will not be treated as tokens.

    How `fn:split` exactly work?

    It split on each character in the delimiter, in your case you have two characters ~ and $ so if your string is abc~$pqr$xyz it will split it like this :

    abc~$pqr$xyz
       ^^   ^
    

    1st split :

    abc
    $pqr$xyz
    

    2nd split :

    abc
    pqr$xyz
    

    3rd split :

    abc
    pqr
    xyz
    

    Solution

    use split in your Servlet instead of JSTL

    for example :

    String[] array = "abc~$pqr$xyz".split("~\\$");