2008-12-10 36 views
20

Estoy buscando una declaración de expresiones regulares que me permita extraer el contenido HTML de solo entre las etiquetas de cuerpo de un documento XHTML.Expresión regular para extraer contenido de cuerpo HTML

Los XHTML que necesito analizar son archivos muy simples, no tengo que preocuparme por el contenido de JavaScript o las etiquetas <![CDATA[, por ejemplo.

A continuación se muestra la estructura esperada del archivo HTML que tengo que analizar. Como sé exactamente todo el contenido de los archivos HTML con los que voy a tener que trabajar, este fragmento de HTML cubre prácticamente todo mi caso de uso. Si puedo obtener una expresión regular para extraer el cuerpo de este ejemplo, seré feliz.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
    <title> 
    </title> 
    </head> 
    <body contenteditable="true"> 
    <p> 
     Example paragraph content 
    </p> 
    <p> 
     &nbsp; 
    </p> 
    <p> 
     <br /> 
     &nbsp; 
    </p> 
    <h1>Header 1</h1> 
    </body> 
</html> 

Conceptualmente, he estado tratando de construir una cadena de expresiones regulares que coincida con todo, PERO con el contenido del cuerpo interno. Con esto, usaría el método C# Regex.Split() para obtener el contenido del cuerpo. Pensé que esta expresión regular:

((.|\n)*<body (.)*>)|((</body>(*|\n)*) 

... que hacer el truco, pero no parece funcionar en absoluto con mi contenido de la prueba en RegexBuddy.

+0

'Split()' es la herramienta incorrecta para este trabajo. Simplemente use 'Regex.Match (subject," (? S) ] *> (. *) ") .Groups [1] .Value'. –

Respuesta

23

¿Funcionaría?

((?:.(?!<body[^>]*>))+.<body[^>]*>)|(</body\>.+) 

Por supuesto, es necesario agregar la necesaria \s con el fin de tener en cuenta < body ...> (elemento con espacios), como en:

Pensándolo bien, no estoy seguro de por qué necesitaba una mirada negativa hacia adelante ...Esto también debería funcionar (para un documento XHTML bien formado):

(.*<\s*body[^>]*>)|(<\s*/\s*body\s*\>.+) 
+0

El segundo fue el truco para mí. Gracias. –

+0

Mmm, parece un buen ejemplo para demostrar que las RE no deberían usarse contra HTML (desconocido): es válido ... :-) – PhiLho

+0

PhiLho, eres incorrecto, no es XHTML válido. ">" debe ser escapado como ">" para que tenga un formato XML. Sin embargo, los navegadores web utilizan varios hacks para leer HTML/XHTML roto. Las páginas con contenido JavaScript generalmente no están bien formadas en XML, a menos que estén en formato CDATA. –

9

XHTML sería más fácil de analizar con un analizador XML, que con una expresión regular. Sé que no es lo que estás preguntando, pero un analizador XML podría navegar rápidamente al nodo del cuerpo y devolverte su contenido sin ningún problema de asignación de etiquetas que la expresión regular te esté dando.

EDITAR: Respondiendo a un comentario aquí; que un analizador XML es demasiado lento.

Hay dos tipos de analizador XML, uno llamado DOM es grande y pesado, fácil y amigable, construye un árbol fuera del documento antes de poder hacer cualquier cosa. El otro se llama SAX y es rápido, liviano y con más trabajo, lee el archivo secuencialmente. Querrá que SAX encuentre la etiqueta de cuerpo.

El método DOM es bueno para múltiples usos, tirando etiquetas y descubriendo quién es el niño. El analizador SAX lee el archivo en orden y rápidamente obtendrá la información que está buscando. El Regex no será más rápido que un analizador SAX, ya que ambos simplemente cruzan el archivo y coinciden con el patrón, con la excepción de que la expresión regular no dejará de buscar una etiqueta corporal, porque la expresión regular no tiene incorporado conocimiento de XML. De hecho, su analizador SAX probablemente use pequeños fragmentos de expresiones regulares para encontrar cada etiqueta.

+4

No hay razón para reinventar la rueda. Si es XHTML, es XML, y un analizador XML es la herramienta para el trabajo. +1 –

+0

Esta fue la primera solución que caí, pero parecía estar funcionando bastante lento. Pensé que RegEx sería más rápido. –

+1

Hay dos tipos de analizador XML, uno llamado DOM es grande y pesado, fácil y amigable, construye un árbol fuera del documento antes de poder hacer cualquier cosa. El otro se llama SAX y es rápido, liviano y con más trabajo, lee el archivo secuencialmente. Querrá que SAX encuentre la etiqueta de cuerpo. – Karl

3
/<body[^>]*>(.*)</body>/s 

reemplazar con

\1 
+0

Esto debe coincidir con el documento completo y colocar el cuerpo en \ 3. Entonces, si no coincide con todo el documento, el formato del documento actual tiene algo más que considerar y puede generar un error. – Kev

+0

Sé que es una publicación muy antigua, pero dang .. Me gusta esta respuesta y tuve que dejarla saber. – stefgosselin

+0

Gracias, stefgosselin :) – Kev

3

Por qué no puedes simplemente dividirlo por

</{0,1}body[^>]*> 

y tomar la segunda cuerda? Creo que será mucho más rápido que buscar una enorme expresión regular.

+0

Porque su etiqueta corporal inicial tiene un atributo ... – Kev

+0

Dicho esto, si lo soluciona, su enfoque puede ser más simple. :) – Kev

+0

Bueno, acabo de notarlo antes de publicar el comentario y edité esta respuesta: P – bezmax

5
String toMatch="aaaaaaaaaaabcxx sldjfkvnlkfd <body>i m avinash</body>"; 
Pattern pattern=Pattern.compile(".*?<body.*?>(.*?)</body>.*?"); 
Matcher matcher=pattern.matcher(toMatch); 
if(matcher.matches()) { 
    System.out.println(matcher.group(1)); 
} 
+0

¡Perfecto! ¡Gracias por esto! – Jef

1

de ajuste de la primera etiqueta del cuerpo: <\s*body.*?>

de ajuste de la última etiqueta del cuerpo: <\s*/\s*body.*?>

(nota: nos cuenta los espacios en el medio de las etiquetas, lo cual es completamente marcado válido por cierto)

Combínalos juntos así y obtendrás todo lo que esté entre ellos, incluidas las etiquetas de cuerpo: <\s*body.*?>.*?<\s*/\s*body.*?>. Y asegúrese de estar utilizando el modo Singleline que ignorará los saltos de línea.

Esto funciona en VB.NET, y espero que otros también!

Cuestiones relacionadas