Supprimer les balises HTML de la chaîne, y compris & nbsp en C #


83

Comment puis-je supprimer toutes les balises HTML, y compris & nbsp, à l'aide de regex en C #. Ma chaîne ressemble à

  "<div>hello</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div>"

9
N'utilisez pas de regex, consultez le pack d'agilité HTML. stackoverflow.com/questions/846994/how-to-use-html-agility-pack
Tim

Merci Tim, mais l'application est assez grande et intacte, l'ajout ou le téléchargement d'un pack d'agilité html ne fonctionnera pas.
rampuriyaaa du

Réponses:


196

Si vous ne pouvez pas utiliser une solution orientée analyseur HTML pour filtrer les balises, voici une simple expression régulière pour cela.

string noHTML = Regex.Replace(inputHTML, @"<[^>]+>|&nbsp;", "").Trim();

Vous devriez idéalement faire un autre passage à travers un filtre regex qui prend en charge plusieurs espaces comme

string noHTMLNormalised = Regex.Replace(noHTML, @"\s{2,}", " ");

Je n'ai pas encore testé cela autant que nécessaire, mais cela a mieux fonctionné que ce à quoi je m'attendais. Je posterai la méthode que j'ai écrite ci-dessous.
Don Rolling

Un match paresseux ( <[^>]+?>selon @David S.) pourrait rendre cela un peu plus rapide, mais vient d'utiliser cette solution dans un projet en direct - très heureux +1 :)
Codage parti le

Regex.Replace (inputHTML, @ "<[^>] +> | & nbsp | \ n;", "") .Trim (); \ n ne sera pas supprimé
Mahesh Malpani

3
Je recommanderais d'ajouter un espace plutôt qu'une chaîne vide, nous Regex.Replace(inputHTML, @"<[^>]+>|&nbsp;", " ")
attrapons de

2
@Tauseef Si vous utilisez un espace dans le premier appel de remplacement, vous pouvez finir par laisser des espaces là où il n'y en avait pas dans l'entrée d'origine. Disons que vous recevez Sound<b>Cloud</b>comme entrée; vous vous retrouverez Sound Cloudalors qu'il aurait dû être supprimé SoundCloudcar c'est ainsi qu'il s'affiche en HTML.
Ravi Thapliyal du

31

J'ai pris le code de @Ravi Thapliyal et créé une méthode: c'est simple et peut-être pas tout nettoyer, mais jusqu'à présent, il fait ce dont j'ai besoin.

public static string ScrubHtml(string value) {
    var step1 = Regex.Replace(value, @"<[^>]+>|&nbsp;", "").Trim();
    var step2 = Regex.Replace(step1, @"\s{2,}", " ");
    return step2;
}

16

J'utilise cette fonction depuis un moment. Supprime à peu près tout html désordonné que vous pouvez lui lancer et laisse le texte intact.

        private static readonly Regex _tags_ = new Regex(@"<[^>]+?>", RegexOptions.Multiline | RegexOptions.Compiled);

        //add characters that are should not be removed to this regex
        private static readonly Regex _notOkCharacter_ = new Regex(@"[^\w;&#@.:/\\?=|%!() -]", RegexOptions.Compiled);

        public static String UnHtml(String html)
        {
            html = HttpUtility.UrlDecode(html);
            html = HttpUtility.HtmlDecode(html);

            html = RemoveTag(html, "<!--", "-->");
            html = RemoveTag(html, "<script", "</script>");
            html = RemoveTag(html, "<style", "</style>");

            //replace matches of these regexes with space
            html = _tags_.Replace(html, " ");
            html = _notOkCharacter_.Replace(html, " ");
            html = SingleSpacedTrim(html);

            return html;
        }

        private static String RemoveTag(String html, String startTag, String endTag)
        {
            Boolean bAgain;
            do
            {
                bAgain = false;
                Int32 startTagPos = html.IndexOf(startTag, 0, StringComparison.CurrentCultureIgnoreCase);
                if (startTagPos < 0)
                    continue;
                Int32 endTagPos = html.IndexOf(endTag, startTagPos + 1, StringComparison.CurrentCultureIgnoreCase);
                if (endTagPos <= startTagPos)
                    continue;
                html = html.Remove(startTagPos, endTagPos - startTagPos + endTag.Length);
                bAgain = true;
            } while (bAgain);
            return html;
        }

        private static String SingleSpacedTrim(String inString)
        {
            StringBuilder sb = new StringBuilder();
            Boolean inBlanks = false;
            foreach (Char c in inString)
            {
                switch (c)
                {
                    case '\r':
                    case '\n':
                    case '\t':
                    case ' ':
                        if (!inBlanks)
                        {
                            inBlanks = true;
                            sb.Append(' ');
                        }   
                        continue;
                    default:
                        inBlanks = false;
                        sb.Append(c);
                        break;
                }
            }
            return sb.ToString().Trim();
        }

Juste pour confirmer: la fonction SingleSpacedTrim () fait la même chose que la chaîne noHTMLNormalised = Regex.Replace (noHTML, @ "\ s {2,}", ""); de la réponse de Ravi Thapliyal?
Jimmy

@Jimmy autant que je peux voir, cette expression régulière n'attrape pas les onglets simples ou les nouvelles lignes comme le fait SingleSpacedTrim (). Cela pourrait être un effet souhaitable, dans ce cas, supprimez simplement les cas au besoin.
David S.

Bien, mais il semble également remplacer les guillemets simples et doubles par des espaces vides, bien qu'ils ne soient pas dans la liste " notOkCharacter ", ou est-ce que je manque quelque chose? Cela fait-il partie des méthodes de décodage / d'encodage appelées au début? Que faudrait-il pour garder ces personnages intacts?
vm370

4
var noHtml = Regex.Replace(inputHTML, @"<[^>]*(>|$)|&nbsp;|&zwnj;|&raquo;|&laquo;", string.Empty).Trim();

1

J'ai utilisé le code de @RaviThapliyal & @Don Rolling mais j'ai fait une petite modification. Puisque nous remplaçons le & nbsp par une chaîne vide mais que & nbsp devrait être remplacé par un espace, nous avons donc ajouté une étape supplémentaire. Cela a fonctionné pour moi comme un charme.

public static string FormatString(string value) {
    var step1 = Regex.Replace(value, @"<[^>]+>", "").Trim();
    var step2 = Regex.Replace(step1, @"&nbsp;", " ");
    var step3 = Regex.Replace(step2, @"\s{2,}", " ");
    return step3;
}

Utilisé & nbps sans point-virgule car il était formaté par le débordement de pile.


0

ce:

(<.+?> | &nbsp;)

correspondra à n'importe quelle balise ou &nbsp;

string regex = @"(<.+?>|&nbsp;)";
var x = Regex.Replace(originalString, regex, "").Trim();

alors x = hello


0

La désinfection d'un document Html implique beaucoup de choses délicates. Ce paquet peut être utile: https://github.com/mganss/HtmlSanitizer


Je pense que c'est plus contre les attaques XSS que de normaliser html
Revious

1
@Revious, je pense que vous avez raison. Peut-être que ma réponse n'est pas beaucoup liée à la question du PO car ils n'ont pas mentionné le but de supprimer les balises html. Mais si le but est de prévenir les attaques, comme c'est souvent le cas, l'utilisation d'un désinfectant déjà développé peut être une meilleure approche. BTW, je n'ai aucune connaissance de la signification de la normalisation du HTML .
Ehsan88

0

Le HTML est dans sa forme de base juste du XML. Vous pouvez analyser votre texte dans un objet XmlDocument et, sur l'élément racine, appeler InnerText pour extraire le texte. Cela supprimera tous les tages HTML sous n'importe quelle forme et traitera également les caractères spéciaux comme & lt; & nbsp; tout en une seule fois.


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.