Как использовать HTML Agility Pack для редактирования фрагмента HTML
Итак, у меня есть фрагмент HTML, который я хочу изменить с помощью С#.
<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="#" onclick="location.href='http://mysite.com/search/specialSearchWord'; return false;">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="#" onclick="location.href='http://mysite.com/search/specialSearchWord'; return false;">specialSearchWord</a> again.
</div>
Я собираюсь использовать HTML Agility Pack на основе многих рекомендаций здесь, но я не знаю, куда я иду. В частности,
- Как загрузить частичный фрагмент в виде строки вместо полного HTML-документа?
- Как редактировать?
- Как мне вернуть текстовую строку отредактированного объекта?
Ответы
Ответ 1
- То же, что и полный HTML-документ. Это не имеет значения.
- Это два варианта: вы можете редактировать свойство
InnerHtml
напрямую (или Text
на текстовых узлах) или изменять дерево dom, используя, например, AppendChild
, PrependChild
и т.д.
- Вы можете использовать свойство
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();
}
Ответ 2
Ответы:
- Возможно, есть способ сделать это, но я не знаю, как это сделать. Я предлагаю
загрузка всего документа.
- Используйте комбинацию XPath и регулярную
выражения
- См. приведенный ниже код для надуманного примера. Ты можешь иметь
другие ограничения, не упомянутые, но этот образец кода должен получить вас
начал.
Обратите внимание, что ваше 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);