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

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

me gusta

line.replace(regExp,"");

¿Cuál es el correcto regExp para usar?

el carácter XML no válido es todo lo que no es esto:

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

Gracias.

La expresión regular de Java admite caracteres suplementarios , por lo que puede especificar esos rangos altos con dos caracteres codificados 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" + "]+"; 

Tendrá que utilizar String.replaceAll(...) y no String.replace(...) .

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

¿Deberíamos considerar personajes sustitutos? de lo contrario ‘(actual> = 0x10000) && (actual <= 0x10FFFF)' nunca será verdadero.

También probó que el modo de expresión regular parece más lento que el siguiente ciclo.

 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)); } } } 

La solución de Jun, simplificada. Usando StringBuffer#appendCodePoint(int) , no necesito ninguna char current o String#charAt(int) . Puedo decir un par sustituto comprobando si codePoint es mayor que 0xFFFF .

(No es necesario hacer el i ++, ya que un sustituto bajo no pasaría el filtro. Pero uno volvería a usar el código para diferentes puntos de código y fallaría. Prefiero progtwigr para piratear).

 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); } } 

Del blog 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 * the * standard. 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(); } 

Todas estas respuestas hasta ahora solo reemplazan a los personajes en sí mismos. Pero a veces un documento XML tendrá secuencias de entidades XML no válidas que generarán errores. Por ejemplo, si tiene  en tu xml, un analizador de Java xml arrojará una Illegal character entity: expansion character (code 0x2 at ...

Aquí hay un progtwig simple de Java que puede reemplazar esas secuencias de entidades invá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 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; } 

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("<"); break; case '>': sb.append(">"); break; case '\"': sb.append("""); break; case '&': sb.append("&"); break; case '\'': sb.append("'"); break; default: if(c>0x7e) { sb.append("&#"+((int)c)+";"); }else sb.append(c); } } return sb.toString(); } 

Si desea almacenar elementos de texto con los caracteres prohibidos en forma de XML, puede usar XPL en su lugar. El dev-kit proporciona XPL concurrente a XML y procesamiento XML, lo que significa que no hay costo de tiempo para la traducción de XPL a XML. O bien, si no necesita todo el poder de XML (espacios de nombres), puede usar XPL.

Página web: HLL XPL

 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; } 

Creo que los siguientes artículos pueden ayudarte.

http://commons.apache.org/lang/api-2.1/org/apache/commons/lang/StringEscapeUtils.html http://www.javapractices.com/topic/TopicAction.do?Id=96

En breve, intente utilizar StringEscapeUtils del proyecto de Yakarta.

    Intereting Posts