HTMLのデコードにWebUtilty.HtmlDecode
を使用していました。たとえば、–
は「–」文字にデコードされることになっていますが、WebUtilty.HtmlDecode
はそれをデコードしません。ただし、HttpUtilty.HtmlDecode
はサポートします。
Debug.WriteLine(WebUtility.HtmlDecode("–"));
Debug.WriteLine(HttpUtility.HtmlDecode("–"));
> –
> –
これらの両方のドキュメントは同じです:HTTP送信用にHTMLエンコードされた文字列をデコードされた文字列に変換します。
なぜそれらが異なるのか、どちらを使用する必要があるのか、および「–」を正しくデコードするためにWebUtility.HtmlDecodeに切り替えると何が変わるのですか?
2つのメソッドの実装は、Windows Phoneでは実際に異なります。
WebUtility.HtmlDecode:
public static void HtmlDecode(string value, TextWriter output)
{
if (value != null)
{
if (output == null)
{
throw new ArgumentNullException("output");
}
if (!StringRequiresHtmlDecoding(value))
{
output.Write(value);
}
else
{
int length = value.Length;
for (int i = 0; i < length; i++)
{
bool flag;
uint num4;
char ch = value[i];
if (ch != '&')
{
goto Label_01B6;
}
int num3 = value.IndexOfAny(_htmlEntityEndingChars, i + 1);
if ((num3 <= 0) || (value[num3] != ';'))
{
goto Label_01B6;
}
string entity = value.Substring(i + 1, (num3 - i) - 1);
if ((entity.Length <= 1) || (entity[0] != '#'))
{
goto Label_0188;
}
if ((entity[1] == 'x') || (entity[1] == 'X'))
{
flag = uint.TryParse(entity.Substring(2), NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out num4);
}
else
{
flag = uint.TryParse(entity.Substring(1), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out num4);
}
if (flag)
{
switch (_htmlDecodeConformance)
{
case UnicodeDecodingConformance.Strict:
flag = (num4 < 0xd800) || ((0xdfff < num4) && (num4 <= 0x10ffff));
goto Label_0151;
case UnicodeDecodingConformance.Compat:
flag = (0 < num4) && (num4 <= 0xffff);
goto Label_0151;
case UnicodeDecodingConformance.Loose:
flag = num4 <= 0x10ffff;
goto Label_0151;
}
flag = false;
}
Label_0151:
if (!flag)
{
goto Label_01B6;
}
if (num4 <= 0xffff)
{
output.Write((char) num4);
}
else
{
char ch2;
char ch3;
ConvertSmpToUtf16(num4, out ch2, out ch3);
output.Write(ch2);
output.Write(ch3);
}
i = num3;
goto Label_01BD;
Label_0188:
i = num3;
char ch4 = HtmlEntities.Lookup(entity);
if (ch4 != '\0')
{
ch = ch4;
}
else
{
output.Write('&');
output.Write(entity);
output.Write(';');
goto Label_01BD;
}
Label_01B6:
output.Write(ch);
Label_01BD:;
}
}
}
}
HttpUtility.HtmlDecode:
public static string HtmlDecode(string html)
{
if (html == null)
{
return null;
}
if (html.IndexOf('&') < 0)
{
return html;
}
StringBuilder sb = new StringBuilder();
StringWriter writer = new StringWriter(sb, CultureInfo.InvariantCulture);
int length = html.Length;
for (int i = 0; i < length; i++)
{
char ch = html[i];
if (ch == '&')
{
int num3 = html.IndexOfAny(s_entityEndingChars, i + 1);
if ((num3 > 0) && (html[num3] == ';'))
{
string entity = html.Substring(i + 1, (num3 - i) - 1);
if ((entity.Length > 1) && (entity[0] == '#'))
{
try
{
if ((entity[1] == 'x') || (entity[1] == 'X'))
{
ch = (char) int.Parse(entity.Substring(2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture);
}
else
{
ch = (char) int.Parse(entity.Substring(1), CultureInfo.InvariantCulture);
}
i = num3;
}
catch (FormatException)
{
i++;
}
catch (ArgumentException)
{
i++;
}
}
else
{
i = num3;
char ch2 = HtmlEntities.Lookup(entity);
if (ch2 != '\0')
{
ch = ch2;
}
else
{
writer.Write('&');
writer.Write(entity);
writer.Write(';');
continue;
}
}
}
}
writer.Write(ch);
}
return sb.ToString();
}
興味深いことに、WebUtilityはWP7には存在しません。また、WebUtilityのWP8実装はデスクトップのものと同じです。 HttpUtility.HtmlDecode
のデスクトップ実装は、WebUtility.HtmlDecode
の単なるラッパーです。最後に重要なことですが、Silverlight 5はHttpUtility.HtmlDecode
の実装がWindows Phoneと同じであり、WebUtilityを実装していません。
Windows Phone 7ランタイムはSilverlightに基づいているため、WP7はSilverlightバージョンのHttpUtility.HtmlDecode
を継承しており、WebUtilityは存在しませんでした。その後、WP8が登場しました。そのランタイムはWinRTに基づいています。 WinRTはWebUtilityをもたらし、古いバージョンのHttpUtility.HtmlDecode
はレガシーWP7アプリとの互換性を確保するために維持されました。
どちらを使用するかを知るために... WP7をターゲットにしたい場合は、HttpUtility.HtmlDecode
を使用するしかありません。 WP8をターゲットにしている場合は、ニーズに最も適した動作のメソッドを選択するだけです。 Microsoftが次期バージョンのWindows PhoneでSilverlightランタイムを廃止することを決定した場合に備えて、WebUtilityはおそらく将来性のある選択です。ただし、質問に入力した例を手動でサポートすることを心配する必要がないように、HttpUtilityを選択するという実際的な選択をそのまま使用します。
メソッドまったく同じ。さらに、それらを逆コンパイルしようとすると、実装が別の実装からコピーされたように見えます。
違いは使用目的のみです。 HttpUtility
はSystem.Web
アセンブリに含まれており、このアセンブリで構築されるASP.netアプリケーションで使用されることが期待されています。 WebUtility
は、ほぼすべてのアプリケーションによって参照されるSystem
アセンブリに含まれており、より一般的な目的またはクライアントの使用のために提供されています。
検索でこれを見つけた人に通知するだけです。質問で言及されている関数を使用しますが、Windows.Data.Html.HtmlUtilities.ConvertToText(string input)
は使用しないでください。 WebUtilty.HtmlDecode
より70倍遅く、クラッシュが発生します。クラッシュは、DevCenterではmshtml!IEPeekMessage
という名前になります。この関数はInternetExplorerを呼び出して文字列を変換するように見えます。ただそれを避けなさい。