带有汉字文本内容的 XmlDocument 未使用 XmlTextWriter 正确编码为 ISO-8859-1



我有一个在其文本内容中包含汉字的XmlDocument,我需要使用 ISO-8859-1 编码将其写入流。 当我这样做时,没有一个汉字字符被正确编码,而是被替换为"??"。

下面是演示如何从XmlDocument编写 XML 的示例代码:

MemoryStream mStream = new MemoryStream();
Encoding enc = Encoding.GetEncoding("ISO-8859-1");
XmlTextWriter writer = new XmlTextWriter(mStream,enc);
doc.WriteTo(writer);
writer.Flush();
mStream.Flush();
mStream.Position = 0;
StreamReader sReader = new StreamReader(mStream, enc);
String formattedXML = sReader.ReadToEnd();

在这种特定情况下,可以做些什么来正确编码汉字?

如注释中所述,显示?字符是因为编码ISO-8859-1不支持汉字字符,因此它将?替换为回退字符。 编码回退在Encoding的文档备注中讨论:

请注意,编码类允许错误(不支持的字符)执行以下操作:

  • 静默地更改为"?"字符。
  • 使用"最合适"字符。
  • 通过使用带有 U+FFFD Unicode 替换字符的EncoderFallbackDecoderFallback类更改为特定于应用程序的行为。

这就是您所看到的行为。

但是,即使ISO-8859-1不支持汉字字符,您也可以通过切换到XmlWriter.Create(Stream, XmlWriterSettings)返回的较新XmlWriter并在XmlWriterSettings.Encoding上设置编码来获得更好的结果,如下所示:

MemoryStream mStream = new MemoryStream();
var enc = Encoding.GetEncoding("ISO-8859-1");
var settings = new XmlWriterSettings
{
Encoding = enc,
CloseOutput = false,
// Remove to enable the XML declaration if you want it.  XmlTextWriter doesn't include it automatically.
OmitXmlDeclaration = true,  
};
using (var writer = XmlWriter.Create(mStream, settings))
{
doc.WriteTo(writer);
}
mStream.Position = 0;
var sReader = new StreamReader(mStream, enc);
var formattedXML = sReader.ReadToEnd();

通过设置Encoding属性XmlWriterSettings,只要当前编码不支持某个字符,XML 编写器就会被通知,并自动将其替换为 XML 字符实体引用,而不是一些硬编码的回退。

例如,假设您有如下所示的 XML:

<Root>
<string>畑 はたけ hatake "field of crops"</string>
</Root>

然后,您的代码将输出以下内容,将所有汉字映射到单个回退字符:

<Root><string>? ??? hatake "field of crops"</string></Root>

而新版本将输出:

<Root><string>&#x7551; &#x306F;&#x305F;&#x3051; hatake "field of crops"</string></Root>

请注意,汉字字符已替换为字符实体,例如&#x7551;? 所有兼容的 XML 解析器都将识别并重建这些字符,因此,尽管您的首选编码不支持汉字,但不会丢失任何信息。

最后,作为旁注,XmlTextWriter的文档指出:

从 .NET Framework 2.0 开始,我们建议您改用 System.Xml.XmlWriter 类。

因此,用XmlWriter替换它通常是一个好主意。

示例 .Net 小提琴演示了这两个编写器的用法,并断言XmlWriter生成的 XML 在语义上等效于原始 XML,尽管字符进行了转义。

最新更新