C#
RelativeUriのこと
ウェブページ(HTML)のソースコードに記載されたURLを抽出する場合、リンクのURLが実際にブラウザでどのようなURLになるか見てみたほうが良い。UriクラスのRelativeUriの扱いは、ブラウザの相対URLとはちょっと違うようだ。むやみにUriのコンストラクタを使うと、うまくいかないことがある。
Uri a = new Uri("http://hoge.com/dir1/dir2/file1.html?a=b&c=d#e");
Uri b = new Uri("?x=y", UriKind.Relative);
Uri c = new Uri(a, b);
Debug.WriteLine(c);
----
http://hoge.com/dir1/dir2/?x=y
もし、「a」のURLのページに「b」のリンクを記載したなら、ブラウザでは「http://hoge.com/dir1/dir2/file1.html?x=y」になるだろう。私もそのURLを取得するメソッドが欲しいと思った。
Uri MakeAbsoluteUrl(Uri PageUrl, string HRef)
{
if ((HRef != null) && HRef.StartsWith("?"))
{
HRef = PageUrl.AbsolutePath + HRef;
}
return new Uri(PageUrl, HRef);
}
Uri MakeAbsoluteUrl(Uri PageUrl, Uri LinkUrl)
{
return MakeAbsoluteUrl(PageUrl, LinkUrl.OriginalString);
}
一方で、相対URLを作る場合の課題は些細だ。基本的にブラウザと違いはないが、ちょっとだけ格好悪い。
Uri a = new Uri("http://hoge.com/dir1/dir2/file1.html?a=b&c=d#e");
Uri b = new Uri("http://hoge.com/dir1/dir2/file1.html?a=b&c=d#z");
Uri c = a.MakeRelativeUri(b);
Debug.WriteLine(c);
----
?a=b&c=d#z
ハッシュ(#)はページ内の位置(Anchor)を示している。クエリまで同じならページとしても同じなので、相対URLにクエリ部分は不要だ。できたら「#z」だけになってほしいと思う。課題は些細なのに、格好良くしようとすると、ちょっと面倒。
Uri MakeRelativeUrl(Uri PageUrl, Uri LinkUrl)
{
if (!(LinkUrl.IsAbsoluteUri))
{
LinkUrl = MakeAbsoluteUrl(PageUrl, LinkUrl.OriginalString);
}
Uri RelativeUrl = PageUrl.MakeRelativeUri(LinkUrl);
if (RelativeUrl.OriginalString.StartsWith("?") &&
(LinkUrl.Query == PageUrl.Query) &&
(LinkUrl.Fragment != string.Empty))
{
RelativeUrl = new Uri(LinkUrl.Fragment, UriKind.Relative);
}
return RelativeUrl;
}
Uri MakeRelativeUrl(Uri PageUrl, string HRef)
{
Uri LinkUrl = new Uri(HRef, UriKind.RelativeOrAbsolute);
return MakeRelativeUrl(PageUrl, LinkUrl);
}
サイト内リンクを相対URLに変換するのも、やってみるとなかなか大変だ。
(2018/11/10 初稿)