2009-01-09 22 views
33

Tôi đã có một chức năng tạo ra một số XmlDocument:Làm cách nào để đặt thuộc tính mã hóa thành xml khác mà utf-16 bằng XmlWriter?

public string CreateOutputXmlString(ICollection<Field> fields) 
{ 
    XmlWriterSettings settings = new XmlWriterSettings(); 
    settings.Indent = true; 
    settings.Encoding = Encoding.GetEncoding("windows-1250"); 

    StringBuilder builder = new StringBuilder(); 
    XmlWriter writer = XmlWriter.Create(builder, settings); 

    writer.WriteStartDocument(); 
    writer.WriteStartElement("data"); 
    foreach (Field field in fields) 
    { 
     writer.WriteStartElement("item"); 
     writer.WriteAttributeString("name", field.Id); 
     writer.WriteAttributeString("value", field.Value); 
     writer.WriteEndElement(); 
    } 
    writer.WriteEndElement(); 
    writer.Flush(); 
    writer.Close(); 

    return builder.ToString(); 
} 

tôi đặt một mã hóa nhưng sau khi tôi tạo XmlWriter nó có utf-16 mã hóa. Tôi biết đó là bởi vì chuỗi (và StringBuilder tôi giả sử) được mã hóa trong utf-16 và bạn không thể thay đổi nó.
Vậy làm thế nào tôi có thể dễ dàng tạo xml này với thuộc tính mã hóa được đặt thành "windows-1250"? nó thậm chí không phải được mã hóa trong mã hóa này, nó chỉ cần có thuộc tính được chỉ định.

chỉnh sửa: nó phải ở trong .Net 2.0 nên mọi phần tử khung công tác mới đều không thể sử dụng được.

+0

Tôi biết nó không thể là một cách đúng đắn nhưng tôi sử dụng blahblah.Replace ("utf-16", "utf-8") khi tôi muốn trở lại chuỗi xml của tôi và nó làm việc cho tôi: D –

Trả lời

65

Bạn cần sử dụng StringWriter với mã hóa thích hợp. Thật không may StringWriter không cho phép bạn xác định mã hóa trực tiếp, vì vậy bạn cần một lớp học như thế này: (. This question là tương tự nhưng không hoàn toàn là một bản sao)

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

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

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

EDIT: Để trả lời bình luận: vượt qua StringWriterWithEncoding thành XmlWriter.Create thay vì StringBuilder, sau đó gọi ToString() trên nó ở cuối.

+0

cũng là một strinWriter, tôi đã nhìn thấy bài đăng này trước (trong một chủ đề khác) nhưng tôi không thực sự biết những gì tôi có thể sử dụng làm cho nó. – agnieszka

+0

bạn có thể vui lòng giải thích làm thế nào tôi có thể sử dụng nó? – agnieszka

+0

Xem chỉnh sửa của tôi ở cuối. Chỉ cần thay đổi StringBuilder của bạn thành StringWriterWithEncoding (chuyển sang mã hóa bạn muốn) và bạn đã hoàn tất. –

3

Tôi thực sự giải quyết được vấn đề với MemoryStream:

public static string CreateOutputXmlString(ICollection<Field> fields) 
     { 
      XmlWriterSettings settings = new XmlWriterSettings(); 
      settings.Indent = true; 
      settings.Encoding = Encoding.GetEncoding("windows-1250"); 

      MemoryStream memStream = new MemoryStream(); 
      XmlWriter writer = XmlWriter.Create(memStream, settings); 

      writer.WriteStartDocument(); 
      writer.WriteStartElement("data"); 
      foreach (Field field in fields) 
      { 
       writer.WriteStartElement("item"); 
       writer.WriteAttributeString("name", field.Id); 
       writer.WriteAttributeString("value", field.Value); 
       writer.WriteEndElement(); 
      } 
      writer.WriteEndElement(); 
      writer.Flush(); 
      writer.Close(); 

      writer.Flush(); 
      writer.Close(); 

      string xml = Encoding.GetEncoding("windows-1250").GetString(memStream.ToArray()); 

      memStream.Close(); 
      memStream.Dispose(); 

      return xml; 
     } 
+1

Nếu bạn định sử dụng MemoryStream, ít nhất bạn nên giải mã nó bằng cùng một mã hóa mà bạn đang sử dụng trước đó (ví dụ: Windows-1250, * not * ASCII). Tôi thích phiên bản của tôi, cá nhân :) –

5

Chỉ cần một số giải thích thêm tại sao điều này là như vậy.

Chuỗi là chuỗi ký tự, không phải byte. Các chuỗi, mỗi phần tử, không được "mã hóa", bởi vì chúng đang sử dụng các ký tự, được lưu trữ dưới dạng các điểm mã Unicode. Mã hóa KHÔNG LÀM SENSE ở cấp Chuỗi.

Mã hóa là ánh xạ từ một chuỗi các điểm (ký tự) đến một chuỗi byte (để lưu trữ trên các hệ thống dựa trên byte như hệ thống tệp hoặc bộ nhớ). Khung công tác không cho phép bạn chỉ định các mã hóa, trừ khi có lý do thuyết phục, giống như để tạo các điểm mã 16 bit phù hợp với lưu trữ dựa trên byte. Vì vậy, khi bạn đang cố gắng viết XML của bạn vào một StringBuilder, bạn đang thực sự xây dựng một chuỗi ký tự XML và viết chúng như một chuỗi các ký tự, vì vậy không có mã hóa nào được thực hiện. Do đó, không có trường mã hóa.

Nếu bạn muốn sử dụng mã hóa, XmlWriter phải ghi vào Luồng.

Về giải pháp mà bạn tìm thấy với MemoryStream, không có ý định phạm tội, nhưng nó chỉ đập quanh cánh tay và di chuyển không khí nóng. Bạn đang mã hóa các điểm mã của bạn bằng 'windows-1252' và sau đó phân tích cú pháp nó trở lại các điểm mã. Sự thay đổi duy nhất có thể xảy ra là các ký tự không được định nghĩa trong windows-1252 được chuyển thành '?' trong quá trình này.

Với tôi, giải pháp phù hợp có thể là giải pháp sau. Tùy thuộc vào chức năng của bạn được sử dụng, bạn có thể chuyển Luồng dưới dạng tham số cho hàm của bạn, để người gọi quyết định liệu nó có được ghi vào bộ nhớ hay tệp không.Vì vậy, nó sẽ được viết như thế này:


     public static void WriteFieldsAsXmlDocument(ICollection fields, Stream outStream) 
     { 
      XmlWriterSettings settings = new XmlWriterSettings(); 
      settings.Indent = true; 
      settings.Encoding = Encoding.GetEncoding("windows-1250"); 

      using(XmlWriter writer = XmlWriter.Create(outStream, settings)) { 
       writer.WriteStartDocument(); 
       writer.WriteStartElement("data"); 
       foreach (Field field in fields) 
       { 
        writer.WriteStartElement("item"); 
        writer.WriteAttributeString("name", field.Id); 
        writer.WriteAttributeString("value", field.Value); 
        writer.WriteEndElement(); 
       } 
       writer.WriteEndElement(); 
      } 
     } 
4
MemoryStream memoryStream = new MemoryStream(); 
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings(); 
xmlWriterSettings.Encoding = Encoding.UTF8; 

XmlWriter xmlWriter = XmlWriter.Create(memoryStream, xmlWriterSettings); 
xmlWriter.WriteStartDocument(); 
xmlWriter.WriteStartElement("root", "http://www.timvw.be/ns"); 
xmlWriter.WriteEndElement(); 
xmlWriter.WriteEndDocument(); 
xmlWriter.Flush(); 
xmlWriter.Close(); 

string xmlString = Encoding.UTF8.GetString(memoryStream.ToArray()); 

From here

0

tôi giải quyết của tôi bằng cách xuất ra chuỗi cho một biến sau đó thay thế bất kỳ tài liệu tham khảo để utf-16 với utf-8 (ứng dụng của tôi cần UTF8 mã hóa). Vì bạn đang sử dụng một hàm, bạn có thể làm một cái gì đó tương tự. Tôi sử dụng VB.net chủ yếu, nhưng tôi nghĩ rằng C# sẽ trông giống như thế này.

return builder.ToString().Replace("utf-16", "utf-8"); 
Các vấn đề liên quan