我找到了.
答案是否定的:XmlDocument不会尊重它写入的响应流的ContentEncoding.
更新:正确的方法
使用Response.Output
,而不是 Response.OutputStream
.
两者都是流,但是Output
是TextWriter
.
当XmlDocument
将自己保存到a时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.: * * 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声明中指定了"UTF-8"编码,则Save(stream)将使用UTF-8编码.
如果未指定编码,例如:
或者完全省略xml声明节点,然后XmlDocument将默认为UTF-8 unicode编码.(参考)
如果未包含编码属性,则在写入或保存文档时假定为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对象中获取.此外,当内容写入TextWriter时,xml声明节点编码属性(如果存在)将替换为TextWriter的编码.(参考)
TextWriter上的编码确定写出的编码(XmlDeclaration节点的编码由TextWriter的编码替换).如果TextWriter上未指定编码,则保存XmlDocument而不使用编码属性.
如果保存为字符串,则使用的编码由xml声明节点的编码属性(如果存在)确定.
在我的具体示例中,我通过ASP.NET写回Http客户端.我想将Response.Encoding类型设置为适当的值 - 我需要匹配XML本身将包含的内容.
执行此操作的适当方法是将xml保存到Response.Output,而不是Response.OutputStream.Response.Output是一个TextWriter,其Encoding值遵循您为Response.Encoding设置的值.
换一种说法:
context.Response.ContentEncoding = System.Text.Encoding.ASCII; doc.Save(context.Response.Output);
结果为xml:
Hello, world!
而:
context.Response.ContentEncoding = System.Text.Encoding.UTF8; doc.Save(context.Response.Output);
结果为xml:
Hello, world!
和
context.Response.ContentEncoding = System.Text.Encoding.Unicode; doc.Save(context.Response.Output);
结果为xml:
Hello, world!