タグ名でグループ化された特定のタグとそのコンテンツの正規表現
質問
入力は次のとおりです(xmlではなくhtml):
... html content ...
<tag1> content for tag 1 </tag1>
<tag2> content for tag 2 </tag2>
<tag3> content for tag 3 </tag3>
... html content ...
それぞれ2つのグループを持つ3つのマッチを取得したい。最初のグループにはタグの名前が含まれ、2番目のグループにはタグの内部テキストが含まれます。これらの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。
他のヒント
このための正規表現は次のようになります。
/<([^>]+)>([^<]+)<\/\1>/
しかし、.NETのエスケープメカニズムについてはあまり知らないので一般的です。翻訳するには:
- 最初のグループは、<!> ltの間の最初のタグの名前と一致します。および<!> gt;
- 2番目のグループはコンテンツと一致します(<!> gt;から次の<!> lt;
- 最初のタグが閉じているかどうかの終了チェック
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タグを探しています。
それぞれ2つのグループを持つ2つの一致を取得する必要があります。最初のグループはタグ名(ユーザーまたはメッセージ)を提供し、2番目のグループはタグの内部テキスト全体を提供します。
データは適切な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
フォーマットタグが必要な場合は、.InnerTextの代わりに.InnerHtmlを使用します。
xmlの場合、xmlの全範囲を使用してコーディングするには、xmlパーサーを使用することをお勧めします。小規模から中規模のxmlの場合、XmlDocumentなどのDOMに読み込むと問題ありません。次に、ノードを照会します(たとえば、<!> quot; // * <!> quot;)。巨大な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]);
}
問題は、([^ <!> lt;] *)人々がタグ内の項目を一致させるために使用していたことで、開始<!> lt;と一致していました。ネストされたタグの終了タグ、およびネストされたタグの終了タグが外側のタグと一致しなかったため、正規表現が失敗しました。
これは、属性と空白を許可するTomalakの正規表現のもう少し堅牢なバージョンです。
Regex tagRegex = new Regex(@"<\s*(?<tag>" + string.Join("|", tags) + @")[^>]*>(?<content>.*?)<\s*/\s*\k<tag>\s*>", RegexOptions.IgnoreCase);
明らかに、特定のタグセットのみを使用する必要がある場合は、置き換えることができます
string.Joing("|", tags)
タグのハードコードされたパイプ区切りリスト付き。
正規表現の制限は、1つのタグが別のタグ内にネストしようとする場合、外側のタグのみと一致することです。すなわち
<!> lt; user <!> gt; abc <!> lt; message <!> gt; def <!> lt; / message <!> gt; ghi <!> lt; / user <!> gt;
外側のユーザータグには一致しますが、内側のメッセージタグには一致しません。
また、次のような属性で引用されている<!> gt;を処理しません。
<!> lt; user attrib = <!> quot; oops <!> gt; <!> quot; <!> gt;
一致します
<!> lt; user attrib = <!> quot; oops <!> gt;
タグとして、
<!> quot; <!> gt;
はタグコンテンツの一部になります。
これにより、必要な名前のキャプチャグループが作成されます。ただし、ネストされたタグでは機能しません。
/<(?<name>[^>]+)>(?<value>[^<]+)</\1>/