2008-10-14 8 views
1

Voici l'entrée (html, xml pas):Regex pour les balises specifig et leur contenu, par le nom groupped tag

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

Je voudrais obtenir 3 matchs, chacun avec deux groupes. Le premier groupe contiendrait le nom de l'étiquette et le deuxième groupe contiendrait le texte interne de l'étiquette. Il n'y a que ces trois balises, il n'a donc pas besoin d'être universel.

En d'autres termes:

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

Toutes les idées?

+0

Notez l'exemple HtmlAgilityPack mis à jour; Je suppose que cela fait ce dont vous avez besoin. –

Répondre

1

Je ne vois pas pourquoi vous voulez utiliser les noms de groupes de correspondance pour cela.

Voici une expression régulière qui correspondrait nom de la balise et le contenu des balises dans les matchs sous numérotés.

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

Voici une variante avec.Les noms de groupe de style NET

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

EDIT

RegEx adaptée selon la clarification de la question auteur.

+0

Tomalak, c'est génial! Fonctionne parfaitement, exactement ce dont j'avais besoin. J'ai essayé de t'équiper, mais je vais devoir t'inscrire. J'ai aussi essayé d'accepter la réponse mais rien ne se passe. – mitch

+0

Vous êtes les bienvenus de toute façon. ;-) Mais vous êtes invités à vous inscrire et à accepter la réponse, si vous voulez retourner la faveur. – Tomalak

+0

Je vais - promettre. – mitch

1

Est-ce que les données xml bon, ou faut-il regarder comme elle?

S'il est html, le HTML Agility Pack est une enquête vaut - il fournit un DOM (similaire à XmlDocument) que vous pouvez utiliser pour interroger les données:

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 
      } 

Ce sorties:

user: hello mitch 
message: some html message bla 

Si vous voulez les balises de formatage, utilisez .InnerHtml au lieu de .InnerText.

Si elle est xml, puis à coder avec le spectre complet de XML, il serait préférable d'utiliser un analyseur XML. Pour les petits à mi taille xml, le charger dans un DOM, comme XmlDocument serait bien - alors interroger les noeuds (par exemple, « // * »). Pour un énorme xml, XmlReader peut être une option.

Si les données ne doit pas se soucier du xml complète, puis une regex simple, ne devrait pas être trop difficile ... un exemple simplifié (pas d'attributs, pas, pas d'espaces de noms XML imbriqué) pourrait être:

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

Les données ne sont pas valides en XML, mais en HTML. – mitch

+0

Je vais mettre à jour pour mentionner HTML Agility Pack –

+0

Cela semble très intéressant, je vais vérifier, tnx. – mitch

0

Regex pour cela pourrait être:

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

Mais il est en général que je ne sais pas grand-chose au sujet de la machanism échapper de .NET. Pour traduire:

  • premier groupe correspond au premier nom de la balise entre < et>
  • deuxième groupe correspond au contenu (de> à la prochaine <
  • la vérification finale si la première balise est fermée

HTH

+0

Je l'ai essayé, mais ça ne correspond à rien. – mitch

+0

Notez que, en raison de la classe de caractères [^ <] pour le contenu de la balise, cela échouera sur les balises imbriquées. . *? serait nécessaire si les balises imbriquées doivent être autorisées. (Commentaire basé sur PCRE, qui peut ou peut ne pas être équivalent au moteur regex de .NET.) –

0

Cela vous donnera des groupes de capture nommés pour ce que vous voulez. Cependant, cela ne fonctionnera pas pour les balises imbriquées.

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

1

Merci à tous, mais aucun des travaux de regexes. :(Peut-être que je ne suis pas assez précis, désolé pour ce qui est ici le html exact je suis en train d'analyser...

...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> ... 

J'espère que ce sera plus clair maintenant, je suis après balises USER et MESSAGE

J'ai besoin d'obtenir deux correspondances, chacune avec deux groupes.Le premier groupe devrait me donner le nom de l'étiquette (utilisateur ou message) et le deuxième groupe me donnerait le texte interne entier de l'étiquette

+0

J'ai apporté quelques modifications à ma réponse, veuillez réessayer! – Tomalak

+0

Ce n'est pas HTML ... Pas avec DTD standard de toute façon. – PhiLho

1

Le problème était que ([^ <] *) les personnes utilisaient pour faire correspondre les choses à l'intérieur des balises étaient correspondant à l'ouverture < des balises imbriquées, puis la balise de fermeture de l'étiquette imbriquée d idn ne correspond pas à la balise externe et donc l'expression rationnelle a échoué.

Voici une version légèrement plus robuste de regex de Tomalak permettant pour les attributs et les espaces:

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

Il est évident que si vous allez seulement jamais besoin d'utiliser un ensemble de balises que vous pouvez remplacer le

string.Joing("|", tags) 

avec la liste d'étiquettes séparées par un code dur.

Limites de la regex sont que si vous avez un tag que vous essayez de correspondre imbriqué dans un autre, il ne correspondra que l'étiquette externe. à savoir

< utilisateur> abc < message> def </message> GHI </utilisateur>

Il correspondra à la balise utilisateur externe, mais pas l'étiquette de message intérieur.

Il ne gère pas aussi> est cité dans les attributs comme ceci:

< utilisateur attrib = "oops>">

Il suffit de faire correspondre

< utilisateur attrib = "oops>

comme l'étiquette et le

« >

sera une partie du contenu des balises.

Questions connexes