2009-01-09 41 views
33

我有一个函数创建一些的XmlDocument:如何将编码属性添加到xml其他与UTF-16和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(); 
} 

我设置编码,但之后,我创建的XmlWriter它确实有UTF-16编码。我知道这是因为字符串(和StringBuilder,我想)在UTF-16编码,你不能改变它。
那么我怎样才能轻松地创建这个XML编码属性设置为“Windows-1250”?它甚至不需要在这种编码中编码,它只需要具有指定的属性。

编辑:它必须在.Net 2.0,所以任何新的框架元素不能使用。

+0

我知道这不可能是正确的做法,但我用blahblah.Replace(“UTF-16”,“UTF-8”)时,我想回报我的XML字符串,它为我工作:d – 2017-08-08 17:35:55

回答

65

您需要使用适当编码的StringWriter。不幸的StringWriter不会让你直接指定编码,所以你需要这样一个类:(This question类似,但并不完全是重复的)

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

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

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

编辑:要回答的评论:通将StringWriterWithEncoding改为XmlWriter.Create而不是StringBuilder,然后在最后调用ToString()。

+0

以及它是一个严谨的写作者,我以前看过这篇文章(在另一个话题中),但我不知道我能做些什么。 – agnieszka 2009-01-09 11:27:34

+0

你能解释我怎么用它? – agnieszka 2009-01-09 11:33:17

3

我其实解决了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; 
     } 
5

只是一些额外的解释,为什么会这样。

字符串是字符序列,而不是字节。字符串本身不是“编码的”,因为它们使用的字符是以Unicode码点存储的。编码不会在字符串级别进行SENSE。

编码是从一系列代码点(字符)到一系列字节(用于存储在基于字节的系统,如文件系统或内存中)的映射。该框架不允许指定编码,除非有令人信服的理由,例如使16位代码点适合基于字节的存储。

因此,当您尝试将XML写入StringBuilder时,实际上是在构建一个XML字符序列并将它们编写为一系列字符,因此不会执行编码。所以没有Encoding字段。

如果您想使用编码,XmlWriter必须写入流。

关于您使用MemoryStream找到的解决方案,没有任何意图,但它只是在手臂上移动并移动热空气。你用'windows-1252'编码你的代码点,然后解析它回代码点。唯一可能发生的变化是未在windows-1252中定义的字符被转换为'?'字符在这个过程中。

对我来说,正确的解决方案可能是以下一种。根据您的函数的用途,您可以将Stream作为参数传递给您的函数,以便调用方决定是将它写入内存还是写入文件。所以这将是这样写的:


     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

我解决了矿山的字符串输出到一个变量,然后用UTF-8,将任何引用为UTF-16(我的应用程序需要UTF8编码)。既然你使用了一个函数,你可以做类似的事情。我主要使用VB.net,但我认为C#看起来像这样。

return builder.ToString().Replace("utf-16", "utf-8");