rimozione di caratteri XML non validi da una stringa in java

Ciao, vorrei rimuovere tutti i caratteri XML non validi da una stringa. Mi piacerebbe usare un’espressione regolare con il metodo string.replace.

piace

line.replace(regExp,"");

qual è il giusto regExp da usare?

carattere XML non valido è tutto ciò che non è questo:

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

Grazie.

La regex di Java supporta caratteri supplementari , quindi è ansible specificare tali intervalli alti con due caratteri codificati UTF-16.

Ecco il modello per la rimozione di caratteri che sono illegali in 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 maggior parte delle persone vorranno la versione XML 1.0.

Ecco il modello per la rimozione di caratteri che sono illegali in XML 1.1 :

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

Sarà necessario utilizzare String.replaceAll(...) e non String.replace(...) .

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

Dovremmo considerare i personaggi surrogati? altrimenti ‘(corrente> = 0x10000) && (corrente < = 0x10FFFF)' non sarà mai vero.

Inoltre, è stato verificato che la modalità regex sembra più lenta del ciclo successivo.

 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 soluzione di Jun, semplificata. Usando StringBuffer#appendCodePoint(int) , non ho bisogno di char current o String#charAt(int) . Posso dire una coppia surrogata controllando se codePoint è maggiore di 0xFFFF .

(Non è necessario eseguire l’i ++, dal momento che un surrogato basso non passerebbe il filtro, ma poi si riutilizzerebbe il codice per diversi punti di codice e fallirebbe. Preferisco la programmazione all’hacking.)

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

Da Mark McLaren’s Weblog

  /** * 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(); } 

Tutte queste risposte finora sostituiscono solo i personaggi stessi. Ma a volte un documento XML avrà sequenze di quadro XML non valide che causano errori. Ad esempio, se hai  nel tuo xml, un parser java xml getterà Illegal character entity: expansion character (code 0x2 at ...

Ecco un semplice programma java che può sostituire quelle sequenze di entity framework non valide.

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

Dal modo migliore per codificare i dati di testo per XML in 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(); } 

Se si desidera memorizzare elementi di testo con i caratteri vietati in formato XML, è ansible utilizzare XPL. Il dev-kit fornisce l’XPL simultaneo all’elaborazione XML e XML, il che significa che non vi è alcun costo di tempo per la traduzione da XPL a XML. Oppure, se non hai bisogno della piena potenza di XML (namespace), puoi semplicemente usare XPL.

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

Credo che i seguenti articoli possano aiutarti.

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

Presto, prova ad usare StringEscapeUtils dal progetto Jakarta.