27

こんにちは、文字列からすべての無効な XML 文字を削除したいと考えています。string.replace メソッドで正規表現を使用したいと考えています。

お気に入り

line.replace(regExp,"");

使用する正しい正規表現は何ですか?

無効な XML 文字は、これ以外のすべてです:

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

ありがとう。

4

9 に答える 9

86

Java の正規表現は補助文字をサポートしているため、UTF-16 でエンコードされた 2 つの文字でこれらの高い範囲を指定できます。

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"
                    + "]";

ほとんどの人は、XML 1.0 バージョンを希望します。

XML 1.1で不正な文字を削除するパターンは次のとおりです。

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

String.replaceAll(...)ではなく andを使用する必要がありますString.replace(...)

String illegal = "Hello, World!\0";
String legal = illegal.replaceAll(pattern, "");
于 2010-11-21T12:58:40.870 に答える
10

代理文字を考慮する必要がありますか? それ以外の場合、'(current >= 0x10000) && (current <= 0x10FFFF)' は真になりません。

また、正規表現の方法が次のループよりも遅いように見えることもテストしました。

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));
        }
    }
}
于 2012-07-26T15:31:56.187 に答える
3

Junのソリューション、簡略化。を使用すると、またはStringBuffer#appendCodePoint(int)は必要ありません。が より大きいかどうかを確認することで、サロゲート ペアを判別できます。char currentString#charAt(int)codePoint0xFFFF

(低サロゲートはフィルターを通過しないため、i++ を実行する必要はありません。しかし、別のコード ポイントに対してコードを再利用すると失敗します。私はハッキングよりもプログラミングを好みます。)

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);
    }
}
于 2015-02-02T17:33:18.227 に答える
1

マーク・マクラーレンのウェブログより

  /**
   * 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();
  }   
于 2012-06-05T09:20:15.960 に答える
0

禁止文字を含むテキスト要素を XML のような形式で保存したい場合は、代わりに XPL を使用できます。開発キットは、XPL から XML および XML への同時処理を提供します。つまり、XPL から XML への変換にかかる時間はありません。または、XML (名前空間) の全機能を必要としない場合は、XPL を使用できます。

ウェブページ: HLL XPL

于 2017-04-07T13:09:41.320 に答える
-1

以下の記事が参考になると思います。

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

早速、Jakarta プロジェクトの StringEscapeUtils を使用してみます。

于 2010-11-21T12:26:00.210 に答える