2009-08-20 6 views
2

Ich habe eine Zeichenfolge mit einigen Markup, die wie folgt aussieht:Java Regex alle HTML-Elemente mit Ausnahme eines Sonderfall anzupassen

The quick brown <a href="www.fox.org">fox</a> jumped over the lazy <a href="entry://id=6000009">dog</a> <img src="dog.png" />.

alles, was ich bin versucht abstreifen mit „-Eintrag mit Ausnahme der Ankerelemente : // id = "innen. Somit ist die gewünschte Ausgabe aus dem obigen Beispiel wäre:

The quick brown fox jumped over the lazy <a href="entry://id=6000009">dog</a>.

dieses Spiel Schreiben, das am nächsten komme ich habe, so weit ist:

<.*?>!<a href=\"entry://id=\\d+\">.*?<\\/a>

Aber ich kann nicht herausfinden, warum das nicht funktioniert. Jede Hilfe (abgesehen von dem "warum verwendest du keinen Parser" :) würde sehr geschätzt werden!

+0

Ein Regex, um sie alle zu beherrschen! Entschuldigung, ich kann mir nicht helfen. – MattC

Antwort

1

diese verwenden:

((<a href="entry://id=\d+">.*?</a>)|<!\[CDATA\[.*?\]\]>|<!--.*?-->|<.*?>) 

und es mit einer Kombination ersetzen alle 2 $ würde für Ihr Beispiel arbeiten. Der folgende Code beweist:

import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

import static org.junit.Assert.*; 
import org.junit.Test; 


public class TestStack1305864 { 

    @Test 
    public void matcherWithCdataAndComments(){ 
     String s="The quick <span>brown</span> <a href=\"www.fox.org\">fox</a> jumped over the lazy <![CDATA[ > ]]> <a href=\"entry://id=6000009\">dog</a> <img src=\"dog.png\" />."; 
     String r="The quick brown fox jumped over the lazy <a href=\"entry://id=6000009\">dog</a> ."; 
     String pattern="((<a href=\"entry://id=\\d+\">.*?</a>)|<!\\[CDATA\\[.*?\\]\\]>|<!--.*?-->|<.*?>)"; 
     Pattern p = Pattern.compile(pattern); 
     Matcher m = p.matcher(s); 

     String t = s.replaceAll(pattern, "$2"); 
     System.out.println(t); 
     System.out.println(r); 
     assertEquals(r, t); 
    } 
} 

Die Idee, alle Elemente zu erfassen, die Sie interessieren sich für eine bestimmte Gruppe zu halten, damit Sie sie zurück in die Zeichenfolge einfügen.
Für jedes Element, das nicht die interessanteren übereinstimmen wird die Gruppe leer sein und das Element wird mit „“
die Gruppe leer ist nicht und wird für die interessanten Elemente ersetzt werden:
Auf diese Weise können Sie alle ersetzen an die Ergebniszeichenfolge angehängt werden.

edit: Griff < oder> in CDATA verschachtelt und Kommentare
edit: http://martinfowler.com/bliki/ComposedRegex.html für ein regex Zusammensetzung Muster sehen, entworfen regex besser lesbar zu Wartungszwecken zu machen.

+0

Vielen Dank! Das machte meinen Tag und gestern auch :-) – thomax

7

Ich würde Regexps wirklich nicht verwenden, um HTML zu analysieren. HTML ist nicht regelmäßig und es gibt keine Ende der Randfälle, um Sie zu stolpern.

Überprüfen Sie JTidy stattdessen.

+0

+1. Fragen wie diese werden mehrmals täglich an SO gesendet. Ob Sie es glauben oder nicht, Sie können einfach [X] [HT] ML nicht mit Regex parsen, und wenn Sie dies tun, werden Sie auf seltsame Fehler, Verwirrung und Sicherheitslücken vorbereitet. Tu es nicht. Es gibt HTML-Parser. – bobince

+0

Entschuldigung, Sie scheinen "regulär" als Fachbegriff zu verwenden. Wenn Sie sind, könnten Sie mich auf eine Referenz verweisen? – Beta

+0

Ich werde jetzt meine Ignoranz zeigen und sagen, dass reguläre Ausdrücke nicht mit beliebig verschachtelten Strukturen umgehen (Sie können <,> über CDATA-Abschnitte verschachteln usw.). Ich bin nicht * total * vertraut mit der richtigen Definition von 'regulär' in diesem Szenario und würde Kommentare von einem mehr qualifizierten SOer begrüßen! –

1

Nicht einfach mit Regex möglich. Ich empfehle einen Parser, der die Semantik von HTML/XML versteht.

Wenn Sie bestehen, könnten Sie einen mehrstufigen Ansatz tun, so etwas wie:

  • "<(a\s*href="entry:.*?/a)>" Ersetzen mit "{{{{\1}}}}"
  • ersetzen "<(?!/a}}}})[^>]*>" mit ""
  • "{{{{" Ersetzen mit "<"
  • ersetzen "}}}}" mit ">"

Seien Sie gewarnt, dass das oben genannte fehleranfällig ist und an einem bestimmten Punkt ausfallen wird. Betrachten Sie es als hässlichen Hack, nicht als echte Lösung. Etwas wie oben ist in Ordnung für eine einmalige Bearbeitung einer Textdatei in einem Regex-fähigen Texteditor, aber für wiederholte, reale Verwendung als Teil der Datenverarbeitung in einer App - nicht so sehr.