web-dev-qa-db-fra.com

Utilisation d'expressions régulières C # pour supprimer les balises HTML

Comment utiliser l'expression régulière C # pour remplacer/supprimer toutes les balises HTML, y compris les crochets? Quelqu'un peut-il m'aider s'il vous plaît avec le code?

136
Steve

Comme souvent indiqué auparavant, vous ne devez pas utiliser d'expressions régulières pour traiter des documents XML ou HTML. Ils ne fonctionnent pas très bien avec les documents HTML et XML, car il n’existe aucun moyen d’exprimer des structures imbriquées de manière générale.

Vous pouvez utiliser ce qui suit.

String result = Regex.Replace(htmlDocument, @"<[^>]*>", String.Empty);

Cela fonctionnera dans la plupart des cas, mais il y aura des cas (par exemple, CDATA contenant des équerres) où cela ne fonctionnera pas comme prévu.

148
Daniel Brückner

La bonne réponse est de ne pas le faire, utilisez le HTML Agility Pack .

Édité pour ajouter:

Pour voler sans vergogne le commentaire ci-dessous de jesse et pour ne pas être accusé de ne pas avoir répondu correctement à la question après tout ce temps, voici un extrait simple et fiable qui utilise HTML Agility Pack et qui fonctionne avec les éléments HTML les plus imparfaitement formés et capricieux:

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(Properties.Resources.HtmlContents);
var text = doc.DocumentNode.SelectNodes("//body//text()").Select(node => node.InnerText);
StringBuilder output = new StringBuilder();
foreach (string line in text)
{
   output.AppendLine(line);
}
string textOnly = HttpUtility.HtmlDecode(output.ToString());

Il existe très peu de cas défendables d'utilisation d'une expression régulière pour l'analyse HTML, car HTML ne peut être analysé correctement sans une prise en compte du contexte qu'il est très pénible de fournir, même dans un moteur regex non traditionnel. Vous pouvez obtenir une partie du chemin avec un RegEx, mais vous devrez faire des vérifications manuelles.

Html Agility Pack peut vous fournir une solution robuste qui réduira le besoin de corriger manuellement les aberrations pouvant résulter du traitement naïf de HTML en tant que grammaire sans contexte.

Une expression régulière peut vous donner la plupart du temps ce que vous voulez, mais elle échouera dans des cas très courants. Si vous pouvez trouver un analyseur syntaxique meilleur/plus rapide que HTML Agility Pack, allez-y, mais s'il vous plait, ne soumettez pas le monde à un piratage HTML plus brisé.

78
JasonTrue

La question est trop vaste pour qu'on y réponde définitivement. Parlez-vous de supprimer toutes les balises d'un document HTML du monde réel, comme une page Web? Si oui, vous devriez:

  • supprime la déclaration <! DOCTYPE ou le prologue <? xml s'ils existent
  • supprimer tous les commentaires SGML
  • supprimer tout l'élément HEAD
  • supprime tous les éléments SCRIPT et STYLE
  • faire Grabthar-sait-quoi avec les éléments FORM et TABLE
  • enlever les étiquettes restantes
  • supprime les séquences <! [CDATA [et]]> des sections CDATA mais laisse leur contenu seul

C'est juste une idée en tête - je suis sûr qu'il y a plus. Une fois que vous avez fait tout cela, vous allez vous retrouver avec des mots, des phrases et des paragraphes qui vont ensemble à certains endroits et de gros morceaux d’espaces blancs inutiles dans d’autres.

Mais, en supposant que vous travaillez avec un fragment et que vous puissiez vous en sortir en supprimant simplement toutes les balises, voici la regex que j'utiliserais:

@"(?></?\w+)(?>(?:[^>'""]+|'[^']*'|""[^""]*"")*)>"

Faire correspondre les chaînes à guillemets simples et à guillemets doubles dans leurs propres alternatives est suffisant pour traiter le problème des chevrons entre parenthèses dans les valeurs d'attribut. Je ne vois pas la nécessité de faire explicitement correspondre les noms d'attributs et d'autres éléments à l'intérieur de la balise, comme le fait la regex dans la réponse de Ryan; la première alternative gère tout cela.

Si vous vous interrogez sur ces constructions (?>...), elles sont groupes atomiques . Ils rendent la regex un peu plus efficace, mais plus important encore, ils évitent les retours arrière fulgurants, ce que vous devez toujours faire attention lorsque vous mélangez des quantificateurs alternés et imbriqués, comme je l'ai fait auparavant. Je ne pense pas vraiment que ce serait un problème ici, mais je sais que si je ne le mentionne pas, quelqu'un d'autre le fera. ;-)

Cette expression rationnelle n'est pas parfaite, bien sûr, mais elle est probablement aussi efficace que nécessaire.

37
Alan Moore
Regex regex = new Regex(@"</?\w+((\s+\w+(\s*=\s*(?:"".*?""|'.*?'|[^'"">\s]+))?)+\s*|\s*)/?>", RegexOptions.Singleline);

Source

25
Ryan Emerle

@JasonTrue est correct, la suppression des balises HTML ne doit pas être effectuée via des expressions régulières.

Il est assez simple de supprimer les balises HTML avec HtmlAgilityPack:

public string StripTags(string input) {
    var doc = new HtmlDocument();
    doc.LoadHtml(input ?? "");
    return doc.DocumentNode.InnerText;
}
17
zzzzBov

Je voudrais faire écho à la réponse de Jason, même si parfois vous devez analyser naïvement du HTML et extraire le contenu du texte.

J'avais besoin de faire cela avec du HTML créé par un éditeur de texte riche, toujours amusant et amusant.

Dans ce cas, vous devrez peut-être supprimer le contenu de certaines balises, ainsi que les balises elles-mêmes.

Dans mon cas, les tags ont été jetés dans ce mélange. Certains trouveront peut-être que ma mise en œuvre (très légèrement) moins naïve est un point de départ utile.

   /// <summary>
    /// Removes all html tags from string and leaves only plain text
    /// Removes content of <xml></xml> and <style></style> tags as aim to get text content not markup /meta data.
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public static string HtmlStrip(this string input)
    {
        input = Regex.Replace(input, "<style>(.|\n)*?</style>",string.Empty);
        input = Regex.Replace(input, @"<xml>(.|\n)*?</xml>", string.Empty); // remove all <xml></xml> tags and anything inbetween.  
        return Regex.Replace(input, @"<(.|\n)*?>", string.Empty); // remove any tags but not there content "<p>bob<span> johnson</span></p>" becomes "bob johnson"
    }
13
CountZero

essayez la méthode d'expression régulière à cette adresse URL: http://www.dotnetperls.com/remove-html-tags

/// <summary>
/// Remove HTML from string with Regex.
/// </summary>
public static string StripTagsRegex(string source)
{
return Regex.Replace(source, "<.*?>", string.Empty);
}

/// <summary>
/// Compiled regular expression for performance.
/// </summary>
static Regex _htmlRegex = new Regex("<.*?>", RegexOptions.Compiled);

/// <summary>
/// Remove HTML from string with compiled Regex.
/// </summary>
public static string StripTagsRegexCompiled(string source)
{
return _htmlRegex.Replace(source, string.Empty);
}
5
Owidat

utilisez ceci..

@"(?></?\w+)(?>(?:[^>'""]+|'[^']*'|""[^""]*"")*)>"
3
Swaroop

Ajoutez .+? dans <[^>]*> et essayez cette regex (base sur this ):

<[^>].+?>

c # .net démo regexenter image description here

2
GRUNGER