ASP.NET:将 XmlDocument 保存到 Response.OutputStream 会遵守编码吗?

标签 asp.net xml unicode xmldocument

我想将 XmlDocument 对象的 xml 发送到 HTTP 客户端,但我担心 suggested soltuion 可能不遵守 Response 已设置为使用的编码:

public void ProcessRequest(HttpContext context)
{
   XmlDocument doc = GetXmlToShow(context);

   context.Response.ContentType = "text/xml";
   context.Response.ContentEncoding = System.Text.Encoding.UTF8;
   context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
   context.Response.Cache.SetAllowResponseInBrowserHistory(true);

   doc.Save(context.Response.OutputStream);

}

如果我将编码更改为其他内容,例如 Unicode 会怎样:
public void ProcessRequest(HttpContext context)
{
   XmlDocument doc = GetXmlToShow(context);

   context.Response.ContentType = "text/xml";
   context.Response.ContentEncoding = System.Text.Encoding.Unicode;
   context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
   context.Response.Cache.SetAllowResponseInBrowserHistory(true);

   doc.Save(context.Response.OutputStream);
}
Response.OutputStream 是否会即时转换写入其中的二进制数据,并使其成为 Unicode?

或者 Response.ContentEncoding 只是提供信息?

如果 ContentEncoding 只是提供信息,后面的文本字符串将返回什么内容编码?
context.Response.ContentEncoding = System.Text.Encoding.Unicode;
context.Response.Write("Hello World");

context.Response.ContentEncoding = System.Text.Encoding.UTF8;
context.Response.Write("Hello World");

context.Response.ContentEncoding = System.Text.Encoding.UTF16;
context.Response.Write("Hello World");

context.Response.ContentEncoding = System.Text.Encoding.ASCII;
context.Response.Write("Hello World");

context.Response.ContentEncoding = System.Text.Encoding.BigEndianUnicode;
context.Response.Write("Hello World");

最佳答案

我找到了。

答案是否定的:XmlDocument 不会遵守它写入的响应流的 ContentEncoding。

更新:正确的方法

  • 使用 Response.Output 而不是 Response.OutputStream

    两者都是流,但 OutputTextWriter

    XmlDocument 将自身保存到 TextWriter 时,它​​将使用编码
    TextWriter 指定。 XmlDocument 将自动更改任何
    xml 声明节点,即:



    匹配 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 编码。 ( Reference )

    If an encoding attribute is not included, UTF-8 encoding is assumed when the document is written or saved out.



    您也可以在 xml 声明中使用的 Some common encodings strings 是:
  • 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

  • 注意 :编码属性不区分大小写:

    Unlike most XML attributes, encoding attribute values are not case-sensitive. This is because encoding character names follow ISO and Internet Assigned Numbers Authority (IANA) standards.



    如果从字符串或文件加载 XML,并且它不包含 xml 声明节点,则可以使用 manually add one to the 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 的编码。 ( Reference )

    The encoding on the TextWriter determines the encoding that is written out (The encoding of the XmlDeclaration node is replaced by the encoding of the TextWriter). If there was no encoding specified on the TextWriter, the XmlDocument is saved without an encoding attribute.



    如果保存为字符串,则使用的编码由 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>
    

    关于ASP.NET:将 XmlDocument 保存到 Response.OutputStream 会遵守编码吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/546994/

    相关文章:

    c# - 自定义错误处理 Asp.Net

    c# - 使用授权管理器 (AzMan) 获取属于某个角色的用户列表

    python - 如何在 python lxml 包中的 XPATH 表达式中设置数组索引

    Java 和统一码

    mysql - Rails 应用程序的 utf8mb4 字符集

    c# - 在 JQuery 对话框中加载动态数据并出现 ASP.NET 回发问题

    c# - 在 c#back end 中使用 linq 在 asp.net 中搜索关键字

    java - 使用 myBatis 映射嵌套的 Oracle CURSOR (ResultSet)

    Android Studio lint.xml 配置

    python - PyGame 中的中文 unicode 字体