我想知道其他人是否可以在System.Uri
或标准.NET框架中提供的其他方法的基础上提出更好的简化相对URL的方法。我的尝试有效,但非常可怕:
public static String SimplifyUrl(String url)
{
var baseDummyUri = new Uri("http://example.com", UriKind.Absolute);
var dummyUri = new Uri(baseDummyUri , String.Join("/",
Enumerable.Range(0, url.Split(new[] { ".." }, StringSplitOptions.None).Length)
.Select(i => "x")));
var absoluteResultUri = new Uri(dummyUri, url);
var resultUri = dummyUri.MakeRelativeUri(absoluteResultUri);
return resultUri.ToString();
}
这给出了例如:
./foo -> foo
foo/./bar -> foo/bar
foo/../bar -> bar
使问题变得如此尴尬的问题是,Uri
本身似乎并不简化相对的URL,MakeRelativeUri
也只适用于绝对URL。因此,为了欺骗Uri
类进行我想要的操作,我构建了一个具有适当嵌套量的基本URL。
我也可以使用System.IO.Path
,但是我必须将反斜杠搜索和替换为斜线......
必须有更好的方法,对吧?
答案 0 :(得分:10)
您可以使用单线来做到这一点:
new Uri(new Uri("http://example.com/"), url).AbsolutePath.TrimStart('/');
以下测试显示了结果:
[Theory]
[InlineData("./foo", "foo")]
[InlineData("/foo", "foo")]
[InlineData("foo", "foo")]
[InlineData("foo/./bar", "foo/bar")]
[InlineData("/foo/./bar", "foo/bar")]
[InlineData("/foo/../bar", "bar")]
[InlineData("foo/../bar", "bar")]
public void Test(string url, string expected)
{
var result = new Uri(new Uri("http://example.com/"), url).AbsolutePath.TrimStart('/');
Assert.Equal(expected, result);
}
当然,如果您想一开始就离开/
,只需删除TrimStart('/')
答案 1 :(得分:0)
这是一个解析问题。标记以“ /”分隔;令牌“ ..”减少了先前的令牌(如果有),而令牌“。”减少了是无人操作。
有一点曲折,是在用“ /”分隔字符串之后,我们需要跟踪它是绝对路径(以“ /”开始)还是相对路径(以“。”开始)。 )。如果缩小的路径为空,我们需要此方法。
public static class UrlHelper
{
static public string Simplify(this string url)
{
string[] sourcePath = (url ?? "").Trim().Split('/');
if (sourcePath.Count() == 0) { throw new ArgumentException(); }
string startingAt = (sourcePath[0] == "")? "/": ".";
Stack<string> simplifiedPath = new Stack<string>();
foreach (string dir in sourcePath) {
if (dir == ".") {
continue;
} else if (dir == ".." && simplifiedPath.Count > 0) {
simplifiedPath.Pop();
continue;
}
simplifiedPath.Push(dir);
}
string reducedPath = (simplifiedPath.Count == 0)? "": simplifiedPath.Reverse().Aggregate((path, dir) => path + "/" + dir);
return (reducedPath == "") ? startingAt : reducedPath;
}
}
一些测试:
static void Main(string[] args)
{
Console.WriteLine("./foo".Simplify()); // => foo
Console.WriteLine("foo/./bar".Simplify()); // => foo/bar
Console.WriteLine("foo/../bar".Simplify()); // => bar
Console.WriteLine("foo/bar/../..".Simplify()); // => .
Console.WriteLine("/foo/bar/../..".Simplify()); // => /
Console.WriteLine("../bar".Simplify()); // => ../bar
Console.WriteLine("..".Simplify()); // => ..
Console.WriteLine(".".Simplify()); // => .
Console.WriteLine("/foo".Simplify()); // => /foo
Console.WriteLine("/".Simplify()); // => /
Console.ReadKey();
}