【问题标题】:Help identifying issue in Relative to Absolute URL RegEx Replacement帮助识别相对于绝对 URL 正则表达式替换中的问题
【发布时间】:2011-10-27 21:19:51
【问题描述】:

我一直在使用我找到的一些代码 here 来帮助我将 HTML 页面源代码中的相对 URL 转换为绝对 URL。

我想使用 RegEx,而不是 HTML 敏捷包来解决这个特定问题。

我稍微修改了代码,除了替换带有前面“/”的相对 URL 之外,它运行良好,但据我所知,似乎不包含前面斜杠的相对 URL 是不是。

我很确定问题出在初始正则表达式字符串中,因为没有尝试替换。这超出了我的正则表达式知识范围。

谁能帮我找出导致这与我描述的 URL 类型不匹配的原因?

const string htmlPattern = "(?<attrib>\\shref|\\ssrc|\\sbackground)\\s*?=\\s*?" + "(?<delim1>[\"'\\\\]{0,2})(?!#|http|ftp|mailto|javascript)" + "/(?<url>[^\"'>\\\\]+)(?<delim2>[\"'\\\\]{0,2})";

// 包装代码

public static string GetRelativePathReplacedHtml(string source, Uri uri)
    {
        source = source.HtmlAppRelativeUrlsToAbsoluteUrls( uri );

        return source;
    }

// 正则表达式匹配代码

public static string HtmlAppRelativeUrlsToAbsoluteUrls(this string html, Uri rootUrl)
    {
        if (string.IsNullOrEmpty(html))
            return html;

        const string htmlPattern = "(?<attrib>\\shref|\\ssrc|\\sbackground)\\s*?=\\s*?"
                                  + "(?<delim1>[\"'\\\\]{0,2})(?!#|http|ftp|mailto|javascript)"
                                  + "/(?<url>[^\"'>\\\\]+)(?<delim2>[\"'\\\\]{0,2})";

        var htmlRegex = new Regex(htmlPattern, RegexOptions.IgnoreCase | RegexOptions.Multiline);
        html = htmlRegex.Replace(html, m => htmlRegex.Replace(m.Value, "${attrib}=${delim1}" + ("~/" + m.Groups["url"].Value).ToAbsoluteUrl(rootUrl) + "${delim2}"));

        const string cssPattern = "@import\\s+?(url)*['\"(]{1,2}"
                                  + "(?!http)\\s*/(?<url>[^\"')]+)['\")]{1,2}";

        var cssRegex = new Regex(cssPattern, RegexOptions.IgnoreCase | RegexOptions.Multiline);
        html = cssRegex.Replace(html, m => cssRegex.Replace(m.Value, "@import url(" + ("~/" + m.Groups["url"].Value).ToAbsoluteUrl(rootUrl) + ")"));

        return html;
    }

// 网址转换

    public static string ToAbsoluteUrl(this string relativeUrl, Uri rootUrl)
    {
        if (string.IsNullOrEmpty(relativeUrl))
            return relativeUrl;

        if (relativeUrl.StartsWith("/"))
            relativeUrl = relativeUrl.Insert(0, "~");
        if (!relativeUrl.StartsWith("~/"))
            relativeUrl = relativeUrl.Insert(0, "~/");

        var url = rootUrl;
        var port = url.Port != 80 ? (":" + url.Port) : String.Empty;

        // return string.Format("{0}://{1}{2}{3}", url.Scheme, url.Host, port, VirtualPathUtility.ToAbsolute(relativeUrl));
        return string.Format("{0}://{1}{2}{3}", url.Scheme, url.Host, port, relativeUrl.Replace("~/", "/"));
    }

【问题讨论】:

    标签: c# regex


    【解决方案1】:

    改变

    + "/(?<url>[^\"'>\\\\]+)(?<delim2>[\"'\\\\]{0,2})";  
    

    + "(?<url>[^\"'>\\\\]+)(?<delim2>[\"'\\\\]{0,2})";  
    

    即去掉前面的斜线

    并在 css 部分更改

    + "(?!http)\\s*/(?<url>[^\"')]+)['\")]{1,2}";  
    

    + "(?!http)\\s*(?<url>[^\"')]+)['\")]{1,2}";  
    

    【讨论】:

      【解决方案2】:

      我怀疑问题只是部分正则表达式,它要求相对 URL 以开头的“/”开头。删除此限制仍然会失败,因为ToAbsoluteUrl 方法最终会调用VirtualPathUtility.ToAbsolute,这需要一个根 URL(相对于应用程序或绝对)。

      您可以更改ToAbsoluteUrl 函数以返回给定属性的正确绝对URL。 当表达式按照以下建议更改时,ToAbsoluteUrl 将接收不带前面 ~/ 的 HTML 属性,例如,/path/a.aspx 而不是 /~/path/a.aspx。。然后可以将模式放松为:

      const string htmlPattern =  @"(?<attrib>\s(?>href|src|background))\s*=\s*"
                       + @"(?<delim1>[""'\\])(?!#|(?>https?|ftp|mailto|javascript|file)://)"
                       + @"(?<url>.+?)\k<delim1>";
                       // to handle escaped deliminators in URL string, use below
                       // in place of last segment:
                       // + @"(?<url>.+?)(?<!(?:(?<!\\)(?:\\\\)*)\\)\k<delim1>";
      

      两行之后:

      html = htmlRegex.Replace(html, m => m.Result("${attrib}=${delim1}"
             + (m.Groups["url"].Value).ToAbsoluteUrl(rootUrl)
             + "${delim2}"));
      

      (我把里面的Regex.Replace换成了m.Result,好像是原作者的本意。)

      两个重要说明。首先,m.Groups["url"].Value 没有被转义,所以像/path/${something}.aspx 这样的源会抛出异常。 (这个特性出现在原始代码中。)第二,the general caveat that using regular expressions to match HTML is generally not advised。例如,如果href="/path.asp" 恰好出现在源标签outside 中,它将被匹配和转换。 (您可以在模式的开头使用像(?&lt;\&lt;[^&gt;]*) 这样的模式来防止这种情况发生,但即使这样也会在&lt;a onmouseover=\"g(f(this)&gt;2)\" href="/a.aspx"&gt; 这样的情况下因为&gt;2 而导致问题。)第三,这并没有解决CSS导入,尽管这可以类似地解决(最简单的方法是在 cssPattern 中删除 \\s* 之后的 /)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多