Регулярное выражение для удаления тегов XML и их содержимого - PullRequest
3 голосов
/ 23 сентября 2008

У меня есть следующая строка, и я хотел бы удалить <bpt *>*</bpt> и <ept *>*</ept> (обратите внимание на дополнительное содержимое тега внутри них, которое также необходимо удалить) без использования синтаксического анализатора XML (накладные расходы слишком велики для крошечных строк).

The big <bpt i="1" x="1" type="bold"><b></bpt>black<ept i="1"></b></ept> <bpt i="2" x="2" type="ulined"><u></bpt>cat<ept i="2"></u></ept> sleeps.

Подойдет любое регулярное выражение в VB.NET или C #.

Ответы [ 7 ]

7 голосов
/ 23 сентября 2008

Если вы просто хотите удалить все теги из строки, используйте это (C #):

try {
    yourstring = Regex.Replace(yourstring, "(<[be]pt[^>]+>.+?</[be]pt>)", "");
} catch (ArgumentException ex) {
    // Syntax error in the regular expression
}

EDIT:

Я решил добавить к своему решению лучший вариант. Предыдущая опция не сработала бы, если бы были встроенные теги. Это новое решение должно удалить все теги <** pt *>, встроенные или нет. Кроме того, в этом решении используется обратная ссылка на исходное совпадение [be], чтобы найти точный совпадающий конечный тег. Это решение также создает повторно используемый объект Regex для повышения производительности, так что на каждой итерации не нужно перекомпилировать Regex:

bool FoundMatch = false;

try {
    Regex regex = new Regex(@"<([be])pt[^>]+>.+?</\1pt>");
    while(regex.IsMatch(yourstring) ) {
        yourstring = regex.Replace(yourstring, "");
    }
} catch (ArgumentException ex) {
    // Syntax error in the regular expression
}

ДОПОЛНИТЕЛЬНЫЕ ЗАМЕЧАНИЯ:

В комментариях пользователь выразил беспокойство, что '.' шаблон соответствия будет интенсивным процессором. Хотя это верно в случае отдельного жадного «.», Использование не жадного символа «?» заставляет механизм регулярных выражений смотреть только вперед, пока не найдет первое совпадение следующего символа в шаблоне против жадного '.' который требует, чтобы двигатель смотрел вперед до конца строки. Я использую RegexBuddy в качестве инструмента разработки регулярных выражений, и он включает в себя отладчик, который позволяет вам видеть относительную производительность различных шаблонов регулярных выражений. Он также автоматически комментирует ваши регулярные выражения при желании, поэтому я решил включить эти комментарии здесь, чтобы объяснить использованное выше регулярное выражение:

    // <([be])pt[^>]+>.+?</\1pt>
// 
// Match the character "<" literally «<»
// Match the regular expression below and capture its match into backreference number 1 «([be])»
//    Match a single character present in the list "be" «[be]»
// Match the characters "pt" literally «pt»
// Match any character that is not a ">" «[^>]+»
//    Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
// Match the character ">" literally «>»
// Match any single character that is not a line break character «.+?»
//    Between one and unlimited times, as few times as possible, expanding as needed (lazy) «+?»
// Match the characters "</" literally «</»
// Match the same text as most recently matched by backreference number 1 «\1»
// Match the characters "pt>" literally «pt>»
1 голос
/ 23 сентября 2008

Почему вы говорите, что накладные расходы слишком велики? Вы измерили это? Или ты угадаешь?

Использование регулярного выражения вместо правильного парсера - это ярлык, с которым вы можете столкнуться, когда кто-то придет с чем-то вроде ">

1 голос
/ 23 сентября 2008

Полагаю, вы хотите полностью сбросить тег?

(<bpt .*?>.*?</bpt>)|(<ept .*?>.*?</ept>)

? после * делает его нежадным, поэтому он попытается найти как можно меньше символов.

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

0 голосов
/ 30 сентября 2010

Вы это измерили? У меня есть проблемы с производительностью при использовании движка регулярных выражений .NET, но, напротив, я проанализировал xml-файлы размером около 40 ГБ без проблемы с помощью анализатора Xml (вам нужно использовать XmlReader для больших строк Однако).

Пожалуйста, опубликуйте пример кода и укажите ваши требования к производительности: я сомневаюсь, что класс Regex является лучшим решением, если производительность имеет значение.

0 голосов
/ 28 декабря 2008

Есть ли какой-нибудь возможный способ получить глобальное решение для regex.pattern для текста типа xml? таким образом я избавлюсь от функции замены, а оболочка использует регулярное выражение. Беда в том, чтобы проанализировать <> порядок или нет .. Также замена зарезервированных символов на '& и так далее. вот код обработка специальных функций символов Функция-друг ReplaceSpecChars (строка ByVal как строка) как строка Dim arrLessThan As New Collection Dim arrGreaterThan As New Collection Если не IsDBNull (str), то

  str = CStr(str)
  If Len(str) > 0 Then
    str = Replace(str, "&", "&amp;")
    str = Replace(str, "'", "&apos;")
    str = Replace(str, """", "&quot;")
    arrLessThan = FindLocationOfChar("<", str)
    arrGreaterThan = FindLocationOfChar(">", str)
    str = ChangeGreaterLess(arrLessThan, arrGreaterThan, str)
    str = Replace(str, Chr(13), "chr(13)")
    str = Replace(str, Chr(10), "chr(10)")
  End If
  Return str
Else
  Return ""
End If

End Function Друг Функция ChangeGreaterLess (ByVal lh As Collection, ByVal gr As Collection, ByVal str As String) Как строка Поскольку я как целое число = 0 к lh.Count Если CInt (lh.Item (i))> CInt (gr.Item (i)), то str = Заменить (str, "<", "<") ///////// проблемы //// Конец, если </p>

  Next


    str = Replace(str, ">", "&gt;")

End Function Функция Friend FindLocationOfChar (ByVal chr As Char, ByVal str As String) Как коллекция Dim Arr As New Collection For i As Integer = 1 Для str.Length () - 1 Если str.ToCharArray (i, 1) = chr, то arr.Add (я) End If следующий Возврат обр Конечная функция

возникла проблема на отметке проблемы

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

0 голосов
/ 24 сентября 2008

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

Правильный (то есть эффективный и правильный) способ сделать это с помощью XSLT. XSLT-преобразование, которое копирует все, кроме определенного элемента, на выход является тривиальным расширением тождественного преобразования. Как только преобразование скомпилировано, оно будет выполнено чрезвычайно быстро. И не будет никаких скрытых дефектов.

0 голосов
/ 23 сентября 2008

Поддерживает ли механизм .NET regex негативные запросы? Если да, то вы можете использовать

(<([eb])pt[^>]+>((?!</\2pt>).)+</\2pt>)

Что делает Большой черный кот спит. из строки выше, если вы удалите все спички. Однако имейте в виду, что он не будет работать, если у вас есть вложенные элементы bpt / ept. Возможно, вы также захотите добавить \s в некоторых местах, чтобы обеспечить дополнительные пробелы в закрывающих элементах и ​​т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...