Regex для определения тегов и их содержимого, сгруппированных по имени тега - PullRequest
1 голос
/ 14 октября 2008

Вот ввод (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"

Есть идеи?

Ответы [ 6 ]

1 голос
/ 14 октября 2008

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

Вот немного более надежная версия регулярного выражения Томалака с учетом атрибутов и пробелов:

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

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

string.Joing("|", tags)

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

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

а Защита ГХИ

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

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

">

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

в качестве тега и

">

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

1 голос
/ 14 октября 2008

Спасибо всем, но ни одно из регулярных выражений не работает. :( Возможно, я не был достаточно конкретен, извините за это. Вот точный 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.

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

1 голос
/ 14 октября 2008

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

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

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

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

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

EDIT

RegEx адаптировано в соответствии с уточнением автора вопроса.

1 голос
/ 14 октября 2008

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

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

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

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

HTH

1 голос
/ 14 октября 2008

Являются ли данные собственно XML или они просто выглядят так?

Если это HTML, то HTML Agility Pack заслуживает изучения - он предоставляет 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]);
        }
0 голосов
/ 14 октября 2008

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

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

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