帮助识别相对于绝对URL RegEx替换的问题
本文关键字:RegEx 替换 问题 URL 识别 相对于 帮助 | 更新日期: 2023-09-27 18:05:47
我一直在使用我在这里找到的一些代码来帮助我在HTML页面源中将相对url转换为绝对url。
我想用RegEx,而不是HTML敏捷包来解决这个问题。
我稍微修改了代码,它工作得很好,除了前面有"/"的相对URL被替换,但似乎,据我所知,不包括前面的斜杠的相对URL不是。
我很确定这个问题是在初始的regEx字符串,因为没有尝试替换。这超出了我的正则表达式知识。
有没有人可以帮助我确定是什么原因导致这个不匹配我所描述的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;
}
//RegEx匹配码
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;
}
//Url转换
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("~/", "/"));
}
change
+ "/(?<url>[^'"'>'''']+)(?<delim2>['"''''']{0,2})";
+ "(?<url>[^'"'>'''']+)(?<delim2>['"''''']{0,2})";
即去掉前面的斜杠
和在CSS部分更改
+ "(?!http)''s*/(?<url>[^'"')]+)[''")]{1,2}";
+ "(?!http)''s*(?<url>[^'"')]+)[''")]{1,2}";
我怀疑问题只是部分在于Regex,它要求相对url以"/"开头。删除此限制仍然会失败,因为ToAbsoluteUrl
方法最终调用VirtualPathUtility.ToAbsolute
,这需要一个根URL(相对于应用程序或绝对)。
您可以更改ToAbsoluteUrl
函数以返回给定属性的正确绝对URL。当表达式按照下面的建议进行更改时,ToAbsoluteUrl将接收没有前面~/的HTML属性,例如/path/a。而不是/~/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}"));
(我用m.Result
代替了内部的Regex.Replace
,这似乎是原作者的意图。)
两个重要的注意事项。首先,m.Groups("url")。值没有转义,所以像/path/${something}.aspx
这样的源代码会抛出异常。(这个特性在原始代码中就有。)其次,一般不建议使用正则表达式来匹配HTML。例如,如果href="/path.asp"
恰好出现在标记之外的源中,它将被匹配并转换。(您可以在模式的开头使用(?<'<[^>]*)
这样的模式来防止这种情况,但是在<a onmouseover='"g(f(this)>2)'" href="/a.aspx">
这样的情况下,由于>2
,即使这样也会导致问题。)第三,这并没有解决CSS导入问题,尽管这个问题可以类似地解决(最简单的方法是将cssPattern
中的''s*
后面的/
删除)。