ASP.NET: будет ли сохранение XmlDocument в Response.OutputStream соответствовать кодировке? - PullRequest
4 голосов
/ 13 февраля 2009

Я хочу отправить 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);

}

Что, если я изменил кодировку на что-то другое, Юникод , например:

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");

Ответы [ 2 ]

14 голосов
/ 13 февраля 2009

Я нашел это.

Ответ отрицательный: 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 это, потому что это:

    • не соответствует указанной кодировке
    • пустая трата памяти

Подводя итог: сохраняя в 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 . e.g.:

     <?xml version="1.0" encoding="UTF-8"?>

Если в объявлении xml указана кодировка "UTF-8", то Save (stream) будет использовать кодировку UTF-8 .

Если кодировка не указана , например ::1010*

<?xml version="1.0"?>

или узел объявления xml полностью пропущен, тогда по умолчанию XmlDocument будет UTF-8 кодировка в юникоде. (* * Ссылка тысяча восемьдесят пять * 1 086 *)

Если атрибут кодирования не включено кодирование 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

Примечание : Атрибут кодирования не чувствителен к регистру:

В отличие от большинства атрибутов XML, кодировка значения атрибута не с учетом регистра. Это потому что имена кодирующих символов соответствуют ISO и интернет назначенные номера Органы власти (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. (* +1146 * Ссылка * * тысяча сто сорок семь)

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

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


В моем конкретном примере я пишу обратно клиенту Http через ASP.NET. я хочу установить для типа 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>
0 голосов
/ 13 февраля 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...