2010-11-30 8 views
1

Ich weiß, dass die Verwendung von Regulären Ausdrücken, um HTML/XML zu parsen oder zu manipulieren, eine schlechte Idee ist und normalerweise würde ich es nie tun. Aber angesichts mangelnder Alternativen.Ersetze Text, der nicht in einem Tag enthalten ist, entweder mit Regex oder XmlParser

Ich muss Text innerhalb einer Zeichenfolge ersetzen, die nicht bereits Teil eines Tags (idealerweise ein span-Tag mit bestimmter ID) mit C#.

Zum Beispiel Nehmen wir an ich alle instaces von ABC im folgenden Text ersetzt werden soll, die nicht innerhalb einer Spanne mit Alternativtext (eine andere Spanne in meinem Fall) sind

ABC at start of line or ABC here must be replaced but, <span id="__publishingReusableFragment" >ABC inside span must not be replaced with anything. Another ABC here </span> this ABC must also be replaced

Ich versuchte regex mit beiden schauen nach vorne und schauen hinter die Behauptung. Verschiedene Kombinationen im Sinne von

string regexPattern = "(?<!id=\"__publishingReusableFragment\").*?" + stringToMatch + ".*?(?!span)"; 

haben aber darauf verzichtet.

Ich habe versucht, es in ein XElement zu laden und versuche, einen Schreiber von dort zu erstellen und Text nicht innerhalb eines Knotens zu bekommen. Aber das konnte ich auch nicht herausfinden.

Ich hoffe irgendwie den Schreiber zu verwenden, um die Zeichenfolgen zu erhalten, die nicht Teil eines Knotens sind, und sie zu ersetzen.

Grundsätzlich bin ich offen für irgendwelche Vorschläge/Lösungen, um dieses Problem zu lösen.

Vielen Dank im Voraus für die Hilfe.

Antwort

1
resultString = Regex.Replace(subjectString, 
    @"(?<!    # assert that we can't match the following 
         # before the current position: 
         # An opening span tag with specified id 
    <\s*span\s*id=""__publishingReusableFragment""\s*> 
    (?:    # if it is not followed by... 
     (?!<\s*/\s*span) # a closing span tag 
     .     # at any position between the opening tag 
    )*     # and our text 
    )     # End of lookbehind assertion 
    ABC     # Match ABC", 
    "XYZ", RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace); 

wird mit allen Einsprüche über HTML arbeiten Parsen (die Sie scheinen zu wissen, also werde ich sie hier nicht wiederholen) noch gültig.

Die Regex passt ABC, wenn es nicht durch eine Öffnung <span id=__publishingReusableFragment"> Tag vorangestellt ist und wenn es keine Schließung <span> Tag zwischen den beiden. Es wird offensichtlich fehlschlagen, wenn es verschachtelte <span> Tags geben kann.

+0

Sieht gut aus. Aber was ist, wenn einige zusätzliche Attribute in der span-Tag hatte zB: ... Ich habe versucht, den Span Teil der Regex als ersetzen folgt <\ s * span. *? id = "" __ publishingReusableFragment "". *?> Aber jetzt passt es nicht nach dem Ende der span-Tag - ... dieses ABC ... – Chaitanya

+0

Sie beginnen zu ran an all die Gründe, warum das Parsen von HTML mit Regexes keine gute Idee ist. Wenn Ihre Attribute niemals ein '>' enthalten, können Sie '<\s*span[^>] * id =" "__ publishingReusableFragment" "[^>] *>' verwenden und auf das Beste hoffen. –

+0

Yup, das war es, danke. Yeah, weshalb ich gehofft hatte, dass es mit LinqToXML oder einer guten LinqToHtml-Lib funktionieren könnte. Dies ist nur ein Wegwurf, ein Tool zum Importieren, das einige Daten auf dem Weg einlesen muss, um die manuelle Nachbearbeitung zu reduzieren. – Chaitanya

1

ich seine etwas hässlich weiß, aber dies funktioniert

var s = 
    @"ABC at start of line or ABC here must be replaced but, <span id=""__publishingReusableFragment"" >ABC inside span must not be replaced with anything. Another ABC here </span> this ABC must also be replaced"; 
var newS = string.Join("</span>",s.Split(new[] {"</span>"}, StringSplitOptions.None) 
    .Select(t => 
     { 
      var bits = t.Split(new[] {"<span"}, StringSplitOptions.None); 
      bits[0] = bits[0].Replace("ABC","DEF"); 
      return string.Join("<span", bits); 
     })); 
+0

Nicht hässlich. Dies ist eine großartige Möglichkeit zu tun, was getan werden muss (was ein bisschen hässlich ist). Das einzige Problem ist, dass es alle Spannen ignoriert. nicht nur überspannt mit einer bestimmten ID, wie der Regex. Dies hätte ich wahrscheinlich erweitert und würde in vielen anderen Situationen helfen. – Chaitanya