Поиск по блогу

вторник, 31 января 2012 г.

Удаление невалидных символов из XML в Java

Решил вот наконец написать что-то умное в блог :-) Я же все-таки программист и возможно найденные мной решения некоторых проблем помогут кому-нибудь сэкономить время. Сегодня расскажу о том, как удалить невалидные символы из XML.
Сперва коротко о самой сути проблемы. Я думаю, что рассказывать что такое XML и как его используют не нужно :-) XML сейчас везде. Но вот далеко не все догадываются, что в XML допустимы далеко не все символы Unicode. Подробнее об этом можно почитать здесь или здесь.
В принципе какие-то проблемы с невалидными символами в XML встречаются достаточно редко так как во-первых практически все невалидные символы крайне редки, а во-вторых никакой нормальный парсер не позволит создать документ с невалидными символами. А вот если XML-документ приходит от какой-нибудь legacy-системы, где он был сформирован как обычный текстовый файл... В общем как раз именно так у меня и было :-) Само собой никто исправлять ошибку в legacy-системе не хотел и поэтому пришлось искать обходное решение. Решил я эту проблему на Java так:

public String removeInvalidXMLCharacters(String s) {
 StringBuilder out = new StringBuilder(); //Результат
 int codePoint; //Текущий символ
 int i = 0;
 int replacedCount = 0;
 while (i < s.length()) {
      codePoint = s.codePointAt(i); //Получаем код символа
      if ((codePoint == 0x9) ||  //Проверяем на валидность
         (codePoint == 0xA) ||
         (codePoint == 0xD) ||
         ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) ||
         ((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) ||
         ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF))) {
           out.append(Character.toChars(codePoint));
      } else {
         out.append(" ");
         replacedCount++;
         System.out.println("Character with hex code 0x" + Integer.toHexString(codePoint).toUpperCase() + " at position " + i + " was replaced by space");
      }
      i+= Character.charCount(codePoint); //Увеличиваем i на длину символа
 }
System.out.println("Replaced " + replacedCount + " char(s)");
return out.toString();
}

Как видите, все работает элементарно - главное знать диапазоны значений. Данный метод получает XML как строку, проверяет каждый символ в документе и если символ не попадает в диапазон валидных значений, то он заменяется на пробел.

2 комментария: