Coverage Report - org.apache.commons.lang3.StringEscapeUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
StringEscapeUtils
94%
32/34
N/A
1,474
StringEscapeUtils$CsvEscaper
90%
10/11
75%
3/4
1,474
StringEscapeUtils$CsvUnescaper
92%
12/13
75%
6/8
1,474
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  * 
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  * 
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.commons.lang3;
 18  
 
 19  
 import java.io.IOException;
 20  
 import java.io.Writer;
 21  
 
 22  
 import org.apache.commons.lang3.text.translate.AggregateTranslator;
 23  
 import org.apache.commons.lang3.text.translate.CharSequenceTranslator;
 24  
 import org.apache.commons.lang3.text.translate.EntityArrays;
 25  
 import org.apache.commons.lang3.text.translate.JavaUnicodeEscaper;
 26  
 import org.apache.commons.lang3.text.translate.LookupTranslator;
 27  
 import org.apache.commons.lang3.text.translate.NumericEntityEscaper;
 28  
 import org.apache.commons.lang3.text.translate.NumericEntityUnescaper;
 29  
 import org.apache.commons.lang3.text.translate.OctalUnescaper;
 30  
 import org.apache.commons.lang3.text.translate.UnicodeUnescaper;
 31  
 import org.apache.commons.lang3.text.translate.UnicodeUnpairedSurrogateRemover;
 32  
 
 33  
 /**
 34  
  * <p>Escapes and unescapes {@code String}s for
 35  
  * Java, Java Script, HTML and XML.</p>
 36  
  *
 37  
  * <p>#ThreadSafe#</p>
 38  
  * @since 2.0
 39  
  */
 40  
 public class StringEscapeUtils {
 41  
 
 42  
     /* ESCAPE TRANSLATORS */
 43  
 
 44  
     /**
 45  
      * Translator object for escaping Java. 
 46  
      * 
 47  
      * While {@link #escapeJava(String)} is the expected method of use, this 
 48  
      * object allows the Java escaping functionality to be used 
 49  
      * as the foundation for a custom translator. 
 50  
      *
 51  
      * @since 3.0
 52  
      */
 53  1
     public static final CharSequenceTranslator ESCAPE_JAVA = 
 54  
           new LookupTranslator(
 55  
             new String[][] { 
 56  
               {"\"", "\\\""},
 57  
               {"\\", "\\\\"},
 58  
           }).with(
 59  
             new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_ESCAPE())
 60  
           ).with(
 61  
             JavaUnicodeEscaper.outsideOf(32, 0x7f) 
 62  
         );
 63  
 
 64  
     /**
 65  
      * Translator object for escaping EcmaScript/JavaScript. 
 66  
      * 
 67  
      * While {@link #escapeEcmaScript(String)} is the expected method of use, this 
 68  
      * object allows the EcmaScript escaping functionality to be used 
 69  
      * as the foundation for a custom translator. 
 70  
      *
 71  
      * @since 3.0
 72  
      */
 73  1
     public static final CharSequenceTranslator ESCAPE_ECMASCRIPT = 
 74  
         new AggregateTranslator(
 75  
             new LookupTranslator(
 76  
                       new String[][] { 
 77  
                             {"'", "\\'"},
 78  
                             {"\"", "\\\""},
 79  
                             {"\\", "\\\\"},
 80  
                             {"/", "\\/"}
 81  
                       }),
 82  
             new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_ESCAPE()),
 83  
             JavaUnicodeEscaper.outsideOf(32, 0x7f) 
 84  
         );
 85  
 
 86  
     /**
 87  
      * Translator object for escaping Json.
 88  
      *
 89  
      * While {@link #escapeJson(String)} is the expected method of use, this
 90  
      * object allows the Json escaping functionality to be used
 91  
      * as the foundation for a custom translator.
 92  
      *
 93  
      * @since 3.2
 94  
      */
 95  1
     public static final CharSequenceTranslator ESCAPE_JSON =
 96  
         new AggregateTranslator(
 97  
             new LookupTranslator(
 98  
                       new String[][] {
 99  
                             {"\"", "\\\""},
 100  
                             {"\\", "\\\\"},
 101  
                             {"/", "\\/"}
 102  
                       }),
 103  
             new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_ESCAPE()),
 104  
             JavaUnicodeEscaper.outsideOf(32, 0x7f)
 105  
         );
 106  
 
 107  
     /**
 108  
      * Translator object for escaping XML.
 109  
      * 
 110  
      * While {@link #escapeXml(String)} is the expected method of use, this 
 111  
      * object allows the XML escaping functionality to be used 
 112  
      * as the foundation for a custom translator. 
 113  
      *
 114  
      * @since 3.0
 115  
      * @deprecated use {@link #ESCAPE_XML10} or {@link #ESCAPE_XML11} instead.
 116  
      */
 117  
     @Deprecated
 118  1
     public static final CharSequenceTranslator ESCAPE_XML = 
 119  
         new AggregateTranslator(
 120  
             new LookupTranslator(EntityArrays.BASIC_ESCAPE()),
 121  
             new LookupTranslator(EntityArrays.APOS_ESCAPE())
 122  
         );
 123  
     
 124  
     /**
 125  
      * Translator object for escaping XML 1.0.
 126  
      * 
 127  
      * While {@link #escapeXml10(String)} is the expected method of use, this
 128  
      * object allows the XML escaping functionality to be used
 129  
      * as the foundation for a custom translator.
 130  
      *
 131  
      * @since 3.3
 132  
      */
 133  1
     public static final CharSequenceTranslator ESCAPE_XML10 =
 134  
         new AggregateTranslator(
 135  
             new LookupTranslator(EntityArrays.BASIC_ESCAPE()),
 136  
             new LookupTranslator(EntityArrays.APOS_ESCAPE()),
 137  
             new LookupTranslator(
 138  
                     new String[][] {
 139  
                             { "\u0000", "" },
 140  
                             { "\u0001", "" },
 141  
                             { "\u0002", "" },
 142  
                             { "\u0003", "" },
 143  
                             { "\u0004", "" },
 144  
                             { "\u0005", "" },
 145  
                             { "\u0006", "" },
 146  
                             { "\u0007", "" },
 147  
                             { "\u0008", "" },
 148  
                             { "\u000b", "" },
 149  
                             { "\u000c", "" },
 150  
                             { "\u000e", "" },
 151  
                             { "\u000f", "" },
 152  
                             { "\u0010", "" },
 153  
                             { "\u0011", "" },
 154  
                             { "\u0012", "" },
 155  
                             { "\u0013", "" },
 156  
                             { "\u0014", "" },
 157  
                             { "\u0015", "" },
 158  
                             { "\u0016", "" },
 159  
                             { "\u0017", "" },
 160  
                             { "\u0018", "" },
 161  
                             { "\u0019", "" },
 162  
                             { "\u001a", "" },
 163  
                             { "\u001b", "" },
 164  
                             { "\u001c", "" },
 165  
                             { "\u001d", "" },
 166  
                             { "\u001e", "" },
 167  
                             { "\u001f", "" },
 168  
                             { "\ufffe", "" },
 169  
                             { "\uffff", "" }
 170  
                     }),
 171  
             NumericEntityEscaper.between(0x7f, 0x84),
 172  
             NumericEntityEscaper.between(0x86, 0x9f),
 173  
             new UnicodeUnpairedSurrogateRemover()
 174  
         );
 175  
     
 176  
     /**
 177  
      * Translator object for escaping XML 1.1.
 178  
      * 
 179  
      * While {@link #escapeXml11(String)} is the expected method of use, this
 180  
      * object allows the XML escaping functionality to be used
 181  
      * as the foundation for a custom translator.
 182  
      *
 183  
      * @since 3.3
 184  
      */
 185  1
     public static final CharSequenceTranslator ESCAPE_XML11 =
 186  
         new AggregateTranslator(
 187  
             new LookupTranslator(EntityArrays.BASIC_ESCAPE()),
 188  
             new LookupTranslator(EntityArrays.APOS_ESCAPE()),
 189  
             new LookupTranslator(
 190  
                     new String[][] {
 191  
                             { "\u0000", "" },
 192  
                             { "\u000b", "&#11;" },
 193  
                             { "\u000c", "&#12;" },
 194  
                             { "\ufffe", "" },
 195  
                             { "\uffff", "" }
 196  
                     }),
 197  
             NumericEntityEscaper.between(0x1, 0x8),
 198  
             NumericEntityEscaper.between(0xe, 0x1f),
 199  
             NumericEntityEscaper.between(0x7f, 0x84),
 200  
             NumericEntityEscaper.between(0x86, 0x9f),
 201  
             new UnicodeUnpairedSurrogateRemover()
 202  
         );
 203  
 
 204  
     /**
 205  
      * Translator object for escaping HTML version 3.0.
 206  
      * 
 207  
      * While {@link #escapeHtml3(String)} is the expected method of use, this 
 208  
      * object allows the HTML escaping functionality to be used 
 209  
      * as the foundation for a custom translator. 
 210  
      *
 211  
      * @since 3.0
 212  
      */
 213  1
     public static final CharSequenceTranslator ESCAPE_HTML3 = 
 214  
         new AggregateTranslator(
 215  
             new LookupTranslator(EntityArrays.BASIC_ESCAPE()),
 216  
             new LookupTranslator(EntityArrays.ISO8859_1_ESCAPE())
 217  
         );
 218  
 
 219  
     /**
 220  
      * Translator object for escaping HTML version 4.0.
 221  
      * 
 222  
      * While {@link #escapeHtml4(String)} is the expected method of use, this 
 223  
      * object allows the HTML escaping functionality to be used 
 224  
      * as the foundation for a custom translator. 
 225  
      *
 226  
      * @since 3.0
 227  
      */
 228  1
     public static final CharSequenceTranslator ESCAPE_HTML4 = 
 229  
         new AggregateTranslator(
 230  
             new LookupTranslator(EntityArrays.BASIC_ESCAPE()),
 231  
             new LookupTranslator(EntityArrays.ISO8859_1_ESCAPE()),
 232  
             new LookupTranslator(EntityArrays.HTML40_EXTENDED_ESCAPE())
 233  
         );
 234  
 
 235  
     /**
 236  
      * Translator object for escaping individual Comma Separated Values. 
 237  
      * 
 238  
      * While {@link #escapeCsv(String)} is the expected method of use, this 
 239  
      * object allows the CSV escaping functionality to be used 
 240  
      * as the foundation for a custom translator. 
 241  
      *
 242  
      * @since 3.0
 243  
      */
 244  1
     public static final CharSequenceTranslator ESCAPE_CSV = new CsvEscaper();
 245  
 
 246  
     // TODO: Create a parent class - 'SinglePassTranslator' ?
 247  
     //       It would handle the index checking + length returning, 
 248  
     //       and could also have an optimization check method.
 249  1
     static class CsvEscaper extends CharSequenceTranslator {
 250  
 
 251  
         private static final char CSV_DELIMITER = ',';
 252  
         private static final char CSV_QUOTE = '"';
 253  1
         private static final String CSV_QUOTE_STR = String.valueOf(CSV_QUOTE);
 254  1
         private static final char[] CSV_SEARCH_CHARS = 
 255  
             new char[] {CSV_DELIMITER, CSV_QUOTE, CharUtils.CR, CharUtils.LF};
 256  
 
 257  
         @Override
 258  
         public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
 259  
 
 260  16
             if(index != 0) {
 261  0
                 throw new IllegalStateException("CsvEscaper should never reach the [1] index");
 262  
             }
 263  
 
 264  16
             if (StringUtils.containsNone(input.toString(), CSV_SEARCH_CHARS)) {
 265  8
                 out.write(input.toString());
 266  
             } else {
 267  8
                 out.write(CSV_QUOTE);
 268  8
                 out.write(StringUtils.replace(input.toString(), CSV_QUOTE_STR, CSV_QUOTE_STR + CSV_QUOTE_STR));
 269  8
                 out.write(CSV_QUOTE);
 270  
             }
 271  16
             return Character.codePointCount(input, 0, input.length());
 272  
         }
 273  
     }
 274  
 
 275  
     /* UNESCAPE TRANSLATORS */
 276  
 
 277  
     /**
 278  
      * Translator object for unescaping escaped Java. 
 279  
      * 
 280  
      * While {@link #unescapeJava(String)} is the expected method of use, this 
 281  
      * object allows the Java unescaping functionality to be used 
 282  
      * as the foundation for a custom translator. 
 283  
      *
 284  
      * @since 3.0
 285  
      */
 286  
     // TODO: throw "illegal character: \92" as an Exception if a \ on the end of the Java (as per the compiler)?
 287  1
     public static final CharSequenceTranslator UNESCAPE_JAVA = 
 288  
         new AggregateTranslator(
 289  
             new OctalUnescaper(),     // .between('\1', '\377'),
 290  
             new UnicodeUnescaper(),
 291  
             new LookupTranslator(EntityArrays.JAVA_CTRL_CHARS_UNESCAPE()),
 292  
             new LookupTranslator(
 293  
                       new String[][] { 
 294  
                             {"\\\\", "\\"},
 295  
                             {"\\\"", "\""},
 296  
                             {"\\'", "'"},
 297  
                             {"\\", ""}
 298  
                       })
 299  
         );
 300  
 
 301  
     /**
 302  
      * Translator object for unescaping escaped EcmaScript. 
 303  
      * 
 304  
      * While {@link #unescapeEcmaScript(String)} is the expected method of use, this 
 305  
      * object allows the EcmaScript unescaping functionality to be used 
 306  
      * as the foundation for a custom translator. 
 307  
      *
 308  
      * @since 3.0
 309  
      */
 310  1
     public static final CharSequenceTranslator UNESCAPE_ECMASCRIPT = UNESCAPE_JAVA;
 311  
 
 312  
     /**
 313  
      * Translator object for unescaping escaped Json.
 314  
      *
 315  
      * While {@link #unescapeJson(String)} is the expected method of use, this
 316  
      * object allows the Json unescaping functionality to be used
 317  
      * as the foundation for a custom translator.
 318  
      *
 319  
      * @since 3.2
 320  
      */
 321  1
     public static final CharSequenceTranslator UNESCAPE_JSON = UNESCAPE_JAVA;
 322  
 
 323  
     /**
 324  
      * Translator object for unescaping escaped HTML 3.0. 
 325  
      * 
 326  
      * While {@link #unescapeHtml3(String)} is the expected method of use, this 
 327  
      * object allows the HTML unescaping functionality to be used 
 328  
      * as the foundation for a custom translator. 
 329  
      *
 330  
      * @since 3.0
 331  
      */
 332  1
     public static final CharSequenceTranslator UNESCAPE_HTML3 = 
 333  
         new AggregateTranslator(
 334  
             new LookupTranslator(EntityArrays.BASIC_UNESCAPE()),
 335  
             new LookupTranslator(EntityArrays.ISO8859_1_UNESCAPE()),
 336  
             new NumericEntityUnescaper()
 337  
         );
 338  
 
 339  
     /**
 340  
      * Translator object for unescaping escaped HTML 4.0. 
 341  
      * 
 342  
      * While {@link #unescapeHtml4(String)} is the expected method of use, this 
 343  
      * object allows the HTML unescaping functionality to be used 
 344  
      * as the foundation for a custom translator. 
 345  
      *
 346  
      * @since 3.0
 347  
      */
 348  1
     public static final CharSequenceTranslator UNESCAPE_HTML4 = 
 349  
         new AggregateTranslator(
 350  
             new LookupTranslator(EntityArrays.BASIC_UNESCAPE()),
 351  
             new LookupTranslator(EntityArrays.ISO8859_1_UNESCAPE()),
 352  
             new LookupTranslator(EntityArrays.HTML40_EXTENDED_UNESCAPE()),
 353  
             new NumericEntityUnescaper()
 354  
         );
 355  
 
 356  
     /**
 357  
      * Translator object for unescaping escaped XML.
 358  
      * 
 359  
      * While {@link #unescapeXml(String)} is the expected method of use, this 
 360  
      * object allows the XML unescaping functionality to be used 
 361  
      * as the foundation for a custom translator. 
 362  
      *
 363  
      * @since 3.0
 364  
      */
 365  1
     public static final CharSequenceTranslator UNESCAPE_XML = 
 366  
         new AggregateTranslator(
 367  
             new LookupTranslator(EntityArrays.BASIC_UNESCAPE()),
 368  
             new LookupTranslator(EntityArrays.APOS_UNESCAPE()),
 369  
             new NumericEntityUnescaper()
 370  
         );
 371  
 
 372  
     /**
 373  
      * Translator object for unescaping escaped Comma Separated Value entries.
 374  
      * 
 375  
      * While {@link #unescapeCsv(String)} is the expected method of use, this 
 376  
      * object allows the CSV unescaping functionality to be used 
 377  
      * as the foundation for a custom translator. 
 378  
      *
 379  
      * @since 3.0
 380  
      */
 381  1
     public static final CharSequenceTranslator UNESCAPE_CSV = new CsvUnescaper();
 382  
 
 383  1
     static class CsvUnescaper extends CharSequenceTranslator {
 384  
 
 385  
         private static final char CSV_DELIMITER = ',';
 386  
         private static final char CSV_QUOTE = '"';
 387  1
         private static final String CSV_QUOTE_STR = String.valueOf(CSV_QUOTE);
 388  1
         private static final char[] CSV_SEARCH_CHARS = 
 389  
             new char[] {CSV_DELIMITER, CSV_QUOTE, CharUtils.CR, CharUtils.LF};
 390  
 
 391  
         @Override
 392  
         public int translate(final CharSequence input, final int index, final Writer out) throws IOException {
 393  
 
 394  18
             if(index != 0) {
 395  0
                 throw new IllegalStateException("CsvUnescaper should never reach the [1] index");
 396  
             }
 397  
 
 398  18
             if ( input.charAt(0) != CSV_QUOTE || input.charAt(input.length() - 1) != CSV_QUOTE ) {
 399  8
                 out.write(input.toString());
 400  8
                 return Character.codePointCount(input, 0, input.length());
 401  
             }
 402  
 
 403  
             // strip quotes
 404  10
             final String quoteless = input.subSequence(1, input.length() - 1).toString();
 405  
 
 406  10
             if ( StringUtils.containsAny(quoteless, CSV_SEARCH_CHARS) ) {
 407  
                 // deal with escaped quotes; ie) ""
 408  8
                 out.write(StringUtils.replace(quoteless, CSV_QUOTE_STR + CSV_QUOTE_STR, CSV_QUOTE_STR));
 409  
             } else {
 410  2
                 out.write(input.toString());
 411  
             }
 412  10
             return Character.codePointCount(input, 0, input.length());
 413  
         }
 414  
     }
 415  
 
 416  
     /* Helper functions */
 417  
 
 418  
     /**
 419  
      * <p>{@code StringEscapeUtils} instances should NOT be constructed in
 420  
      * standard programming.</p>
 421  
      *
 422  
      * <p>Instead, the class should be used as:</p>
 423  
      * <pre>StringEscapeUtils.escapeJava("foo");</pre>
 424  
      *
 425  
      * <p>This constructor is public to permit tools that require a JavaBean
 426  
      * instance to operate.</p>
 427  
      */
 428  
     public StringEscapeUtils() {
 429  1
       super();
 430  1
     }
 431  
 
 432  
     // Java and JavaScript
 433  
     //--------------------------------------------------------------------------
 434  
     /**
 435  
      * <p>Escapes the characters in a {@code String} using Java String rules.</p>
 436  
      *
 437  
      * <p>Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.) </p>
 438  
      *
 439  
      * <p>So a tab becomes the characters {@code '\\'} and
 440  
      * {@code 't'}.</p>
 441  
      *
 442  
      * <p>The only difference between Java strings and JavaScript strings
 443  
      * is that in JavaScript, a single quote and forward-slash (/) are escaped.</p>
 444  
      *
 445  
      * <p>Example:</p>
 446  
      * <pre>
 447  
      * input string: He didn't say, "Stop!"
 448  
      * output string: He didn't say, \"Stop!\"
 449  
      * </pre>
 450  
      *
 451  
      * @param input  String to escape values in, may be null
 452  
      * @return String with escaped values, {@code null} if null string input
 453  
      */
 454  
     public static final String escapeJava(final String input) {
 455  36
         return ESCAPE_JAVA.translate(input);
 456  
     }
 457  
 
 458  
     /**
 459  
      * <p>Escapes the characters in a {@code String} using EcmaScript String rules.</p>
 460  
      * <p>Escapes any values it finds into their EcmaScript String form.
 461  
      * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.) </p>
 462  
      *
 463  
      * <p>So a tab becomes the characters {@code '\\'} and
 464  
      * {@code 't'}.</p>
 465  
      *
 466  
      * <p>The only difference between Java strings and EcmaScript strings
 467  
      * is that in EcmaScript, a single quote and forward-slash (/) are escaped.</p>
 468  
      *
 469  
      * <p>Note that EcmaScript is best known by the JavaScript and ActionScript dialects. </p>
 470  
      *
 471  
      * <p>Example:</p>
 472  
      * <pre>
 473  
      * input string: He didn't say, "Stop!"
 474  
      * output string: He didn\'t say, \"Stop!\"
 475  
      * </pre>
 476  
      *
 477  
      * @param input  String to escape values in, may be null
 478  
      * @return String with escaped values, {@code null} if null string input
 479  
      *
 480  
      * @since 3.0
 481  
      */
 482  
     public static final String escapeEcmaScript(final String input) {
 483  5
         return ESCAPE_ECMASCRIPT.translate(input);
 484  
     }
 485  
 
 486  
     /**
 487  
      * <p>Escapes the characters in a {@code String} using Json String rules.</p>
 488  
      * <p>Escapes any values it finds into their Json String form.
 489  
      * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.) </p>
 490  
      *
 491  
      * <p>So a tab becomes the characters {@code '\\'} and
 492  
      * {@code 't'}.</p>
 493  
      *
 494  
      * <p>The only difference between Java strings and Json strings
 495  
      * is that in Json, forward-slash (/) is escaped.</p>
 496  
      *
 497  
      * <p>See http://www.ietf.org/rfc/rfc4627.txt for further details. </p>
 498  
      *
 499  
      * <p>Example:</p>
 500  
      * <pre>
 501  
      * input string: He didn't say, "Stop!"
 502  
      * output string: He didn't say, \"Stop!\"
 503  
      * </pre>
 504  
      *
 505  
      * @param input  String to escape values in, may be null
 506  
      * @return String with escaped values, {@code null} if null string input
 507  
      *
 508  
      * @since 3.2
 509  
      */
 510  
     public static final String escapeJson(final String input) {
 511  3
         return ESCAPE_JSON.translate(input);
 512  
     }
 513  
 
 514  
     /**
 515  
      * <p>Unescapes any Java literals found in the {@code String}.
 516  
      * For example, it will turn a sequence of {@code '\'} and
 517  
      * {@code 'n'} into a newline character, unless the {@code '\'}
 518  
      * is preceded by another {@code '\'}.</p>
 519  
      * 
 520  
      * @param input  the {@code String} to unescape, may be null
 521  
      * @return a new unescaped {@code String}, {@code null} if null string input
 522  
      */
 523  
     public static final String unescapeJava(final String input) {
 524  12
         return UNESCAPE_JAVA.translate(input);
 525  
     }
 526  
 
 527  
     /**
 528  
      * <p>Unescapes any EcmaScript literals found in the {@code String}.</p>
 529  
      *
 530  
      * <p>For example, it will turn a sequence of {@code '\'} and {@code 'n'}
 531  
      * into a newline character, unless the {@code '\'} is preceded by another
 532  
      * {@code '\'}.</p>
 533  
      *
 534  
      * @see #unescapeJava(String)
 535  
      * @param input  the {@code String} to unescape, may be null
 536  
      * @return A new unescaped {@code String}, {@code null} if null string input
 537  
      *
 538  
      * @since 3.0
 539  
      */
 540  
     public static final String unescapeEcmaScript(final String input) {
 541  0
         return UNESCAPE_ECMASCRIPT.translate(input);
 542  
     }
 543  
 
 544  
     /**
 545  
      * <p>Unescapes any Json literals found in the {@code String}.</p>
 546  
      *
 547  
      * <p>For example, it will turn a sequence of {@code '\'} and {@code 'n'}
 548  
      * into a newline character, unless the {@code '\'} is preceded by another
 549  
      * {@code '\'}.</p>
 550  
      *
 551  
      * @see #unescapeJava(String)
 552  
      * @param input  the {@code String} to unescape, may be null
 553  
      * @return A new unescaped {@code String}, {@code null} if null string input
 554  
      *
 555  
      * @since 3.2
 556  
      */
 557  
     public static final String unescapeJson(final String input) {
 558  0
         return UNESCAPE_JSON.translate(input);
 559  
     }
 560  
 
 561  
     // HTML and XML
 562  
     //--------------------------------------------------------------------------
 563  
     /**
 564  
      * <p>Escapes the characters in a {@code String} using HTML entities.</p>
 565  
      *
 566  
      * <p>
 567  
      * For example:
 568  
      * </p> 
 569  
      * <p><code>"bread" &amp; "butter"</code></p>
 570  
      * becomes:
 571  
      * <p>
 572  
      * <code>&amp;quot;bread&amp;quot; &amp;amp; &amp;quot;butter&amp;quot;</code>.
 573  
      * </p>
 574  
      *
 575  
      * <p>Supports all known HTML 4.0 entities, including funky accents.
 576  
      * Note that the commonly used apostrophe escape character (&amp;apos;)
 577  
      * is not a legal entity and so is not supported). </p>
 578  
      *
 579  
      * @param input  the {@code String} to escape, may be null
 580  
      * @return a new escaped {@code String}, {@code null} if null string input
 581  
      * 
 582  
      * @see <a href="http://hotwired.lycos.com/webmonkey/reference/special_characters/">ISO Entities</a>
 583  
      * @see <a href="http://www.w3.org/TR/REC-html32#latin1">HTML 3.2 Character Entities for ISO Latin-1</a>
 584  
      * @see <a href="http://www.w3.org/TR/REC-html40/sgml/entities.html">HTML 4.0 Character entity references</a>
 585  
      * @see <a href="http://www.w3.org/TR/html401/charset.html#h-5.3">HTML 4.01 Character References</a>
 586  
      * @see <a href="http://www.w3.org/TR/html401/charset.html#code-position">HTML 4.01 Code positions</a>
 587  
      * 
 588  
      * @since 3.0
 589  
      */
 590  
     public static final String escapeHtml4(final String input) {
 591  211
         return ESCAPE_HTML4.translate(input);
 592  
     }
 593  
 
 594  
     /**
 595  
      * <p>Escapes the characters in a {@code String} using HTML entities.</p>
 596  
      * <p>Supports only the HTML 3.0 entities. </p>
 597  
      *
 598  
      * @param input  the {@code String} to escape, may be null
 599  
      * @return a new escaped {@code String}, {@code null} if null string input
 600  
      * 
 601  
      * @since 3.0
 602  
      */
 603  
     public static final String escapeHtml3(final String input) {
 604  1
         return ESCAPE_HTML3.translate(input);
 605  
     }
 606  
 
 607  
     //-----------------------------------------------------------------------
 608  
     /**
 609  
      * <p>Unescapes a string containing entity escapes to a string
 610  
      * containing the actual Unicode characters corresponding to the
 611  
      * escapes. Supports HTML 4.0 entities.</p>
 612  
      *
 613  
      * <p>For example, the string {@code "&lt;Fran&ccedil;ais&gt;"}
 614  
      * will become {@code "<Fran├žais>"}</p>
 615  
      *
 616  
      * <p>If an entity is unrecognized, it is left alone, and inserted
 617  
      * verbatim into the result string. e.g. {@code "&gt;&zzzz;x"} will
 618  
      * become {@code ">&zzzz;x"}.</p>
 619  
      *
 620  
      * @param input  the {@code String} to unescape, may be null
 621  
      * @return a new unescaped {@code String}, {@code null} if null string input
 622  
      * 
 623  
      * @since 3.0
 624  
      */
 625  
     public static final String unescapeHtml4(final String input) {
 626  65561
         return UNESCAPE_HTML4.translate(input);
 627  
     }
 628  
 
 629  
     /**
 630  
      * <p>Unescapes a string containing entity escapes to a string
 631  
      * containing the actual Unicode characters corresponding to the
 632  
      * escapes. Supports only HTML 3.0 entities.</p>
 633  
      *
 634  
      * @param input  the {@code String} to unescape, may be null
 635  
      * @return a new unescaped {@code String}, {@code null} if null string input
 636  
      * 
 637  
      * @since 3.0
 638  
      */
 639  
     public static final String unescapeHtml3(final String input) {
 640  1
         return UNESCAPE_HTML3.translate(input);
 641  
     }
 642  
 
 643  
     //-----------------------------------------------------------------------
 644  
     /**
 645  
      * <p>Escapes the characters in a {@code String} using XML entities.</p>
 646  
      *
 647  
      * <p>For example: {@code "bread" & "butter"} =&gt;
 648  
      * {@code &quot;bread&quot; &amp; &quot;butter&quot;}.
 649  
      * </p>
 650  
      *
 651  
      * <p>Supports only the five basic XML entities (gt, lt, quot, amp, apos).
 652  
      * Does not support DTDs or external entities.</p>
 653  
      *
 654  
      * <p>Note that Unicode characters greater than 0x7f are as of 3.0, no longer 
 655  
      *    escaped. If you still wish this functionality, you can achieve it 
 656  
      *    via the following: 
 657  
      * {@code StringEscapeUtils.ESCAPE_XML.with( NumericEntityEscaper.between(0x7f, Integer.MAX_VALUE) );}</p>
 658  
      *
 659  
      * @param input  the {@code String} to escape, may be null
 660  
      * @return a new escaped {@code String}, {@code null} if null string input
 661  
      * @see #unescapeXml(java.lang.String)
 662  
      * @deprecated use {@link #escapeXml10(java.lang.String)} or {@link #escapeXml11(java.lang.String)} instead.
 663  
      */
 664  
     @Deprecated
 665  
     public static final String escapeXml(final String input) {
 666  7
         return ESCAPE_XML.translate(input);
 667  
     }
 668  
 
 669  
     /**
 670  
      * <p>Escapes the characters in a {@code String} using XML entities.</p>
 671  
      *
 672  
      * <p>For example: {@code "bread" & "butter"} =&gt;
 673  
      * {@code &quot;bread&quot; &amp; &quot;butter&quot;}.
 674  
      * </p>
 675  
      *
 676  
      * <p>Note that XML 1.0 is a text-only format: it cannot represent control
 677  
      * characters or unpaired Unicode surrogate codepoints, even after escaping.
 678  
      * {@code escapeXml10} will remove characters that do not fit in the
 679  
      * following ranges:</p>
 680  
      * 
 681  
      * <p>{@code #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]}</p>
 682  
      * 
 683  
      * <p>Though not strictly necessary, {@code escapeXml10} will escape
 684  
      * characters in the following ranges:</p>
 685  
      * 
 686  
      * <p>{@code [#x7F-#x84] | [#x86-#x9F]}</p>
 687  
      * 
 688  
      * <p>The returned string can be inserted into a valid XML 1.0 or XML 1.1
 689  
      * document. If you want to allow more non-text characters in an XML 1.1
 690  
      * document, use {@link #escapeXml11(String)}.</p>
 691  
      *
 692  
      * @param input  the {@code String} to escape, may be null
 693  
      * @return a new escaped {@code String}, {@code null} if null string input
 694  
      * @see #unescapeXml(java.lang.String)
 695  
      * @since 3.3
 696  
      */
 697  
     public static String escapeXml10(final String input) {
 698  6
         return ESCAPE_XML10.translate(input);
 699  
     }
 700  
     
 701  
     /**
 702  
      * <p>Escapes the characters in a {@code String} using XML entities.</p>
 703  
      *
 704  
      * <p>For example: {@code "bread" & "butter"} =&gt;
 705  
      * {@code &quot;bread&quot; &amp; &quot;butter&quot;}.
 706  
      * </p>
 707  
      *
 708  
      * <p>XML 1.1 can represent certain control characters, but it cannot represent
 709  
      * the null byte or unpaired Unicode surrogate codepoints, even after escaping.
 710  
      * {@code escapeXml11} will remove characters that do not fit in the following
 711  
      * ranges:</p>
 712  
      * 
 713  
      * <p>{@code [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]}</p>
 714  
      * 
 715  
      * <p>{@code escapeXml11} will escape characters in the following ranges:</p>
 716  
      * 
 717  
      * <p>{@code [#x1-#x8] | [#xB-#xC] | [#xE-#x1F] | [#x7F-#x84] | [#x86-#x9F]}</p>
 718  
      * 
 719  
      * <p>The returned string can be inserted into a valid XML 1.1 document. Do not
 720  
      * use it for XML 1.0 documents.</p>
 721  
      *
 722  
      * @param input  the {@code String} to escape, may be null
 723  
      * @return a new escaped {@code String}, {@code null} if null string input
 724  
      * @see #unescapeXml(java.lang.String)
 725  
      * @since 3.3
 726  
      */
 727  
     public static String escapeXml11(final String input) {
 728  7
         return ESCAPE_XML11.translate(input);
 729  
     }
 730  
 
 731  
     //-----------------------------------------------------------------------
 732  
     /**
 733  
      * <p>Unescapes a string containing XML entity escapes to a string
 734  
      * containing the actual Unicode characters corresponding to the
 735  
      * escapes.</p>
 736  
      *
 737  
      * <p>Supports only the five basic XML entities (gt, lt, quot, amp, apos).
 738  
      * Does not support DTDs or external entities.</p>
 739  
      *
 740  
      * <p>Note that numerical \\u Unicode codes are unescaped to their respective 
 741  
      *    Unicode characters. This may change in future releases. </p>
 742  
      *
 743  
      * @param input  the {@code String} to unescape, may be null
 744  
      * @return a new unescaped {@code String}, {@code null} if null string input
 745  
      * @see #escapeXml(String)
 746  
      * @see #escapeXml10(String)
 747  
      * @see #escapeXml11(String)
 748  
      */
 749  
     public static final String unescapeXml(final String input) {
 750  11
         return UNESCAPE_XML.translate(input);
 751  
     }
 752  
 
 753  
     //-----------------------------------------------------------------------
 754  
 
 755  
     /**
 756  
      * <p>Returns a {@code String} value for a CSV column enclosed in double quotes,
 757  
      * if required.</p>
 758  
      *
 759  
      * <p>If the value contains a comma, newline or double quote, then the
 760  
      *    String value is returned enclosed in double quotes.</p>
 761  
      *
 762  
      * <p>Any double quote characters in the value are escaped with another double quote.</p>
 763  
      *
 764  
      * <p>If the value does not contain a comma, newline or double quote, then the
 765  
      *    String value is returned unchanged.</p>
 766  
      *
 767  
      * see <a href="http://en.wikipedia.org/wiki/Comma-separated_values">Wikipedia</a> and
 768  
      * <a href="http://tools.ietf.org/html/rfc4180">RFC 4180</a>.
 769  
      *
 770  
      * @param input the input CSV column String, may be null
 771  
      * @return the input String, enclosed in double quotes if the value contains a comma,
 772  
      * newline or double quote, {@code null} if null string input
 773  
      * @since 2.4
 774  
      */
 775  
     public static final String escapeCsv(final String input) {
 776  12
         return ESCAPE_CSV.translate(input);
 777  
     }
 778  
 
 779  
     /**
 780  
      * <p>Returns a {@code String} value for an unescaped CSV column. </p>
 781  
      *
 782  
      * <p>If the value is enclosed in double quotes, and contains a comma, newline 
 783  
      *    or double quote, then quotes are removed. 
 784  
      * </p>
 785  
      *
 786  
      * <p>Any double quote escaped characters (a pair of double quotes) are unescaped 
 787  
      *    to just one double quote. </p>
 788  
      *
 789  
      * <p>If the value is not enclosed in double quotes, or is and does not contain a 
 790  
      *    comma, newline or double quote, then the String value is returned unchanged.</p>
 791  
      *
 792  
      * see <a href="http://en.wikipedia.org/wiki/Comma-separated_values">Wikipedia</a> and
 793  
      * <a href="http://tools.ietf.org/html/rfc4180">RFC 4180</a>.
 794  
      *
 795  
      * @param input the input CSV column String, may be null
 796  
      * @return the input String, with enclosing double quotes removed and embedded double 
 797  
      * quotes unescaped, {@code null} if null string input
 798  
      * @since 2.4
 799  
      */
 800  
     public static final String unescapeCsv(final String input) {
 801  13
         return UNESCAPE_CSV.translate(input);
 802  
     }
 803  
 
 804  
 }