2009-06-09 16 views
10

Ich bin auf der Suche nach einer schnellen Möglichkeit, HTML-Tags aus einer ColdFusion-Zeichenfolge zu analysieren. Wir ziehen einen RSS-Feed ein, der potenziell etwas enthalten könnte. Wir machen dann etwas Manipulation der Information und spucken es dann an einen anderen Ort zurück. Derzeit tun wir dies mit einem regulären Ausdruck. Gibt es einen besseren Weg, dies zu tun?Wie kann ich HTML-Tags aus einer ColdFusion-Zeichenfolge entfernen?

<cfloop from="1" to="#ArrayLen(myFeed.item)#" index="i"> 
    <cfset myFeed.item[i].description.value = 
    REReplaceNoCase(myFeed.item[i].description.value, '<(.|\n)*?>', '', 'ALL')> 
</cfloop> 

Wir Coldfusion verwenden 8.

Antwort

14

Haftungsausschluss Ich bin ein harter Verfechter der einen geeigneten Parser (statt regex) HTML zu analysieren. Allerdings ist diese Frage nicht über Parsing HTML, sondern über es zu zerstören. Verwenden Sie für alle Aufgaben, die darüber hinausgehen, einen Parser.


Ich denke, Ihre Regex ist gut. Solange es nichts mehr gibt als Entfernen aller HTML-Tags von der Eingabe, mit einer Regex wie Ihre ist sicher.

Alles andere wäre wahrscheinlich mehr Ärger als es wert ist, aber man konnte eine kleine Funktion schreiben, die einmal durch den string char-by-char-Loops und entfernt alles, was Klammern innerhalb der TAG — zB:

  • Schalter auf einem „INTAG“ -Kennzeichen, sobald Sie einen „<“ Charakter begegnen,
  • es ausschalten, sobald Sie „>
  • Kopie Zeichen an die Ausgabezeichenfolge, solange das Flag begegnen, ist aus
  • für Leistung, verwenden Sie ein StringBuilder-Java-Objekt anstelle von String-Verkettung

Für einen anspruchsvollen Teil Ihrer App, kann dies schneller als die Regex sein. Aber die Regex ist sauber und wahrscheinlich schnell genug.

Vielleicht modifizierte regex hat einige Vorteile für Sie:

<[^>]*(?:>|$) 
  • Fänge nicht geschlossene Tags am Ende des Strings
  • [^>]* ist besser als (.|\n)

Die Verwendung von REReplaceNoCase() ist unnötig, wenn im Muster keine Buchstaben enthalten sind. Die Groß-/Kleinschreibung von Regex-Übereinstimmungen ist langsamer als bei der Groß- und Kleinschreibung.

+0

Ich habe <[^>] *> als eine mögliche modifizierte Regex verwendet werden kann. Welchen Vorteil bietet Ihre zweite Hälfte? – Jason

+0

Wie gesagt: Es fängt nicht geschlossene Tags am Ende der Zeichenfolge ab. "(?:> | $)" liest als "entweder eine schließende Tag-Klammer oder das Ende der Zeichenkette". Der Rest der Regex entspricht der gefundenen Alternative. "[^>] *" ist generell empfehlenswerter als "(. | \ n) *?", weil es expliziter und schneller ist. – Tomalak

+1

Ich würde empfehlen, einen zweiten Durchlauf zu machen, um mit > zu ersetzen, weil Sie vielleicht einige Reste haben. – Kip

2

Der beste Weg besteht normalerweise darin, < zu &lt; und > zu &gt; zu zwingen. Auf diese Weise treffen Sie keine Annahmen über die Art der Nachricht. Jemand kann über <tags> sprechen oder versuchen, <<expressive>> zu sein oder einen Tastenanschlag zu beschreiben <Ctrl>+C oder mit Mathe 1 <x> 3.Auch könnte Smiles <8P X> regulären Ausdruck

<cfloop from="1" to="#ArrayLen(myFeed.item)#" index="i"> 
    <cfset myFeed.item[i].description.value = ReplaceList(myFeed.item[i].description.value, '<,>', '&lt;,&gt;')> 
</cfloop> 
+1

@SpliFF: In Bezug auf "Sogar Smilies könnte die Regex auslösen" - nein, sie konnten nicht. Sie würden als "< 8P" codiert werden. – Tomalak

+0

Ja, sagt er, seine Daten stammen von einem RSS-Feed. Wenn der Feed korrekt ist, wäre der einzige bare < and > von Tags, die anderen wären <und>.Es ist durchaus möglich, dass der Quell-Feed fehlerhaft ist, aber das wäre das Problem des Anbieters (was wahrscheinlich jeden Feed-Parser durcheinander bringen würde). – Kip

+0

Ist ]]> in einer RSS-Feed-Beschreibung nicht gültig? –

7

HTML keine reguläre Sprache ist, so Reguläre Ausdrücke auf (ungeregelt) mit HTML ist etwas, das mit großer Sorgfalt durchgeführt werden soll (wenn überhaupt).

Betrachten wir zum Beispiel die folgende gültig Segment von HTML:

<img src="boat.jpg" alt="a boat" title="My boat is > everything! I <3 my boat!"> 

Sie werden bemerken, wie die Syntax-Highlighter auf, dass erstickt - wie wird die bestehende regex, die angeboten wurde.

Sofern Sie bestimmte sein kann, dass die Zeichenfolge, die Sie verarbeiten nicht HTML-Code ähnlich wie oben enthalten, die Sie vermeiden sollten Annahmen/Kompromiss zu machen, die eine einzelne/reine regex Route, die Sie zwingen würde, zu tun.

. (Anmerkung: Das gleiche Problem gilt für die vorgeschlagene char-by-char Methode auch)


Ihr Problem zu lösen, sollten Sie einen DOM-Parser verwenden, um Ihre Zeichenfolge in ein HTML-Objekt zu analysieren, Looping durch jedes Element und Umwandlung in Text.

Wenn Sie gültiges XHTML haben, dann können Sie CFs XmlParse() verwenden, um das Objekt zu erzeugen, das Sie dann Schleife können. Wenn es sich nicht um XML-HTML handelt, gibt es keine integrierte Option für CF8, daher müssen Sie Optionen in Java/etc untersuchen.

+0

ah, Boot Programmierung :) – jinglesthula

3

ich verwenden:

REReplaceNoCase(text, "<[^[:space:]][^>]*>", "", "ALL"); 

99% der Fälle es funktioniert gut.

0
<cfset a = "<b><font color = 'red'>(PCB) <1 ppm </font></b>"> 

<cfset b = REReplaceNoCase(a, "<[^><]*>", '', 'ALL')> 

<cfdump var="#b#"> 

Ausgang b = "(PCB) < 1 ppm"

Die Regex "< [^> <] *>" werden alle Tags und die Zeichen innerhalb dieser Schlagwörter entfernen und entfernen nicht einzelnen Tags wie < oder> die als weniger als oder größer als Symbol in der Zeichenfolge

Verwandte Themen