StringResourceEscaper { @NonNull static String escapeCharacterData(@NonNull String xml) { if (xml.isEmpty()) { return ""; } xml = DECIMAL_REFERENCE.matcher(xml).replaceAll(DECIMAL_PLACEHOLDER + "$1;"); xml = HEXADECIMAL_REFERENCE.matcher(xml).replaceAll(HEXADECIMAL_PLACEHOLDER + "$1;"); StringBuilder builder = new StringBuilder(xml.length() * 3 / 2); if (startsOrEndsWithSpace(xml)) { builder.append('"'); } else if (startsWithQuestionMarkOrAtSign(xml)) { builder.append('\\'); } try { parse(xml, builder); } catch (SAXException exception) { throw new IllegalArgumentException(xml, exception); } if (startsOrEndsWithSpace(xml)) { builder.append('"'); } xml = builder.toString(); xml = ESCAPED_DECIMAL_REFERENCE.matcher(xml).replaceAll("&#$1;"); xml = ESCAPED_HEXADECIMAL_REFERENCE.matcher(xml).replaceAll("&#x$1;"); return xml; } private  StringResourceEscaper();   }
@Test public void escapeCharacterDataInvalidXml() { try { StringResourceEscaper.escapeCharacterData("<"); fail(); } catch (IllegalArgumentException exception) { } }