Как использовать HTML Agility Pack для редактирования фрагмента HTML - PullRequest
12 голосов
/ 01 марта 2012

Итак, у меня есть фрагмент HTML, который я хочу изменить с помощью C #.

<div>
This is a specialSearchWord that I want to link to
<img src="anImage.jpg" />
<a href="foo.htm">A hyperlink</a>
Some more text and that specialSearchWord again.
</div>

и я хочу преобразовать это в:

<div>
This is a <a class="special" href="http://mysite.com/search/specialSearchWord">specialSearchWord</a> that I want to link to
<img src="anImage.jpg" />
<a href="foo.htm">A hyperlink</a>
Some more text and that <a class="special" href="http://mysite.com/search/specialSearchWord">specialSearchWord</a> again.
</div>

Я собираюсь использовать HTML Agility Pack, основываясь на множестве рекомендаций, но я не знаю, куда я иду. В частности,

  1. Как загрузить частичный фрагмент в виде строки, а не полный HTML-документ?
  2. Как редактировать?
  3. Как мне затем вернуть текстовую строку отредактированного объекта?

Ответы [ 2 ]

20 голосов
/ 02 марта 2012
  1. То же, что и полный HTML-документ. Это не имеет значения.
  2. Существует 2 варианта: вы можете редактировать свойство InnerHtml напрямую (или Text на текстовых узлах) или изменять дерево dom, используя, например, AppendChild, PrependChild и т. Д.
  3. Вы можете использовать свойство HtmlDocument.DocumentNode.OuterHtml или метод HtmlDocument.Save (лично я предпочитаю второй вариант).

Что касается разбора, я выбираю текстовые узлы, которые содержат поисковый термин внутри вашего div, а затем просто использую метод string.Replace для его замены:

var doc = new HtmlDocument();
doc.LoadHtml(html);
var textNodes = doc.DocumentNode.SelectNodes("/div/text()[contains(.,'specialSearchWord')]");
if (textNodes != null)
    foreach (HtmlTextNode node in textNodes)
        node.Text = node.Text.Replace("specialSearchWord", "<a class='special' href='http://mysite.com/search/specialSearchWord'>specialSearchWord</a>");

И сохранение результата в строку:

string result = null;
using (StringWriter writer = new StringWriter())
{
    doc.Save(writer);
    result = writer.ToString();
}
1 голос
/ 01 марта 2012

Ответы:

  1. Может быть, есть способ сделать это, но я не знаю как. Я предлагаю загрузка всего документа.
  2. Используйте комбинацию XPath и обычного выражения
  3. См. Код ниже для надуманного примера. Ты можешь иметь другие ограничения, не упомянутые, но этот пример кода должен вас началось.

Обратите внимание, что ваше выражение Xpath может быть более сложным, чтобы найти нужный вам div.

HtmlDocument doc = new HtmlDocument();

doc.Load(yourHtmlFile);
HtmlNode divNode = doc.DocumentNode.SelectSingleNode("//div[2]");
string newDiv = Regex.Replace(divNode.InnerHtml, @"specialSearchWord", 
"<a class='special' href='http://etc'>specialSearchWord</a>");
divNode.InnerHtml = newDiv;
Console.WriteLine(doc.DocumentNode.OuterHtml);
...