2009-03-20 6 views
0

Ich bekomme einige HTML-Daten von Remote-Server und bevor es in der Benutzeroberfläche der Anwendung angezeigt wird, muss ich einige Änderungen vornehmen, dh Zähler löschen, ersetzen usw. Entfernen einige Tags mit Inhalten und Ändern bestimmter Link ist keine große Sache, aber wenn es um einige erweiterte Verarbeitung geht, habe ich einige Probleme.Es gibt eine Notwendigkeit zu ersetzen (löschen) einige HTML-Tag-Attribute (nicht ein Tag selbst - es gibt viele Beispiele über das Internet über Dies). Zum Beispiel: Löschen Sie alle onmouseover Handler von Schaltflächen. Ich weiß, dass XPath für solch ein Problem perfekt passen würde, aber ich weiß es überhaupt nicht und obwohl meine Informationen XHTML-Beschwerde sind, ist es in einer String-Variablen gespeichert und nicht abfragbar :(. Also versuche ich zu verwenden Reguläre Ausdrücke dieses Problem zu lösen, ohne Erfolg für den Moment. ich denke, es ist ein Fehler im Muster ...C# - Verarbeitung von HTML-Tag-Attributen

public string Processing (string Source, string Tag, string Attribute) 
{  
return System.Text.RegularExpressions.Regex.Replace(Source, string.Format(@"<{0}(\s+({1}=""([^""]*)""|\w+=(""[^""]*""|\S+)))+>", Tag, Attribute), string.Empty); 
} 

... 

string before = @"<input type=""text"" name=""Input"" id=""Input"" onMouseOver=""some js to be eliminated"">"; 
string after = Processing(before,"input","onMouseOver"); 
// expected : <input type="text" name="Input" id="Input">" 

Antwort

1

, dass ein interessanter Ansatz ist, aber wie bobince sagte, können Sie nur ein Attribut pro Spiel verarbeiten. Diese Regex wird alles zusammenpassen, um das Attribut, das Sie interessiert sind:

@"(<{0}\b[^>]*?\b){1}=""(?:[^""]*)""" 

Dann Sie „$ 1“ als Ersatz-String zu stopfen zurück in alles, aber das Attribut verwenden.

Bei diesem Ansatz müssen Sie die Zeichenfolge für jedes Ziel-Tag/Attribut-Paar separat übergeben. Zu Beginn jedes Durchgangs müssen Sie die Regex erstellen und kompilieren. Nicht sehr effizient, aber wenn die Saite nicht zu groß ist, sollte es in Ordnung sein. Ein viel größeres Problem ist, dass es keine doppelten Attribute abfängt; Wenn es zwei "onmouseover" -Attribute auf einer Schaltfläche gibt, fangen Sie nur die erste.

Wenn ich in C# tue dies wäre, würde ich wahrscheinlich die Regex verwenden, um den Ziel-Tag übereinstimmen, dann eine MatchEvaluator verwenden alle das Ziel zu entfernen, auf einmal Attribute. Aber im Ernst, wenn die Zeichenfolge richtig ist XML wohlgeformt ist, gibt es keine Entschuldigung dafür, nicht mit XML-spezifischen Werkzeugen, um es zu verarbeiten - das ist, was XML war erfunden für.

+0

Es scheint, als ob die schließende runde Klammer der Gruppe fehlt (Regex kompiliert nicht). Fester Ausdruck: @ "(<{0}\b[^>] * \ b?) ({1} =" "(?: [^" "] *)" ")" – Jaded

+0

Und natürlich, vielen Dank, Ihr Tipp ist eigentlich das, was ich brauchte. – Jaded

+0

Hoppla. Eigentlich sollte die öffnende runde Klammer kurz vor der {1} nicht da sein. Es macht keinen Sinn, das Attribut zu erfassen, da Sie es nur löschen. –

1

ich weiß, das ist eine Frage, über (Fixierung) RegEx aber ein alternativer Ansatz ist Ihren xHtml zu laden in ein XmlDocument (es akzeptiert eine Zeichenkette) oder XDocument und benutze XPath oder Linq.

+0

Nun, würde ich ein einfaches Beispiel XPath geschätzt;) – Jaded

0

Ich denke, dass Ihr Ansatz zu einfach ist. Das Analysieren eines HTML mit regulären Ausdrücken ist möglicherweise viel schwieriger, als Sie denken. Ich würde vorschlagen nehmen Sie ein look at this question.

+0

mit einigen Dritt Rahmen für eine solche. eine Aufgabe wäre "viel mehr". Ich weiß, dass HTML Agility Pack ziemlich mächtig ist, b Aber ich werde versuchen, es zu benutzen, falls es wirklich notwendig ist. – Jaded

0

Ich weiß, dass XPath

Ganz so eine perfekte Passform für ein solches Problem sein würde. Oder jede andere XML-Parser-basierte Technik, wie zum Beispiel DOM-Methoden.

Es ist wirklich nicht schwer zu lernen: stopfen Sie Ihre Zeichenfolge in die XmlDocument.LoadXml() Methode dann rufen Sie selectNodes() darauf mit etwas wie '// Tagname [@attrname]', um eine Liste von Elementen mit dem unerwünschten Attribut zu erhalten. Peasy.

Ich versuche, Reguläre Ausdrücke zu verwenden, um dieses Problem zu lösen, ohne Erfolg

Was ist das mit regulären Ausdrücken? Die Leute benutzen sie auch dann, wenn sie wissen, dass es falsch ist, obwohl sie oft unlesbar und schwer zu bekommen sind (wie die endlosen Fragen "Warum funktioniert das nicht?").

Also was ist so attraktiv an den verdammten Dingen? Es gibt jeden Tag mehrere Fragen zu SO über das Parsen von [X] [HT] ML mit Regex, alle beantworteten "verwende keine Regex, Regex ist nicht stark genug, um HTML zu analysieren". Aber irgendwie kommt es nie durch.

ich, es ist ein Fehler im Muster erraten ...

Nun erscheint das Muster mit einem leeren String zu versuchen, ganze Tags entsprechen zu ersetzen, das nicht das, was Sie wollen. Stattdessen sollten Sie nur das Attribut targetieren. Um sicherzustellen, dass nur Attribute innerhalb eines "< Tags ...>" gezählt werden, müssen Sie eine negative Lookbehind-Assertion verwenden - "(?! < Tag)". Sie können jedoch normalerweise keine Lookbehind-Assertion variabler Länge verwenden, die Sie anderen Attributen ermöglichen müssten, um zwischen dem Tag-Namen und dem Zielattribut zu kommen.

Auch Ihre '\ S +' Klausel hat das Potenzial, große Mengen unbeabsichtigten Inhalts zu verschlingen. Da Sie wohlgeformtes XHTML-Format haben, sind Ihnen korrekt zitierte Attribute garantiert, so dass Sie das sowieso nicht benötigen.

Aber der Fehler ist nicht das Muster. Es ist Regex.

+0

Sicher. Regex sind für viele Probleme nützlich. Aber wenn die Fragen zu SO alles sind - und nach der Menge an Coding Horror in der realen Welt, die ich gesehen habe, sind sie wahrscheinlich - eine Mehrheit der Regex-Nutzung ist völlig unangemessen. – bobince

+0

Nun ... Ich dachte, Reguläre Ausdrücke sind besser als etwas wie folgt: Source.Substring (Source.IndexOf (Attribut), Attribute.Length + ParameterLength) oder etwas ... Plus ist ein Dokument i mit Arbeits bin erscheint sei nicht vollständig XHTML-Beschwerde. Es ist ein XML-Namespace enthalten, aber die Validierung schlägt fehl. – Jaded

+0

"Validierung" ist nicht wichtig für die Verarbeitung als XML, es muss nur "wohlgeformt" sein. Ansonsten gibt es HTML-Parser wie das Agility Pack, die immer noch viel, viel einfacher sind als der Versuch, eine Regex zu hacken. – bobince

0

Also, die neu geschrieben Code:

public static string Process(string Source, string Tag, string Attribute) 
{ 
     return Regex.Replace(Source, string.Format(@"(<{0}\b[^>]*?\b)({1}=""(?:[^""]*)"")", Tag, Attribute), "$1");     
} 

ich habe es ausprobiert und es funktioniert gut.

string before = @"<input type=""text"" name=""Input"" id=""Input"" onMouseOver=""some js to be eliminated1""/>" 
     + "\r\n" + @"<input type=""text"" name=""Input2"" id=""Input2"" onMouseOver=""some js to be eliminated2"">" 
     + "\r\n" + @"<input type=""text"" name=""Input3"" id=""Input3"" onMouseOver=""some js to be eliminated3"">";    
string after = Process(before, "input", "onMouseOver"); 
//<input type="text" name="Input" id="Input" /> 
//<input type="text" name="Input2" id="Input2" > 
//<input type="text" name="Input3" id="Input3" > 

Für jetzt ist das Problem gelöst. Ich würde versuchen, eine XML-Abhilfe zu verwenden, aber es scheint, wie vor XmlDocument Schaffung ich brauche Eingabe html wieder zu überarbeiten, weil nach w3c validator es Fehler hat. Es beginnt wie folgt

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
    <HTML xmlns="http://www.w3.org/1999/xhtml"> 
    <HEAD> 
    <TITLE>page title</TITLE> 

Auf LoadXml i „System.Xml.XmlException über‚>‘Marker erhalten, ist nicht akzeptabel - Zeile 1, Position 63. Hinzufügen von Dokumenttypdefinition die gleiche Ausnahme verursacht, aber diesmal über‚- .? "Marker falsch,‚>‘erwartet

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
     "http://www.w3.org/TR/html4/strict.dtd"> 

Ideen oder lassen sie es gehen)

+0

Wenn es in Großbuchstaben sagt, ist es nicht XHTML - wahrscheinlich der ursprüngliche Legacy-HTML-Doctype ist passender und die "Xmlns" ist nur Lügen. – bobince

+0

(Und wir können es nicht von der Eingabe sehen, aber der Fehler über '-' ist normalerweise ein Zeichen für einen gebrochenen Kommentar wie "" , die sowohl in HTML als auch in XHTML ungültig ist, aber von Browsern und dem Agility Pack ordnungsgemäß verarbeitet wird. – bobince