Регулярное выражение для определенных тегов и их содержимого, сгруппированных по имени тега.

StackOverflow https://stackoverflow.com/questions/200525

  •  03-07-2019
  •  | 
  •  

Вопрос

Вот ввод (html, а не xml):

... html content ...
<tag1> content for tag 1 </tag1>
<tag2> content for tag 2 </tag2>
<tag3> content for tag 3 </tag3>
... html content ...

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

Другими словами:

match.Groups["name"] would be "tag1"
match.Groups["value"] would be "content for tag 2"

Есть идеи?

Это было полезно?

Решение

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

Вот регулярное выражение, которое будет сопоставлять имя и содержимое тега с пронумерованными вложенными совпадениями.

<(tag1|tag2|tag3)>(.*?)</$1>

Вот вариант с именами групп в стиле .NET.

<(?'name'tag1|tag2|tag3)>(?'value'.*?)</\k'name'>.

РЕДАКТИРОВАТЬ

RegEx адаптирован согласно пояснениям автора вопроса.

Другие советы

Regex для этого может быть:

/<([^>]+)>([^<]+)<\/\1>/

Но это в общих чертах, поскольку я мало что знаю о механизме побега .NET.Чтобы перевести это:

  • первая группа соответствует имени первого тега между < и >
  • вторая группа соответствует содержимому (от > до следующего <
  • конечная проверка, закрыт ли первый тег

ХТХ

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

...some html content <b> etc </b> ...
<user> hello <b>mitch</b> </user>
...some html content <b> etc </b> ...
<message> some html <i>message</i> <a href....>bla</a> </message>
...some html content <b> etc </b> ...

Надеюсь, теперь стало яснее.Мне нужны теги USER и MESSAGE.

Мне нужно получить два совпадения, каждое с двумя группами.Первая группа должна была дать мне имя тега (пользователя или сообщение), а вторая группа предоставить мне весь внутренний текст тега.

Являются ли данные правильным XML-файлом или они просто так выглядят?

Если это html, то Пакет гибкости HTML заслуживает изучения — это предоставляет DOM (похожий на XmlDocument), который вы можете использовать для запроса данных:

string input = @"<html>...some html content <b> etc </b> ...
<user> hello <b>mitch</b> </user>
...some html content <b> etc </b> ...
<message> some html <i>message</i> <a href....>bla</a> </message>
...some html content <b> etc </b> ...</html>";

            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(input);
            foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//user | //message"))
            {
                Console.WriteLine("{0}: {1}", node.Name, node.InnerText);
                // or node.InnerHtml to keep the formatting within the content
            }

Это выводит:

user:  hello mitch
message:  some html message bla

Если вам нужны теги форматирования, используйте .InnerHtml вместо .InnerText.

Если это xml, то для кодирования всего спектра xml лучше использовать синтаксический анализатор xml.Для XML-файла малого и среднего размера можно загрузить его в DOM, например XmlDocument, а затем запросить узлы (например, «//*»).Для огромных XML-файлов можно использовать XmlReader.

Если данным не нужно беспокоиться о полном XML-файле, то какое-нибудь простое регулярное выражение не должно быть слишком сложным...упрощенный пример (без атрибутов, без пространств имен, без вложенного XML) может быть таким:

string input = @"blah <tag1> content for tag 1 </tag1> blop
<tag2> content for tag 2 </tag2> bloop
<tag3> content for tag 3 </tag3> blip";

        const string pattern = @"<(\w+)>\s*([^<>]*)\s*</(\1)>";
        Console.WriteLine(Regex.IsMatch(input, pattern));
        foreach(Match match in Regex.Matches(input, pattern)) {
            Console.WriteLine("{0}: {1}", match.Groups[1], match.Groups[2]);
        }

Проблема заключалась в том, что люди ([^<]*), которые люди использовали для сопоставления вещей внутри тегов, соответствовали открывающему < вложенных тегов, а затем закрывающий тег вложенного тега не соответствовал внешнему тегу, и поэтому регулярное выражение не удалось.

Вот немного более надежная версия регулярного выражения Томалака, позволяющая использовать атрибуты и пробелы:

Regex tagRegex = new Regex(@"<\s*(?<tag>" + string.Join("|", tags) + @")[^>]*>(?<content>.*?)<\s*/\s*\k<tag>\s*>", RegexOptions.IgnoreCase);

Очевидно, что если вам когда-либо понадобится использовать только определенный набор тегов, вы можете заменить

string.Joing("|", tags)

с жестко запрограммированным списком тегов, разделенным трубами.

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

<user>abc<message>def</message>ghi</user>

Он будет соответствовать внешнему тегу пользователя, но не внутреннему тегу сообщения.

Он также не обрабатывает кавычки > в атрибутах, например:

<user attrib="oops>">

Это просто будет соответствовать

<user attrib="упс>

как тег и

">

будет частью содержимого тегов.

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

/<(?<name>[^>]+)>(?<value>[^<]+)</\1>/

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top