Jag bloggar numera på http://blog.dileno.com ».

Prenumerera på RSS

ASP.NET, XML och teckenkodning

Jag gjorde en djupdykning i ASP.NETs XML-hantering när jag skulle skrev inlägget om hur du skapar ett RSS-flöde i ASP.NET. Jag stötte på problem gällande framför allt teckenkodningen i XML-dokument och tänkte nu dela med mig av mina erfarenheter.

XmlTextWriter ger dig UTF-16

Använder du dig av XmlTextWriter tillsammans med StringWriter, så kommer XML-dokumentet du skapar att få teckenkodningen UTF-16, i stället för UTF-8 som oftast är önskvärt.

Detta beror på att en sträng i .NET alltid är UTF-16.

XML-deklarationen för ett XML-dokument som har teckenkodningen UTF-16 ser ut så här:

<?xml version="1.0" encoding="utf-16"?>

Det finns flera problem med UTF-16. Till att börja med renderas XML-dokument med UTF-16 ironiskt nog inte alls i Internet Explorer 7, utan ger i stället Feed code error. Detta är bra att ha i minnet, för att spara tid vid framtida felsökning.

Tittar man sedan närmre på StringWriter inser man att den ärver från TextWriter, som XmlTextWriter accepterar som indata. TextWriter har egenskapen Encoding för att hantera teckenkodning – men denna egenskap är read-only, vilket gör att man inte kan sätta en teckenkodning.

Detta lämnar två alternativ för att få teckenkodningen UTF-8:

  • Använd MemoryStream
  • Skapa en klass som ärver från StringWriter och tillåter att Encoding-egenskapen sätts

MemoryStream och StreamWriter

Med MemoryStream och StreamWriter kan du skicka ut XML-data med UTF-8. Det finns två metoder som fungerar bra för detta, och en metod som inte fungerar lika bra.

Alla tre metoder går ut på att man instansierar en MemoryStream och en StreamWriter och sedan använder sig av StreamWritern tillsammans med XmlTextReader:

MemoryStream ms = new MemoryStream();
StreamWriter objWriter = new StreamWriter(ms);

XmlWriter objXml = XmlWriter.Create(objWriter, settings);

Skillnaden är sedan metoden för att skriva ut själva XML-dokumentet. Här är följande tre metoder som alla skriver ut innehållet i MemoryStream-strömmen:

  1. ToBuffer

    Encoding.UTF8.GetString(ms.ToBuffer())

  2. ToArray

    Encoding.UTF8.GetString(ms.ToArray())

  3. StreamReader

    StreamReader objReader = new StreamReader(ms);
    ms.Seek(0, SeekOrigin.Begin);
    string rssFeed = objReader.ReadToEnd();

ToBuffer()-metoden kan till en början verka fungera, men rekommenderas inte. Den skapar tomt utrymme i XML-datat och gör så att XML-dokumentet inte validerar – och i Internet Explorer 7 inte ens visas!

För att XML-datat ska visas bör du använda ToArray() i stället, eller i vissa fall när du närmre vill specifiera vad som ska visas från XML:en – använda dig av en StreamReader.

Modiferad StringWriter-klass med Encoding

En snitsig lösning på problemet med att kunna sätta teckenkodning för en StringWriter är att helt enkelt skapa en egen klass som ärver från StringWriter och tillåter att en specifik teckenkodning sätts. Så här ser den klassen ut:

public sealed class StringWriterWithEncoding : StringWriter
{
private readonly Encoding encoding;

public StringWriterWithEncoding(Encoding encoding)
{
this.encoding = encoding;
}

public override Encoding Encoding
{
get { return encoding; }
}
}

Glöm inte att lägga till using-direktiv för System.IO och System.Text. Du använder sedan StringWriterWithEncoding-objektet så här:

StringWriterWithEncoding objWriter = new StringWriterWithEncoding(Encoding.UTF8);

Mer läsning

Det finns en hel del intressant läsning om ASP.NET, XML och teckenkodning. Nedanstående rekommenderas för närmre läsning:

Till sidhuvudet

Clicky Web Analytics