java xml regex invalid-characters

eliminar caracteres XML no válidos de una cadena en java



regex invalid-characters (9)

Hola, me gustaría eliminar todos los caracteres XML no válidos de una cadena. Me gustaría usar una expresión regular con el método string.replace.

me gusta

line.replace(regExp,"");

¿Cuál es el regExp correcto para usar?

Carácter XML inválido es todo lo que no es esto:

[#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]

Gracias.


¿De la mejor manera de codificar datos de texto para XML en Java?

String xmlEscapeText(String t) { StringBuilder sb = new StringBuilder(); for(int i = 0; i < t.length(); i++){ char c = t.charAt(i); switch(c){ case ''<'': sb.append("&lt;"); break; case ''>'': sb.append("&gt;"); break; case ''/"'': sb.append("&quot;"); break; case ''&'': sb.append("&amp;"); break; case ''/''': sb.append("&apos;"); break; default: if(c>0x7e) { sb.append("&#"+((int)c)+";"); }else sb.append(c); } } return sb.toString(); }


¿Debemos considerar personajes sustitutos? de lo contrario, ''(current> = 0x10000) && (current <= 0x10FFFF)'' nunca será verdadero.

También se probó que la forma de expresión regular parece más lenta que el siguiente bucle.

if (null == text || text.isEmpty()) { return text; } final int len = text.length(); char current = 0; int codePoint = 0; StringBuilder sb = new StringBuilder(); for (int i = 0; i < len; i++) { current = text.charAt(i); boolean surrogate = false; if (Character.isHighSurrogate(current) && i + 1 < len && Character.isLowSurrogate(text.charAt(i + 1))) { surrogate = true; codePoint = text.codePointAt(i++); } else { codePoint = current; } if ((codePoint == 0x9) || (codePoint == 0xA) || (codePoint == 0xD) || ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF))) { sb.append(current); if (surrogate) { sb.append(text.charAt(i)); } } }



Del weblog de Mark McLaren

/** * This method ensures that the output String has only * valid XML unicode characters as specified by the * XML 1.0 standard. For reference, please see * <a href="http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char">the * standard</a>. This method will return an empty * String if the input is null or empty. * * @param in The String whose non-valid characters we want to remove. * @return The in String, stripped of non-valid characters. */ public static String stripNonValidXMLCharacters(String in) { StringBuffer out = new StringBuffer(); // Used to hold the output. char current; // Used to reference the current character. if (in == null || ("".equals(in))) return ""; // vacancy test. for (int i = 0; i < in.length(); i++) { current = in.charAt(i); // NOTE: No IndexOutOfBoundsException caught here; it should not happen. if ((current == 0x9) || (current == 0xA) || (current == 0xD) || ((current >= 0x20) && (current <= 0xD7FF)) || ((current >= 0xE000) && (current <= 0xFFFD)) || ((current >= 0x10000) && (current <= 0x10FFFF))) out.append(current); } return out.toString(); }


La solución de Jun, simplificada. Al usar StringBuffer#appendCodePoint(int) , no necesito char current o String#charAt(int) . Puedo decirle a un par sustituto verificando si codePoint es mayor que 0xFFFF .

(No es necesario hacer el i ++, ya que un sustituto bajo no pasaría el filtro. Pero luego se reutilizaría el código para diferentes puntos de código y fallaría. Prefiero la programación a la piratería).

StringBuilder sb = new StringBuilder(); for (int i = 0; i < text.length(); i++) { int codePoint = text.codePointAt(i); if (codePoint > 0xFFFF) { i++; } if ((codePoint == 0x9) || (codePoint == 0xA) || (codePoint == 0xD) || ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF))) { sb.appendCodePoint(codePoint); } }


Si desea almacenar elementos de texto con los caracteres prohibidos en forma similar a XML, puede utilizar XPL en su lugar. El dev-kit proporciona procesamiento simultáneo de XPL a XML y XML, lo que significa que no hay costos de tiempo para la traducción de XPL a XML. O, si no necesita toda la potencia de XML (espacios de nombres), simplemente puede usar XPL.

Página web: HLL XPL


Todas estas respuestas hasta ahora solo reemplazan a los personajes. Pero a veces un documento XML tendrá secuencias de entidad XML no válidas que darán como resultado errores. Por ejemplo, si tiene &#2; en su xml, un analizador java xml lanzará una Illegal character entity: expansion character (code 0x2 at ...

Aquí hay un programa Java simple que puede reemplazar esas secuencias de entidades no válidas.

public final Pattern XML_ENTITY_PATTERN = Pattern.compile("//&//#(?:x([0-9a-fA-F]+)|([0-9]+))//;"); /** * Remove problematic xml entities from the xml string so that you can parse it with java DOM / SAX libraries. */ String getCleanedXml(String xmlString) { Matcher m = XML_ENTITY_PATTERN.matcher(xmlString); Set<String> replaceSet = new HashSet<>(); while (m.find()) { String group = m.group(1); int val; if (group != null) { val = Integer.parseInt(group, 16); if (isInvalidXmlChar(val)) { replaceSet.add("&#x" + group + ";"); } } else if ((group = m.group(2)) != null) { val = Integer.parseInt(group); if (isInvalidXmlChar(val)) { replaceSet.add("&#" + group + ";"); } } } String cleanedXmlString = xmlString; for (String replacer : replaceSet) { cleanedXmlString = cleanedXmlString.replaceAll(replacer, ""); } return cleanedXmlString; } private boolean isInvalidXmlChar(int val) { if (val == 0x9 || val == 0xA || val == 0xD || val >= 0x20 && val <= 0xD7FF || val >= 0x10000 && val <= 0x10FFFF) { return false; } return true; }


La expresión regular de Java admite caracteres suplementarios , por lo que puede especificar esos altos rangos con dos caracteres codificados en UTF-16.

Aquí está el patrón para eliminar caracteres que son ilegales en XML 1.0 :

// XML 1.0 // #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] String xml10pattern = "[^" + "/u0009/r/n" + "/u0020-/uD7FF" + "/uE000-/uFFFD" + "/ud800/udc00-/udbff/udfff" + "]";

La mayoría de la gente querrá la versión XML 1.0.

Aquí está el patrón para eliminar caracteres que son ilegales en XML 1.1 :

// XML 1.1 // [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] String xml11pattern = "[^" + "/u0001-/uD7FF" + "/uE000-/uFFFD" + "/ud800/udc00-/udbff/udfff" + "]+";

Deberá usar String.replaceAll(...) y no String.replace(...) .

String illegal = "Hello, World!/0"; String legal = illegal.replaceAll(pattern, "");


String xmlData = xmlData.codePoints().filter(c -> isValidXMLChar(c)).collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString(); private boolean isValidXMLChar(int c) { if((c == 0x9) || (c == 0xA) || (c == 0xD) || ((c >= 0x20) && (c <= 0xD7FF)) || ((c >= 0xE000) && (c <= 0xFFFD)) || ((c >= 0x10000) && (c <= 0x10FFFF))) { return true; } return false; }