Regex,用于指定标记及其内容,按标记名称分组

本文关键字:用于 Regex | 更新日期: 2023-09-27 17:47:25

这里是输入(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"

有什么想法吗?

Regex,用于指定标记及其内容,按标记名称分组

我不明白为什么要使用匹配组名称。

下面是一个正则表达式,它将标记名称和标记内容匹配为编号的子匹配。

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

这是一个带有的变体。NET样式组名称

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

编辑

RegEx根据问题作者的澄清进行了调整。

Regex可能是:

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

但这是一般性的,因为我对逃避的男子主义了解不多。NET。翻译:

  • 第一组在<和>
  • 第二组匹配内容(从>到下一<
  • 结束检查第一个标签是否关闭

HTH

感谢所有正则表达式,但没有一个有效。:(也许我不够具体,很抱歉。以下是我试图解析的确切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标签。

我需要两场比赛,每场有两组。第一组wp会给我标签名称(用户或消息),第二组wp则会给我整个标签内部文本。

数据是正确的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,那么一些简单的regex应该不会太棘手。。。一个简化的例子(没有属性,没有名称空间,没有嵌套的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失败。

下面是Tomalak正则表达式的一个稍微健壮一点的版本,允许使用属性和空白:

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

显然,如果你只需要使用一组特定的标签,你可以更换

string.Joing("|", tags)

带有硬编码管道分离标签列表。

正则表达式的局限性在于,如果您有一个试图匹配的标签嵌套在另一个标签中,它将只匹配外部标签。即

<user>abc<消息>def<message>ghi<用户>

它将匹配外部用户标记,但不匹配内部消息标记。

它也不处理属性中引用的>:

<user attrib="oops>">

它将刚好匹配

<user attrib="oops>

作为标签和

">

将是标签内容的一部分。

这将为您提供所需的命名捕获组。但是,它不适用于嵌套标记。

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