2016-04-29 2 views
1

mit C# zu brechen - WinFormsWie kann ich ein <span> um timmender Wörter in HTML wickeln, ohne die HTML

ich eine gültige HTML-Zeichenfolge haben, die oder nicht verschiedene HTML-Elemente wie <a> enthalten.

Ich muss diesen HTML suchen und bestimmte Schlüsselwörter markieren - die Hervorhebung erfolgt durch Hinzufügen einer <span> um den Text mit Inline-Styling. Ich sollte dies nicht für <a> Tags oder andere HTML-Tags tun, die für den Benutzer nicht sichtbar sind.

z.B. zur Zeit mache ich das:

html = html.Replace(phraseToCount, "<span style=\"background: #FF0000; color: #FFFFFF; font-weight: bold;\">" + phraseToCount + "</span>"); 

Diese Art von Arbeiten, aber es bricht <a> Tags. So in das folgende Beispiel nur die erste Instanz des Wortes Getreide sollte mit einem <span> um es am Ende:

<p>To view more types of cereal click <a href="http://www.cereal.com">here</a>.</p> 

Wie ich dies tun könnte?

BEARBEITEN - Weitere Informationen.

Dies wird in einer Winforms-App als die beste Möglichkeit ausgeführt werden, HTML mit dem WebBrowser-Steuerelement zu erhalten - ich werde Webseiten scrapen und verschiedene Wörter hervorheben.

+0

Sie sollten nicht wirklich mit rohem HTML in C# herumspielen. Lass die Sicht diese Logik machen. – ManoDestra

+0

Müssen Sie diese Serverseite tun? Können Sie Clientskript verwenden? Mit jQuery wäre das ziemlich einfach. – squillman

+0

Es gibt HTML-Parsing-Bibliotheken da draußen. Ich benutze persönlich CSQuery das ist ein jquery port –

Antwort

4

Sie bearbeiten HTML als Nur-Text. Das willst du nicht. Sie wollen nur den "InnerText" Ihrer HTML-Elemente durchsuchen, wie in <p attribute="value">innertext</p>. Nicht über Tags, Kommentare, Stile und Skripts und was auch immer in Ihrem Dokument enthalten sein kann.

Um dies richtig zu machen, müssen Sie den HTML-Code analysieren und dann die InnerTexts aller Elemente abrufen und Ihre Logik darauf anwenden.

In der Tat ist Inner eine Vereinfachung: wenn Sie ein Element wie <p>FooBar<span>BarBaz</span></p>, wo "Baz" ersetzt werden soll, dann müssen Sie tatsächlich rekursiv alle Knoten im DOM laufen, und nur text Knoten ersetzen, weil in der Schreib InnerText Eigenschaft wird alle untergeordneten Knoten entfernen.

Für wie das tun, Sie möchten eine Bibliothek verwenden. Sie möchten keinen eigenen HTML-Parser erstellen. Siehe zum Beispiel C#: HtmlAgilityPack extract inner text, Extracting Inner text from HTML BODY node with Html Agility Pack, How can i parse InnerText of <option> tag with HtmlAgilityPack?, Parsing HTML with CSQuery, HtmlAgilityPack - get all nodes in a document und so weiter.

scheint am wichtigsten How can I retrieve all the text nodes of a HTMLDocument in the fastest way in C#? zu sein:

HtmlNodeCollection coll = htmlDoc.DocumentNode.SelectNodes("//text()"); 

foreach (HTMLNode node in coll) 
{ 
    node.InnerText = node.InnerText.Replace(...); 
} 
+0

Wenn der innere Text durch einen inneren Text mit allen Änderungen ersetzt wird, gehen die anderen Elemente verloren, richtig? –

+1

@Kaiser wenn du meinst '

FooBar BarBaz

' wo '" Baz "' ersetzt werden soll, dann ja, du musst die Kindknoten rekursiv durchlaufen und nur 'text' Knoten ersetzen. – CodeCaster

+0

Oh, die 'text' Knoten. Vielen Dank –

0

Hier ist, wie würden Sie tun, was @CodeCaster in CSQuery vorgeschlagen

string str = "<p>To view more types of cereal click <a href=\"http://www.cereal.com\">here cereal</a>.</p>"; 
var cq = CQ.Create(str); 
foreach (IDomElement node in cq.Elements) 
{ 
    PerformActionOnTextNodeRecursively(node, domNode => domNode.NodeValue = domNode.NodeValue.Replace("cereal", "<span>cereal</span>")); 
} 
Console.WriteLine(cq.Render()); 


private static void PerformActionOnTextNodeRecursively(IDomNode node, Action<IDomNode> action) 
{ 
    foreach (var childNode in node.ChildNodes) 
    { 
     if (childNode.NodeType == NodeType.TEXT_NODE) 
     { 
      action(childNode); 
     } 
     else 
     { 
      PerformActionOnTextNodeRecursively(childNode, action); 
     } 
    } 
} 

Hoffe, es hilft.

Verwandte Themen