2008-12-10 18 views
20

Ich bin auf der Suche nach einer Regex-Anweisung, mit der ich den HTML-Inhalt nur zwischen den Body-Tags aus einem XHTML-Dokument extrahieren kann.Regulärer Ausdruck zum Extrahieren von HTML-Body-Inhalt

Das XHTML, das ich analysieren muss, werden sehr einfache Dateien sein, ich muss mich zum Beispiel nicht um JavaScript-Inhalt oder <![CDATA[ Tags kümmern.

Unten ist die erwartete Struktur der HTML-Datei, die ich analysieren muss. Da ich genau den gesamten Inhalt der HTML-Dateien kenne, mit denen ich arbeiten muss, deckt dieses HTML-Snippet ziemlich genau meinen gesamten Anwendungsfall ab. Wenn ich eine Regex bekommen kann, um den Körper dieses Beispiels zu extrahieren, werde ich glücklich sein.

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

Konzeptionell Ich habe versucht, eine Regex Zeichenfolge zu bauen, die alles, aber den inneren Körpergehalt entspricht. Mit diesem würde ich die C# Regex.Split() Methode verwenden, um den Körperinhalt zu erhalten. Ich dachte, diese Regex:

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

... würde es tun, aber es scheint nicht überhaupt mit meinen Testinhalten in RegexBuddy zu arbeiten.

+0

'Split()' ist das falsche Werkzeug für diesen Job. Verwenden Sie einfach 'Regex.Match (Betreff) '(? S) ] *> (. *)") .Gruppen [1] .Wert ". –

Antwort

23

Würde das funktionieren?

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

Natürlich müssen Sie die notwendigen \s hinzuzufügen, um zu berücksichtigen < body ...> (Element mit Leerzeichen) zu nehmen, wie in:

Am zweiten Gedanken, ich bin nicht sicher, warum ich brauchte eine negative Vorausschau ...Dies soll auch arbeiten (für ein wohlgeformtes XHTML-Dokument):

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

Zweite war der Trick für mich. Vielen Dank. –

+0

Mmm, sieht aus wie ein guter Fall für die Demonstration von REs sollte nicht gegen (unbekannte) HTML verwendet werden: ist gültig ... :-) – PhiLho

+0

PhiLho, du bist falsch, es ist kein gültiges XHTML. ">" muss als ">" als XML-well-formed ausgegeben werden. Webbrowser verwenden jedoch verschiedene Hacks, um fehlerhaftes HTML/XHTML zu lesen. Seiten mit JavaScript-Inhalt sind normalerweise nicht gut formatiert, wenn sie nicht in CDATA eingefügt werden. –

9

XHTML würde leichter mit einem XML-Parser als mit einer Regex geparst werden. Ich weiß, dass es nicht das ist, was du fragst, aber ein XML-Parser wäre in der Lage, schnell zum Body-Knoten zu navigieren und dir seinen Inhalt zurück zu geben, ohne irgendwelche Tag-Mapping-Probleme, die dir die Regex gibt.

EDIT: Als Antwort auf einen Kommentar hier; dass ein XML-Parser zu langsam ist.

Es gibt zwei Arten von XML-Parser, einer namens DOM ist groß und schwer und einfach und freundlich, es baut einen Baum aus dem Dokument, bevor Sie etwas tun können. Die andere heißt SAX und ist schnell und leicht und mehr Arbeit, liest sie die Datei sequentiell. Sie möchten, dass SAX das Body-Tag findet.

Die DOM-Methode ist gut für mehrere Anwendungen, ziehen Tags und finden, wer ist was Kind. Der SAX-Parser liest die Datei in der Reihenfolge durch und qill erhält schnell die Informationen, nach denen Sie suchen. Der Regex wird nicht schneller als ein SAX-Parser sein, da beide einfach über die Datei- und Musterübereinstimmung laufen, mit der Ausnahme, dass die Regex nicht aufhört, nach einem Body-Tag zu suchen, weil Regex nicht eingebaut ist Kenntnis von XML. In der Tat verwendet Ihr SAX-Parser wahrscheinlich kleine Regex-Elemente, um jedes Tag zu finden.

+4

Kein Grund, das Rad neu zu erfinden. Wenn es XHTML ist, ist es XML und ein XML-Parser ist das Werkzeug für den Job. +1 –

+0

Dies war die erste Lösung, die ich müde, aber es schien ziemlich langsam zu laufen. Ich dachte, RegEx wäre schneller. –

+1

Es gibt zwei Arten von XML-Parsern. Einer namens DOM ist groß und schwer und einfach und freundlich. Er erstellt einen Baum aus dem Dokument, bevor Sie etwas tun können. Die andere heißt SAX und ist schnell und leicht und mehr Arbeit, liest sie die Datei sequentiell. Sie möchten, dass SAX das Body-Tag findet. – Karl

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

mit ersetzen

\1 
+0

Dies sollte das gesamte Dokument entsprechen und den Körper in \ 3. Sie wissen also, wenn es nicht mit dem gesamten Dokument übereinstimmt, dass die Formatierung des aktuellen Dokuments etwas anderes berücksichtigt, und Sie können einen Fehler ausgeben. – Kev

+0

Ich weiß, es ist ein sehr alter Post aber dang .. Ich mag diese Antwort und musste es bekannt geben. – stefgosselin

+0

Danke, steggosselin :) – Kev

3

Warum können Sie nicht teilen Sie es nur von

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

und Nimm die zweite Saite? Ich glaube, es wird viel schneller sein, als nach einem riesigen Regexp zu suchen.

+0

Weil sein anfänglicher Body-Tag ein Attribut hat ... – Kev

+0

Das heißt, wenn Sie beheben, dass Ihre Vorgehensweise einfacher sein kann. :) – Kev

+0

Nun, ich habe es gerade bemerkt, bevor Sie den Kommentar gepostet und diese Antwort bearbeitet: 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

Perfekt! Danke dafür! – Jef

1

Spiel der erste Body-Tag: <\s*body.*?>

Spiel der letzte Körper tag: <\s*/\s*body.*?>

(Anmerkung: wir machen Räume in der Mitte der Tags, die btw vollständig gültig Markup)

Kombinieren Sie sie so und Sie erhalten alles dazwischen, einschließlich der Körper-Tags: <\s*body.*?>.*?<\s*/\s*body.*?>. Und stellen Sie sicher, dass Sie den Singleline Modus verwenden, der Zeilenumbrüche ignoriert.

Dies funktioniert in VB.NET, und hoffentlich auch andere!

Verwandte Themen