Java: регулярное выражение для удаления частей файла XML

Я читаю XML-файл Википедии, в котором я должен удалить что-либо между фигурными скобками. Например, для следующей строки:

String text = "{{Использовать даты dmy | дата = ноябрь 2012}}} {{Infobox musicartist | name
= Русс Конвей | изображение = | заголовок = Расс Конвей, изображенный на лицевой стороне его 1959 года [[Расширенная игра |EP]] ''More Party Pops''. | image_size = | background = non_vocal_instrumentalist | имя_сознания = Тревор Герберт Стэнфорд | псевдоним = | дата рождения = {{дата рождения |1925|09|2|df=y}} | место рождения = [[Бристоль]], [[Англия]], Великобритания | death_date = {{дата и возраст смерти |2000|11|16|1925|09|02|df=y}} | death_place = [[Истборн]], [[Сассекс]], Англия, Великобритания | происхождение = | инструмент = [[Piano]] | жанр = | занятие = [[Музыкант]] | years_active = | лейбл = EMI (Колумбия), Pye, MusicMedia, Черчилль | related_acts = | сайт = | notable_instruments = }}";

Его следует заменить пустой строкой. Обратите внимание, что в примере есть несколько новых строк и вложенных {{...}}

Я использую следующий код:

Pattern p1 = Pattern.compile(".*\\({\\{.+\\}\\}).*", Pattern.DOTALL);
Matcher m1 = p1.matcher(text);

while(m1.find()){

String text1 = text.replaceAll(m1.group(1), "");
}

Я новичок в regex, подскажите, пожалуйста, что я делаю не так?

1 ответ

Решение

Обычно это невозможно с помощью регулярного выражения. Обычные языки не могут описать произвольные уровни вложенности, потому что у них нет возможности "посчитать", на каком уровне они находятся.

Если вам абсолютно необходимо использовать регулярное выражение, вы можете создать громоздкое выражение, которое будет работать, например, для трех уровней вложенности, кодируя все возможности вложенности вручную. Но это было бы чрезвычайно обременительно, фактически было бы нарушением СУХОГО, и далеко не подходящее средство для работы.

Скорее всего, было бы легче сделать это "вручную", если потребуется. Сканируйте строку самостоятельно, и каждый раз, когда вы нажимаете {{ увеличить "уровень скобки"; каждый раз, когда вы нажмете }} уменьшить его. Скопируйте каждый символ на выход, если и только если уровень скобки равен нулю.

Что-то вроде (не проверено):

StringBuilder output = new StringBuilder();
char[] input = text.toCharArray();
int braceLevel = 0;
for (int i = 0; i < input.length; i++) {
   final char c = input[i];
   if (c == '{') {
      // Check for {{
      if (i < input.length - 1 && input[i+1] == '{') {
         // Yep, it's a double brace - increase the level, consume
         // the second character and continue with the next char
         braceLevel++;
         i++;
         continue;
      }
   }
   else if (c == '}' && braceLevel > 0) {
      // Check for a closing brace similar to above
      if (i < input.length - 1 && input[i+1] == '}') {
         braceLevel--;
         i++;
         continue;
      }
   }

   if (braceLevel == 0) {
      output.append(c);
   }
}

// Now output contains every character that was not contained within brackets
Другие вопросы по тегам