我找到了。
答案是否定的:XmlDocument 将不遵守它正在写入的响应流的 ContentEncoding。
更新:正确的方法
使用Response.Output
,而不是 Response.OutputStream
。
两者都是流,但Output
都是TextWriter
.
当 aXmlDocument
将自己保存到 aTextWriter
时,它将使用TextWriter
. 将XmlDocument
自动更改任何 xml 声明节点,即:
<?xml 版本="1.0" 编码="ISO-8859-1"?>
匹配 的编码Response.Output
设置使用的编码。
的Response.Output
TextWriter
编码设置来自
Response.ContentEncoding
值。
使用doc.Save
, not Response.Write(doc.ToString())
或Response.Write(doc.InnerXml)
您不想将xml保存到字符串中,或者将 xml 填充到字符串response.Write
中,因为:
总结一下:通过保存到 a 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 编码。(参考)
如果不包含编码属性,则在写入或保存文档时采用 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
注意:编码属性不区分大小写:
与大多数 XML 属性不同,编码属性值不区分大小写。这是因为编码字符名称遵循 ISO 和 Internet 号码分配机构 (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 声明没有编码属性,则保存的文档也没有。
注意:如果 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,其编码值遵循您为 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>