ASP.NET: будет ли при сохранении XmlDocument в Response.OutputStream соблюдаться кодировка?

я хочу отправить xml объекта XmlDocument HTTP-клиенту, но меня беспокоит, что предлагаемое решение может не учитывать кодировку, установленную для 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");

person Ian Boyd    schedule 13.02.2009    source источник


Ответы (2)


я нашел это.

Ответ - нет: XmlDocument не будет учитывать ContentEncoding потока ответа, в который он пишет.


Обновление: как это сделать

  1. Используйте Response.Output и НЕ Response.OutputStream.

    Оба являются потоками, но Output - это TextWriter.

    Когда XmlDocument сохраняется в TextWriter, он будет использовать кодировку, указанную в TextWriter. XmlDocument автоматически изменит любой узел декларации xml, то есть:

    ‹? Xml version =" 1.0 "encoding =" ISO-8859-1 "?>

    чтобы соответствовать кодировке, используемой настройкой кодировки Response.Output.

  2. Параметры кодировки Response.Output TextWriter определяются значением Response.ContentEncoding.

  3. Используйте doc.Save, не Response.Write(doc.ToString()) или Response.Write(doc.InnerXml)

    Вы НЕ хотите сохранять xml в строку или вставлять xml в строку и response.Write это, потому что это:

    • doesn't follow the encoding specified
    • тратит память

Подводя итог: при сохранении в 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 по умолчанию будет использовать кодировку Unicode UTF-8. (Справочник)

Если атрибут кодировки не включен, при записи или сохранении документа предполагается кодировка 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 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 не имеет атрибута кодировки, сохраненный документ также не будет иметь его.

Примечание. Если XmlDocument сохраняется в TextWriter, то используемая кодировка берется из объекта TextWriter. Кроме того, атрибут кодировки узла объявления xml (если он присутствует) будет заменен кодировкой TextWriter по мере записи содержимого в TextWriter. (Ссылка)

Кодировка TextWriter определяет записываемую кодировку (кодировка узла XmlDeclaration заменяется кодировкой TextWriter). Если в TextWriter не указана кодировка, XmlDocument сохраняется без атрибута кодировки.

При сохранении в строку используемая кодировка определяется атрибутом кодировки узла объявления xml, если он присутствует.


В моем конкретном примере я отвечаю на Http-клиент через ASP.NET. Я хочу установить для типа 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:

<?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>
person Ian Boyd    schedule 13.02.2009

Первые 2 ссылки из Google

Как: выбрать кодировку для глобализации веб-страницы ASP.NET: http://msdn.microsoft.com/en-us/library/hy4kkhe0.aspx

Элемент глобализации (схема настроек ASP.NET): http://msdn.microsoft.com/en-us/library/hy4kkhe0.aspx

person Alex Reitbort    schedule 13.02.2009