簡體   English   中英

如何將不可點擊的純文本 URL 轉換為 HTML 源中的鏈接

[英]How to convert unclickable plain text URLs to links in HTML source

我想檢測 URL 並將它們鏈接到 HTML 代碼中。 我搜索了 Stack Overflow,但許多答案都是關於檢測和轉換文本字符串中的鏈接。 當我這樣做時,html 代碼將無效; IE。 img 來源會改變,等等。

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>

我需要:

  1. 在 html 車身零件中查找任何 URL

  2. 檢查它是否可點擊:如果沒有被'a','img',',--'包裹。 ETC..

  3. 如果不使其可點擊:用'a'包裹

我怎樣才能做到這一點? 所有 C# 和 JS 版本對我來說都可以。

最新更新將項目構建目標從 4.7.2 更改為 4.5 並返回到 4.7.2 修復了“錯誤”。

更新:這是我在@jira 幫助下的解決方案這里的問題是節點根本不會改變。 我的意思是遞歸 function 完成這項工作,替換鏈接,調試說,但是 html 文檔根本不會更新。 function 內部的任何修改都不會影響 function 外部,我不知道為什么, InnerText 更改 - InnerHtml 沒有更改

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 function:

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\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)",
            "<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;
}

使用 html 解析器,如HtmlAgility Pack Select 僅文本節點,然后在其中搜索鏈接。 這樣你就不會觸及現有的鏈接。 根據您需要的精確程度,您可以使用正則表達式。

例如

var doc = new HtmlDocument();
doc.LoadHtml(html);
Regex r = new Regex(@"(https?://[^\s]+)");
var textNodes = doc.DocumentNode.SelectNodes("//text()");

foreach (var textNode in textNodes) {
    var text = textNode.GetDirectInnerText();
    var withLinks = r.Replace(text, "<a href=\"$1\">$1</a>");
    textNode.InnerHtml = withLinks;
}

小提琴

正確檢查鏈接的正則表達式可能會變得相當復雜。 在此處查看其他答案。

將項目構建目標從 4.7.2 更改為 4.5 並將 go 更改回 4.7.2 后,再次修復了“錯誤”。

這是工作代碼:

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;

遞歸 Linkify function:

HtmlAgilityPack.HtmlNode Linkify(HtmlAgilityPack.HtmlNode node)
{
    if (node == null || 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\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)",
            "<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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM