removendo caracteres XML inválidos de uma string em java

Oi eu gostaria de remover todos os caracteres XML inválidos de uma seqüência de caracteres. Eu gostaria de usar uma expressão regular com o método string.replace.

gostar

line.replace(regExp,"");

qual é o regExp certo para usar?

caractere XML inválido é tudo o que não é isso:

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

obrigado.

A regex do Java suporta caracteres suplementares , para que você possa especificar os intervalos altos com dois caracteres codificados em UTF-16.

Aqui está o padrão para remover caracteres que são ilegais no 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" + "]"; 

A maioria das pessoas vai querer a versão XML 1.0.

Aqui está o padrão para remover caracteres que são ilegais no XML 1.1 :

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

Você precisará usar String.replaceAll(...) e não String.replace(...) .

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

Devemos considerar caracteres substitutos? caso contrário, ‘(atual> = 0x10000) && (atual <= 0x10FFFF)' nunca será verdadeiro.

Também testei que o modo regex parece mais lento que o loop seguinte.

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

Solução de junho, simplificada. Usando StringBuffer#appendCodePoint(int) , não preciso de char current ou String#charAt(int) . Eu posso dizer um par substituto, verificando se codePoint é maior que 0xFFFF .

(Não é necessário fazer o i ++, uma vez que um substituto baixo não passaria no filtro. Mas, então, um iria reutilizar o código para diferentes pontos de código e ele falharia. Eu prefiro programar para 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); } } 

Do 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 essas respostas até agora apenas substituem os personagens. Mas, às vezes, um documento XML terá seqüências de entidades XML inválidas, resultando em erros. Por exemplo, se você tiver o  em seu xml, um analisador java xml lançará Illegal character entity: expansion character (code 0x2 at ...

Aqui está um programa java simples que pode replace essas seqüências 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 melhor maneira de codificar dados de texto para XML em 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 você deseja armazenar elementos de texto com os caracteres proibidos em formato XML, pode usar XPL. O dev-kit fornece XPL simultâneo para processamento XML e XML – o que significa nenhum custo de tempo para a conversão de XPL para XML. Ou, se você não precisa do poder total do XML (namespaces), você pode simplesmente usar o XPL.

Página da 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; } 

Eu acredito que os artigos a seguir podem ajudá-lo.

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

Em breve, tente usar o StringEscapeUtils do projeto Jakarta.

    Intereting Posts