Verwenden von regulären C # -Ausdrücken zum Entfernen von HTML-Tags
139
Wie verwende ich den regulären C # -Ausdruck, um alle HTML-Tags einschließlich der spitzen Klammern zu ersetzen / zu entfernen? Kann mir bitte jemand mit dem Code helfen?
Sie geben es nicht an, aber ich schließe daraus, dass Sie auch Skript- und Stilelemente vollständig entfernen und nicht nur das Tag entfernen möchten. Die Antwort auf das HTML Agility Pack unten ist korrekt, um die Tags zu entfernen. Um jedoch Skript und Stil zu entfernen, benötigen Sie auch etwas wie stackoverflow.com/questions/13441470/…
John
1
Die als Duplikat angegebene Frage enthält viele Informationen (und Tony the Pony!), Es wurde jedoch nur nach dem Öffnen von Tags gefragt, nicht nach allen Tags. Ich bin mir also nicht sicher, ob es technisch gesehen ein Duplikat ist. Die Antwort ist jedoch dieselbe: nicht.
Goodeye
Antworten:
154
Wie bereits erwähnt, sollten Sie keine regulären Ausdrücke verwenden, um XML- oder HTML-Dokumente zu verarbeiten. Sie funktionieren mit HTML- und XML-Dokumenten nicht sehr gut, da verschachtelte Strukturen nicht allgemein ausgedrückt werden können.
Sie könnten Folgendes verwenden.
String result =Regex.Replace(htmlDocument,@"<[^>]*>",String.Empty);
Dies funktioniert in den meisten Fällen, aber es gibt Fälle (z. B. CDATA mit spitzen Klammern), in denen dies nicht wie erwartet funktioniert.
Dies ist eine naive Implementierung. Das heißt, <div id = "x <4>"> ist leider gültiges HTML. Behandelt die meisten vernünftigen Fälle ..
Ryan Emerle
8
Wie bereits erwähnt, ist mir bewusst, dass dieser Ausdruck in einigen Fällen fehlschlagen wird. Ich bin mir nicht einmal sicher, ob der allgemeine Fall durch einen regulären Ausdruck ohne Fehler behandelt werden kann.
Daniel Brückner
1
Nein, das wird in allen Fällen fehlschlagen! es ist gierig.
Jake
13
@Cipher, warum denkst du, ist Gier ein Problem? Angenommen, die Übereinstimmung beginnt am Anfang eines gültigen HTML-Tags und wird niemals über das Ende dieses Tags hinausgehen. Dafür ist das [^>] da.
Alan Moore
1
@AlanMoore HTML ist keine "normale Sprache", dh Sie können nicht alles, was gültiges HTML ist, mit regulären Ausdrücken abgleichen. siehe: stackoverflow.com/questions/590747/…
Kache
78
Die richtige Antwort lautet: Tun Sie das nicht. Verwenden Sie das HTML Agility Pack .
Bearbeitet, um hinzuzufügen:
Um den Kommentar von Jesse schamlos zu stehlen und zu vermeiden, dass er nach all der Zeit beschuldigt wird, die Frage nicht ausreichend beantwortet zu haben, finden Sie hier einen einfachen, zuverlässigen Ausschnitt mit dem HTML Agility Pack, der selbst mit den unvollständig geformten, launischen HTML-Elementen funktioniert:
HtmlDocument doc =newHtmlDocument();
doc.LoadHtml(Properties.Resources.HtmlContents);var text = doc.DocumentNode.SelectNodes("//body//text()").Select(node => node.InnerText);StringBuilder output =newStringBuilder();foreach(string line in text){
output.AppendLine(line);}string textOnly =HttpUtility.HtmlDecode(output.ToString());
Es gibt nur sehr wenige vertretbare Fälle für die Verwendung eines regulären Ausdrucks zum Parsen von HTML, da HTML ohne ein Kontextbewusstsein, das selbst in einer nicht-traditionellen Regex-Engine sehr schmerzhaft ist, nicht korrekt analysiert werden kann. Sie können mit einem RegEx auf halbem Weg dorthin gelangen, müssen jedoch manuelle Überprüfungen durchführen.
Html Agility Pack bietet Ihnen eine robuste Lösung, mit der Sie die Aberrationen, die sich aus der naiven Behandlung von HTML als kontextfreie Grammatik ergeben können, nicht mehr manuell beheben müssen.
Ein regulärer Ausdruck kann Ihnen meistens das bringen, was Sie wollen, aber in sehr häufigen Fällen schlägt er fehl. Wenn Sie einen besseren / schnelleren Parser als HTML Agility Pack finden, versuchen Sie es, aber setzen Sie die Welt nicht mehr kaputtem HTML-Hackery aus.
HTML Agility Pack ist nicht die Antwort auf alles, was mit der Arbeit mit HTML zu tun hat (z. B. was ist, wenn Sie nur mit Fragmenten des HTML-Codes arbeiten möchten?!).
PropellerHead
7
Es funktioniert ziemlich gut mit HTML-Fragmenten und ist die beste Option für das im Originalposter beschriebene Szenario. Ein Regex hingegen funktioniert nur mit einem idealisierten HTML-Code und bricht mit perfekt gültigem HTML-Code, da die Grammatik von HTML nicht regelmäßig ist. Wenn er Ruby verwendet hätte, hätte ich immer noch Nokogiri oder Hpricot oder Beautifulsoup für Python vorgeschlagen. Es ist am besten, HTML wie HTML zu behandeln, nicht irgendeinen beliebigen Textstrom ohne Grammatik.
JasonTrue
1
HTML ist keine reguläre Grammatik und kann daher nicht nur mit regulären Ausdrücken analysiert werden. Sie können reguläre Ausdrücke zum Lexen verwenden, jedoch nicht zum Parsen. So einfach ist das wirklich. Linguisten hätten dem zugestimmt, bevor es überhaupt HTML gab.
JasonTrue
20
Dies ist keine Ansichtssache. Ein regulärer Ausdruck kann Ihnen meistens das bringen, was Sie wollen, aber in sehr häufigen Fällen schlägt er fehl. Wenn Sie einen besseren / schnelleren Parser als HTML Agility Pack finden, versuchen Sie es, aber setzen Sie die Welt bitte nicht mehr kaputtem HTML-Hackery aus.
JasonTrue
2
Sie können HTML-Tags nicht zuverlässig identifizieren, ohne HTML zu analysieren. Verstehst du die gesamte Grammatik für HTML? Sehen Sie sich den bösen Hack an, um "ziemlich nah" zu kommen, den andere Antworten vorschlagen, und sagen Sie mir, warum Sie das beibehalten möchten. Wenn Sie mich herabstimmen, weil ein hackiger schneller Versuch für Ihre Beispieleingabe funktioniert, wird Ihre Lösung nicht korrekt. Ich habe gelegentlich reguläre Ausdrücke verwendet, um Berichte aus HTML-Inhalten zu generieren oder um eine CSS-Referenz mithilfe eines negativen Abgleichs auf & gt; um die Wahrscheinlichkeit von Fehlern zu begrenzen, aber wir haben zusätzliche Überprüfungen durchgeführt; es war kein allgemeiner Zweck.
JasonTrue
38
Die Frage ist zu weit gefasst, um endgültig beantwortet zu werden. Sprechen Sie über das Entfernen aller Tags aus einem realen HTML-Dokument wie einer Webseite? Wenn ja, müssten Sie:
Entfernen Sie die <! DOCTYPE-Deklaration oder das <? xml-Prolog, falls vorhanden
Entfernen Sie alle SGML-Kommentare
Entfernen Sie das gesamte HEAD-Element
Entfernen Sie alle SCRIPT- und STYLE-Elemente
Mach Grabthar-weiß-was mit FORM- und TABLE-Elementen
Entfernen Sie die verbleibenden Tags
Entfernen Sie die <! [CDATA [und]]> Sequenzen aus den CDATA-Abschnitten, lassen Sie jedoch deren Inhalt in Ruhe
Das ist mir ein Rätsel - ich bin mir sicher, dass es noch mehr gibt. Wenn Sie das alles erledigt haben, werden an einigen Stellen Wörter, Sätze und Absätze zusammenlaufen und an anderen große Stücke nutzloser Leerzeichen.
Angenommen, Sie arbeiten nur mit einem Fragment und können alle Tags einfach entfernen. Hier ist der reguläre Ausdruck, den ich verwenden würde:
Das Anpassen von Zeichenfolgen in einfachen und doppelten Anführungszeichen in ihren eigenen Alternativen reicht aus, um das Problem der spitzen Klammern in Attributwerten zu lösen. Ich sehe keine Notwendigkeit, die Attributnamen und andere Dinge im Tag explizit abzugleichen, wie es der reguläre Ausdruck in Ryans Antwort tut. Die erste Alternative erledigt all das.
Falls Sie sich über diese (?>...)Konstrukte wundern , handelt es sich um Atomgruppen . Sie machen den Regex ein wenig effizienter, aber was noch wichtiger ist, sie verhindern ein außer Kontrolle geratenes Backtracking, worauf Sie immer achten sollten, wenn Sie wie ich Alternation und verschachtelte Quantifizierer mischen. Ich denke nicht wirklich, dass das hier ein Problem wäre, aber ich weiß, wenn ich es nicht erwähne, wird es jemand anderes tun. ;-);
Diese Regex ist natürlich nicht perfekt, aber wahrscheinlich so gut, wie Sie es jemals brauchen werden.
Dies ist bei weitem die beste Antwort. Sie beantworten die Frage des Posters und erklären, warum für die jeweilige Aufgabe kein regulärer Ausdruck verwendet werden sollte. Gut gemacht.
Obwohl ich etwas spät dran bin, möchte ich erwähnen, dass dies auch auf XML funktioniert, wie es von Word und anderen Office-Produkten produziert wird. Jeder, der jemals die Notwendigkeit hatte, sich mit Word xml zu befassen, sollte sich die Verwendung dieser Option ansehen, da dies sehr hilfreich ist, insbesondere wenn Sie Tags aus Inhalten entfernen müssen, für die ich sie genau benötigt habe.
Steve Pettifer
Als alles andere zu scheitern schien, rettete dieses einfache Code-Snippet den Tag. Vielen Dank!
Ted Krapf
13
Ich möchte Jasons Antwort wiederholen, obwohl Sie manchmal naiv etwas HTML analysieren und den Textinhalt herausziehen müssen.
Ich musste dies mit etwas HTML tun, das von einem Rich-Text-Editor erstellt wurde, immer Spaß und Spiel.
In diesem Fall müssen Sie möglicherweise den Inhalt einiger Tags sowie nur die Tags selbst entfernen.
In meinem Fall wurden Tags in diese Mischung geworfen. Jemand mag meine (sehr geringfügig) weniger naive Implementierung als nützlichen Ausgangspunkt betrachten.
/// <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>publicstaticstringHtmlStrip(thisstring 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. returnRegex.Replace(input,@"<(.|\n)*?>",string.Empty);// remove any tags but not there content "<p>bob<span> johnson</span></p>" becomes "bob johnson"}
Abgesehen von offensichtlichen plattformübergreifenden Problemen mit Zeilenumbrüchen ist ein ungreedy Quantifizierer langsam, wenn der Inhalt begrenzt ist. Verwenden Sie Dinge wie <xml>.*(?!</xml>)</xml>mit dem RegexOptions.SingleLineModifikator für die ersten beiden und <[^>]*>für die letzten. Die ersten können auch durch eine erfasste Abwechslung im Namen des ersten Tags und Rückverweise darauf im negativen Lookahead und im letzten Tag kombiniert werden.
/// <summary>/// Remove HTML from string with Regex./// </summary>publicstaticstringStripTagsRegex(string source){returnRegex.Replace(source,"<.*?>",string.Empty);}/// <summary>/// Compiled regular expression for performance./// </summary>staticRegex _htmlRegex =newRegex("<.*?>",RegexOptions.Compiled);/// <summary>/// Remove HTML from string with compiled Regex./// </summary>publicstaticstringStripTagsRegexCompiled(string source){return _htmlRegex.Replace(source,string.Empty);}
Antworten:
Wie bereits erwähnt, sollten Sie keine regulären Ausdrücke verwenden, um XML- oder HTML-Dokumente zu verarbeiten. Sie funktionieren mit HTML- und XML-Dokumenten nicht sehr gut, da verschachtelte Strukturen nicht allgemein ausgedrückt werden können.
Sie könnten Folgendes verwenden.
Dies funktioniert in den meisten Fällen, aber es gibt Fälle (z. B. CDATA mit spitzen Klammern), in denen dies nicht wie erwartet funktioniert.
quelle
Die richtige Antwort lautet: Tun Sie das nicht. Verwenden Sie das HTML Agility Pack .
Bearbeitet, um hinzuzufügen:
Um den Kommentar von Jesse schamlos zu stehlen und zu vermeiden, dass er nach all der Zeit beschuldigt wird, die Frage nicht ausreichend beantwortet zu haben, finden Sie hier einen einfachen, zuverlässigen Ausschnitt mit dem HTML Agility Pack, der selbst mit den unvollständig geformten, launischen HTML-Elementen funktioniert:
Es gibt nur sehr wenige vertretbare Fälle für die Verwendung eines regulären Ausdrucks zum Parsen von HTML, da HTML ohne ein Kontextbewusstsein, das selbst in einer nicht-traditionellen Regex-Engine sehr schmerzhaft ist, nicht korrekt analysiert werden kann. Sie können mit einem RegEx auf halbem Weg dorthin gelangen, müssen jedoch manuelle Überprüfungen durchführen.
Html Agility Pack bietet Ihnen eine robuste Lösung, mit der Sie die Aberrationen, die sich aus der naiven Behandlung von HTML als kontextfreie Grammatik ergeben können, nicht mehr manuell beheben müssen.
Ein regulärer Ausdruck kann Ihnen meistens das bringen, was Sie wollen, aber in sehr häufigen Fällen schlägt er fehl. Wenn Sie einen besseren / schnelleren Parser als HTML Agility Pack finden, versuchen Sie es, aber setzen Sie die Welt nicht mehr kaputtem HTML-Hackery aus.
quelle
Die Frage ist zu weit gefasst, um endgültig beantwortet zu werden. Sprechen Sie über das Entfernen aller Tags aus einem realen HTML-Dokument wie einer Webseite? Wenn ja, müssten Sie:
Das ist mir ein Rätsel - ich bin mir sicher, dass es noch mehr gibt. Wenn Sie das alles erledigt haben, werden an einigen Stellen Wörter, Sätze und Absätze zusammenlaufen und an anderen große Stücke nutzloser Leerzeichen.
Angenommen, Sie arbeiten nur mit einem Fragment und können alle Tags einfach entfernen. Hier ist der reguläre Ausdruck, den ich verwenden würde:
Das Anpassen von Zeichenfolgen in einfachen und doppelten Anführungszeichen in ihren eigenen Alternativen reicht aus, um das Problem der spitzen Klammern in Attributwerten zu lösen. Ich sehe keine Notwendigkeit, die Attributnamen und andere Dinge im Tag explizit abzugleichen, wie es der reguläre Ausdruck in Ryans Antwort tut. Die erste Alternative erledigt all das.
Falls Sie sich über diese
(?>...)
Konstrukte wundern , handelt es sich um Atomgruppen . Sie machen den Regex ein wenig effizienter, aber was noch wichtiger ist, sie verhindern ein außer Kontrolle geratenes Backtracking, worauf Sie immer achten sollten, wenn Sie wie ich Alternation und verschachtelte Quantifizierer mischen. Ich denke nicht wirklich, dass das hier ein Problem wäre, aber ich weiß, wenn ich es nicht erwähne, wird es jemand anderes tun. ;-);Diese Regex ist natürlich nicht perfekt, aber wahrscheinlich so gut, wie Sie es jemals brauchen werden.
quelle
Quelle
quelle
@JasonTrue ist richtig, dass das Entfernen von HTML-Tags nicht über reguläre Ausdrücke erfolgen sollte.
Es ist ganz einfach, HTML-Tags mit HtmlAgilityPack zu entfernen:
quelle
Ich möchte Jasons Antwort wiederholen, obwohl Sie manchmal naiv etwas HTML analysieren und den Textinhalt herausziehen müssen.
Ich musste dies mit etwas HTML tun, das von einem Rich-Text-Editor erstellt wurde, immer Spaß und Spiel.
In diesem Fall müssen Sie möglicherweise den Inhalt einiger Tags sowie nur die Tags selbst entfernen.
In meinem Fall wurden Tags in diese Mischung geworfen. Jemand mag meine (sehr geringfügig) weniger naive Implementierung als nützlichen Ausgangspunkt betrachten.
quelle
<xml>.*(?!</xml>)</xml>
mit demRegexOptions.SingleLine
Modifikator für die ersten beiden und<[^>]*>
für die letzten. Die ersten können auch durch eine erfasste Abwechslung im Namen des ersten Tags und Rückverweise darauf im negativen Lookahead und im letzten Tag kombiniert werden.Versuchen Sie es mit der Methode für reguläre Ausdrücke unter folgender URL: http://www.dotnetperls.com/remove-html-tags
quelle
benutze das..
quelle
Fügen Sie
.+?
in<[^>]*>
und versuchen , diese regex (Basis auf diese ):c # .net Regex Demo
quelle
Verwenden Sie diese Methode, um Tags zu entfernen:
quelle