Я хочу обнаружить URL-адреса и сделать их ссылочными в коде HTML. Я искал переполнение стека, но многие ответы касаются обнаружения и преобразования ссылок в текстовых строках. Когда я это сделаю, код html будет недействителен; ie. исходники img изменятся, et c.
PS: Закройте голосующие: пожалуйста, прочтите вопрос внимательно! Это не дубликат.
Например; строка 1 должна быть преобразована, а строки 2 и 3 - нет.
<!-- Sample html source -->
<div>
Line 1 : https://www.google.com/
Line 2 : <a href="https://www.google.com/">https://www.google.com/</a>
Line 3: <img src="http://a-domain.com/lovely-image.jpg">
</div>
Мне нужно:
Найти любой URL-адрес в html часть тела
Проверить, кликабельна она или нет: если она не заключена в символы 'a', 'img', '! -', et c ..
Если не сделать его кликабельным: Оберните 'a'
Как я могу это сделать? Все версии C# и JS мне подходят.
ПОСЛЕДНЕЕ ОБНОВЛЕНИЕ Изменение цели сборки проекта с 4.7.2 на 4.5 и обратно на 4.7.2 устранило «ошибку».
ОБНОВЛЕНИЕ: Это мое решение с помощью @jira. Проблема в том, что узлы вообще не изменятся. Я имею в виду, что рекурсивная функция выполняет свою работу, заменяет ссылки, говорит отладка, однако документ html не обновляется вообще. Любая модификация внутри функции не действует вне функции, я не знаю почему, InnerText изменяется - внутренний Html не меняется
var htmlVersion = "<html><head></head><body>\r\n"
+ "Some text\r\n"
+ "<div>http://google.com</div>\r\n"
+ " Then later more text: http://500px.com\r\n"
+ "<div>Sub <span>abc</span> Back text</div>\r\n"
+ "And the final text"
+ "</body></html>";
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(htmlVersion);
// Linkify body
var modified = false;
var bodyNode = doc.DocumentNode.SelectSingleNode("//body");
var before = bodyNode.InnerHtml;
bodyNode = Linkify(bodyNode);
modified = modified || bodyNode.InnerHtml != before;
// modified is false !!!
Рекурсивная Linkify функция:
HtmlAgilityPack.HtmlNode Linkify(HtmlAgilityPack.HtmlNode node)
{
if (node.Name == "a") // It's already a link
{
return node;
}
if (node.Name == "#text") // Do replacement here
{
// Create links
// https://stackoverflow.com/a/4750468/627193
node.InnerHtml = Regex.Replace(node.InnerHtml,
@"((http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)",
"<a target='_blank' href='$1'>$1</a>");
}
for (int i = 0; i < node.ChildNodes.Count; i++) // Go for child nodes
{
node.ChildNodes[i] = Linkify(node.ChildNodes[i]);
}
return node;
}