2010-02-02 4 views
0

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

код кажется достаточно простым:

String stringToParse = "<body><xml>some stuff</xml></body>"; 
Pattern pattern = Pattern.compile("</[^(a|em|li)]*?>"); 
Matcher matcher = pattern.matcher(stringToParse); 
stringToParse = matcher.replaceAll(""); 

Однако, когда это работает, он пропускает "XML" закрывающий тег. Кажется, что пропускает любой тег, где в скомпилированной группе есть соответствующий символ (a | em | li), то есть если я удалю «l» из «li», он работает.

Я бы ожидать, что это возвращает следующую строку: «<body><xml>some stuff» (я делаю дополнительный синтаксический анализ, чтобы удалить теги открытия, но держать его просто для примера).

+0

Не могли бы вы конкретно указать, что вы хотите получить окончательное значение stringToParse, и что вы получаете вместо этого? –

+1

Это похоже на некоторые важные для безопасности задачи. Я бы настоятельно рекомендовал забыть идею регулярного выражения и вместо этого использовать ** настоящий ** парсер. Даже если вы назвали переменную «stringToParse», использование регулярного выражения ** не ** разбор. – BalusC

ответ

4

Вы, вероятно, не следует использовать регулярное выражение для решения этой задачи, но давайте посмотрим, что происходит ...

Ваша проблема заключается в том, что вы используете негативный класс символов, а внутри классов символов вы не можете писать сложные выражения - только символы. Вы можете попробовать отрицательный предпросмотр вместо:

"</(?!a|em|li).*?>" 

Но это не будет обрабатывать несколько случаев правильно:

  • Комментарии, содержащие вещи, которые выглядят как теги.
  • Теги как строки в атрибутах.
  • Теги, которые начинаются с символа a, em или li, но на самом деле являются другими тегами.
  • Заглавные буквы.
  • и т.д ...

Вы, вероятно, может решить эти проблемы, но вы должны рассмотреть вопрос о том, является ли оно стоит, или если было бы лучше искать решение, основанное на правильном HTML парсер ,

+0

+1 для объяснения и толчок в правильном направлении – akf

+0

Удивительный, Марк, спасибо за объяснение. Я не понял этого аспекта классов персонажей. –

0

Вы не можете использовать чередование внутри класса символов. Класс символов всегда соответствует одному символу.

Скорее всего, вы хотите использовать отрицательный предпросмотр или вместо: просмотра назад

"</(?!a|em|li).*?>" 
1

Я бы действительно использовать правильный синтаксический анализатор для этого (например, JTidy). Вы не можете анализировать XML/HTML с помощью регулярных выражений, поскольку он не является регулярным, и никаких крайних случаев не существует. Я предпочел бы использовать синтаксический анализ XML, доступный в стандартном JDK (JAXP) или подходящей сторонней библиотеке (см. Выше) и соответствующим образом настроить ваш вывод.

См. this answer для более страстной информации re. синтаксический анализ XML/HTML с помощью регулярных выражений.

Смежные вопросы