Elimine las etiquetas HTML de la cadena, incluido & nbsp en C #

83

¿Cómo puedo eliminar todas las etiquetas HTML, incluidas & nbsp, usando expresiones regulares en C #? Mi cuerda parece

  "<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>"
rampuriyaaa
fuente
9
No use una expresión regular, consulte el HTML Agility Pack. stackoverflow.com/questions/846994/how-to-use-html-agility-pack
Tim
Gracias Tim, pero la aplicación es bastante grande e intacta, agregar o descargar un paquete de agilidad html no funcionará.
rampuriyaaa

Respuestas:

196

Si no puede utilizar una solución orientada al analizador HTML para filtrar las etiquetas, aquí tiene una expresión regular simple.

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

Idealmente, debería hacer otra pasada a través de un filtro de expresiones regulares que se encarga de varios espacios como

string noHTMLNormalised = Regex.Replace(noHTML, @"\s{2,}", " ");
Ravi Thapliyal
fuente
Todavía no lo he probado tanto como lo necesito, pero funcionó mejor de lo que esperaba. Publicaré el método que escribí a continuación.
Don Rolling
Una coincidencia perezosa ( <[^>]+?>según @David S.) podría hacer esto un poco más rápido, pero solo usé esta solución en un proyecto en vivo, muy feliz +1 :)
Gone Coding
Regex.Replace (inputHTML, @ "<[^>] +> | & nbsp | \ n;", "") .Trim (); \ n no se eliminará
Mahesh Malpani
3
Recomendaría agregar un espacio en lugar de una cadena vacía, estamos capturando espacios adicionales de cualquier maneraRegex.Replace(inputHTML, @"<[^>]+>|&nbsp;", " ")
Tauseef
2
@Tauseef Si usa un espacio en la primera llamada de reemplazo, puede terminar dejando espacios donde no había ninguno en la entrada original. Digamos que recibe Sound<b>Cloud</b>como entrada; terminará con Sound Cloudlo que debería haber sido eliminado SoundCloudporque así es como se muestra en HTML.
Ravi Thapliyal
31

Tomé el código de @Ravi Thapliyal e hice un método: es simple y puede que no limpie todo, pero hasta ahora está haciendo lo que necesito que haga.

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

He estado usando esta función por un tiempo. Elimina prácticamente cualquier html desordenado que puedas lanzar y deja el texto intacto.

        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();
        }
David S.
fuente
Solo para confirmar: la función SingleSpacedTrim () hace lo mismo que string noHTMLNormalised = Regex.Replace (noHTML, @ "\ s {2,}", ""); de la respuesta de Ravi Thapliyal?
Jimmy
@Jimmy, por lo que puedo ver, esa expresión regular no captura pestañas individuales o líneas nuevas como lo hace SingleSpacedTrim (). Sin embargo, ese podría ser un efecto deseable, en ese caso simplemente elimine los casos según sea necesario.
David S.
Bien, pero parece que reemplaza las comillas simples y dobles con espacios en blanco también, aunque no están en la lista " notOkCharacter ", ¿o me falta algo allí? ¿Esta parte de los métodos de decodificación / codificación se llama al principio? ¿Qué sería necesario para mantener intactos a estos personajes?
vm370
4
var noHtml = Regex.Replace(inputHTML, @"<[^>]*(>|$)|&nbsp;|&zwnj;|&raquo;|&laquo;", string.Empty).Trim();
MRP
fuente
1

He usado el código de @RaviThapliyal y @Don Rolling, pero hice una pequeña modificación. Ya que estamos reemplazando & nbsp con una cadena vacía, pero en su lugar & nbsp debería reemplazarse con un espacio, agregamos un paso adicional. Me funcionó a las mil maravillas.

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;
}

Se usó & nbps sin punto y coma porque el Stack Overflow lo estaba formateando.

Sabique A Khan
fuente
0

esta:

(<.+?> | &nbsp;)

coincidirá con cualquier etiqueta o &nbsp;

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

entonces x = hello

Jonesopolis
fuente
0

La desinfección de un documento Html implica muchas cosas complicadas. Este paquete puede ser de ayuda: https://github.com/mganss/HtmlSanitizer

Ehsan88
fuente
Creo que es más contra los ataques XSS que normalizar html
Revious
1
@Revious Creo que tienes razón. Tal vez mi respuesta no esté relacionada mucho con la pregunta del OP, ya que no mencionaron el propósito de eliminar las etiquetas html. Pero si el propósito es prevenir ataques, como sucede en muchos casos, entonces usar un desinfectante ya desarrollado puede ser un mejor enfoque. Por cierto, no tengo conocimiento sobre cuál es el significado de normalizar html .
Ehsan88
0

HTML está en su forma básica solo XML. Puede analizar su texto en un objeto XmlDocument y, en el elemento raíz, llamar a InnerText para extraer el texto. Esto eliminará todas las etiquetas HTML en cualquier forma y también tratará con caracteres especiales como & lt; & nbsp; todo de una vez.

nivs1978
fuente