suppression des caractères XML invalides d'une chaîne de caractères en java

Hi j'aimerais supprimer tous les caractères XML invalides d'une chaîne de caractères. je voudrais utiliser une expression régulière avec la chaîne.remplacement de la méthode.

line.replace(regExp,"");

Quel est le bon regExp à utiliser ?

le caractère XML invalide est tout ce qui n'est pas cela:

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

merci.

18
demandé sur yossi 2010-11-21 14:37:58

9 réponses

le regex de Java supporte des caractères supplémentaires, de sorte que vous pouvez spécifier ces fourchettes élevées avec deux caractères encodés UTF-16.

voici le modèle pour supprimer les caractères qui sont illégaux dans 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 plupart des gens voudront la version XML 1.0.

voici le modèle pour supprimer les caractères qui sont illégaux dans XML 1.1:

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

vous devrez utiliser String.replaceAll(...) et non String.replace(...).

String illegal = "Hello, World!";
String legal = illegal.replaceAll(pattern, "");
68
répondu McDowell 2013-04-22 11:16:28

devrions-nous envisager des caractères de substitution? sinon, '(courant >= 0x10000) & & (<= 0x10FFFF) " ne sera jamais vrai.

a également testé que la voie regex semble plus lente que la boucle suivante.

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));
        }
    }
}
6
répondu Jun 2012-07-27 05:27:38

la solution de Jun, simplifiée. En utilisant StringBuffer#appendCodePoint(int), je n'ai pas besoin char current ou String#charAt(int). Je peux dire une paire de substitution en vérifiant si codePoint est supérieur à 0xFFFF.

(il n'est pas nécessaire de faire le i++, puisqu'une mère porteuse basse ne passerait pas le filtre. Mais alors on réutiliserait le code pour différents points de code et il échouerait. Je préfère la programmation au piratage.)

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);
    }
}
2
répondu Vlasec 2015-02-02 17:33:18

Marque McLaren Blog

  /**
   * 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();
  }   
1
répondu Renaud 2012-06-05 09:20:15

toutes ces réponses ne remplacent jusqu'à présent que les caractères eux-mêmes. Mais parfois un document XML aura des séquences d'entités XML invalides résultant en erreurs. Par exemple, si vous avez &#2; dans votre xml, un analyseur java xml lancera Illegal character entity: expansion character (code 0x2 at ....

voici un programme java simple qui peut remplacer ces séquences d'entités invalides.

  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;
  }
1
répondu Nicholas DiPiazza 2017-07-20 19:14:36

meilleure façon d'encoder des données texte pour 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();
}
0
répondu Roger F. Gay 2017-05-23 12:10:33

si vous voulez stocker des éléments de texte avec les caractères interdits dans un format de type XML, vous pouvez utiliser XPL à la place. Le dev-kit fournit le traitement simultané de XPL à XML et XML - ce qui signifie aucun coût de temps à la traduction de XPL à XML. Ou, si vous n'avez pas besoin de la pleine puissance de XML (namespaces), vous pouvez simplement utiliser XPL.

page Web: HLL XPL

0
répondu Roger F. Gay 2017-04-07 13:09:41
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;
}
0
répondu Hans Schreuder 2018-01-29 08:18:56

je crois que les articles suivants peuvent vous aider.

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

bientôt, essayez D'utiliser StringEscapeUtils du projet Jakarta.

-2
répondu AlexR 2010-11-21 12:26:00