見つけた。
答えはノーです。XmlDocument は、書き込み先の応答ストリームの ContentEncoding を尊重しません。
更新:それを行う適切な方法
Response.Output
およびNOT を使用しResponse.OutputStream
ます。
どちらもストリームですOutput
が、TextWriter
.
XmlDocument
が自身を に保存するとき、TextWriter
で指定されたエンコーディングを使用しますTextWriter
。XmlDocument
は、xml 宣言ノードを自動的に変更します。つまり、次のようになります。
<?xml version="1.0" encoding="ISO-8859-1"?>
のエンコーディング設定で使用されるエンコーディングと一致させResponse.Output
ます。
のResponse.Output
TextWriter
エンコーディング設定は
Response.ContentEncoding
値から取得されます。
を使用するdoc.Save
、または使用しない Response.Write(doc.ToString())
Response.Write(doc.InnerXml)
xml を文字列に保存したり、xml を文字列に詰め込んだりする必要はありませんresponse.Write
。
- 指定されたエンコーディングに従っていません
- メモリを無駄にします
要約すると、次のように保存されますTextWriter
: XML 宣言ノード、XML コンテンツ、および HTML 応答のコンテンツ エンコーディングがすべて一致します。
サンプルコード:
public class Handler : IHttpHandler, System.Web.SessionState.IRequiresSessionState
{
//Note: We add IRequiesSessionState so that we'll have access to context.Session object
//Otherwise it will be null
public void ProcessRequest(HttpContext context)
{
XmlDocument doc = GetXmlToShow(context); //GetXmlToShow will look for parameters from the context
if (doc != null)
{
context.Response.ContentType = "text/xml"; //must be 'text/xml'
context.Response.ContentEncoding = System.Text.Encoding.UTF8; //we'd like utf-8
doc.Save(context.Response.Output); //doc save itself to the textwriter, using the encoding of the text-writer (which comes from response.contentEncoding)
}
#region Notes
/*
* 1. Use Response.Output, and NOT Response.OutputStream.
* Both are streams, but Output is a TextWriter.
* When an XmlDocument saves itself to a TextWriter, it will use the encoding
* specified by the TextWriter. The XmlDocument will automatically change any
* xml declaration node, i.e.:
* <?xml version="1.0" encoding="ISO-8859-1"?>
* to match the encoding used by the Response.Output's encoding setting
* 2. The Response.Output TextWriter's encoding settings comes from the
* Response.ContentEncoding value.
* 3. Use doc.Save, not Response.Write(doc.ToString()) or Response.Write(doc.InnerXml)
* 3. You DON'T want to Save the xml to a string, or stuff the xml into a string
* and response.Write that, because that
* - doesn't follow the encoding specified
* - wastes memory
*
* To sum up: by Saving to a TextWriter: the XML Declaration node, the XML contents,
* and the HTML Response content-encoding will all match.
*/
#endregion Notes
}
public bool IsReusable { get { return false; } }
}
ストリームに保存するときに XmlDocument が使用するエンコーディングは、xml 宣言ノードで指定されたエンコーディングによって異なります。例えば:
<?xml version="1.0" encoding="UTF-8"?>
xml 宣言で「UTF-8」エンコーディングが指定されている場合、Save(stream) はUTF-8エンコーディングを使用します。
エンコーディングが指定されていない場合、例えば:
<?xml version="1.0"?>
または xml 宣言ノードが完全に省略されている場合、XmlDocument はデフォルトでUTF-8 Unicode エンコーディングになります。(参考)
encoding 属性が含まれていない場合、ドキュメントが書き込まれるか保存されるときに UTF-8 エンコーディングが想定されます。
xml 宣言でも使用できるいくつかの一般的なエンコーディング文字列は次のとおりです。
- UTF-8
- UTF-16
- ISO-10646-UCS-2
- ISO-10646-UCS-4
- ISO-8859-1
- ISO-8859-2
- ISO-8859-3
- ISO-8859-4
- ISO-8859-5
- ISO-8859-6
- ISO-8859-7
- ISO-8859-8
- ISO-8859-9
- ISO-2022-JP
- Shift_JIS
- EUC-JP
注: encoding 属性は大文字と小文字を区別しません。
ほとんどの XML 属性とは異なり、エンコーディング属性値では大文字と小文字が区別されません。これは、エンコーディング文字名が ISO および Internet Assigned Numbers Authority (IANA) 標準に従っているためです。
文字列またはファイルから XML をロードし、xml 宣言ノードが含まれていない場合は、次を使用して XmlDocument に手動で追加できます。
// Create an XML declaration.
XmlDeclaration xmldecl;
xmldecl = doc.CreateXmlDeclaration("1.0", null, null);
xmldecl.Encoding="UTF-8";
// Add the new node to the document.
XmlElement root = doc.DocumentElement;
doc.InsertBefore(xmldecl, root);
XmlDocument に xml 宣言がない場合、または xml 宣言に encoding 属性がない場合、保存されたドキュメントにもそれはありません。
注: XmlDocument が TextWriter に保存されている場合、使用されるエンコーディングは TextWriter オブジェクトから取得されます。さらに、xml 宣言ノードのエンコーディング属性 (存在する場合) は、コンテンツが TextWriter に書き込まれるときに、TextWriter のエンコーディングに置き換えられます。(参考)
TextWriter のエンコーディングによって、書き出されるエンコーディングが決まります (XmlDeclaration ノードのエンコーディングは、TextWriter のエンコーディングに置き換えられます)。TextWriter でエンコーディングが指定されていない場合、XmlDocument はエンコーディング属性なしで保存されます。
文字列に保存する場合、使用されるエンコーディングは、xml 宣言ノードのエンコーディング属性 (存在する場合) によって決定されます。
私の具体的な例では、ASP.NET を介して Http クライアントに書き戻しています。Response.Encoding タイプを適切な値に設定したいのですが、XML 自体に含まれるものと一致させる必要があります。
これを行う適切な方法は、xml を Response.OutputStream ではなく Response.Output に保存することです。Response.Output は TextWriter であり、その Encoding 値は Response.Encoding に設定した値に従います。
言い換えると:
context.Response.ContentEncoding = System.Text.Encoding.ASCII;
doc.Save(context.Response.Output);
xml の結果:
<?xml version="1.0" encoding="us-ascii" ?>
<foo>Hello, world!</foo>
その間:
context.Response.ContentEncoding = System.Text.Encoding.UTF8;
doc.Save(context.Response.Output);
xml の結果:
<?xml version="1.0" encoding="utf-8" ?>
<foo>Hello, world!</foo>
と
context.Response.ContentEncoding = System.Text.Encoding.Unicode;
doc.Save(context.Response.Output);
xml の結果:
<?xml version="1.0" encoding="utf-16" ?>
<foo>Hello, world!</foo>