【问题标题】:XmlDocument.Load() method fails to decode € (euro)XmlDocument.Load() 方法无法解码 €(欧元)
【发布时间】:2010-12-09 14:10:39
【问题描述】:

我有一个 XML 文档 file.xml,它是用 Iso-latin-15(又名 Iso-Latin-9)编码的

<?xml version="1.0" encoding="iso-8859-15"?>
<root xmlns="http://stackoverflow.com/demo">
  <f>€.txt</f>
</root>

从我最喜欢的文本编辑器中,我可以看出该文件以 Iso-Latin-15(它不是 UTF-8)正确编码。

我的软件是用 C# 编写的,想提取元素 f

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("file.xml"); 

在现实生活中,我有一个 XMLResolver 来设置凭据。但基本上,我的代码就是这么简单。加载顺利,我没有引发任何异常。

现在,我提取值时的问题:

//xnsm is the XmlNameSpace manager
XmlNode n = xmlDoc.SelectSingleNode("//root/f", xnsm); 
if (n != null)
  String filename = n.InnerText;

Visual Studio 调试器显示文件名 = □.txt

这可能只是一个 Visual Studio 错误。不幸的是,File.Exists(filename) 返回 false,而文件实际存在。

怎么了?

【问题讨论】:

  • 我已经用 Visual Studio 仔细检查了编码。
  • 您是否尝试过,如果也出现错误,如果您使用的是手动设置编码的 Stream?我会小心“它可能只是一个 Visual Studio 错误”之类的陈述......

标签: c# xml encoding xml-deserialization


【解决方案1】:

如果我没记错的话,XmlDocument.Load(string) 方法总是假定 UTF-8,无论 XML 编码如何。

您必须使用正确的编码创建StreamReader 并将其用作参数。

xmlDoc.Load(new StreamReader(
                     File.Open("file.xml"), 
                     Encoding.GetEncoding("iso-8859-15"))); 

编辑:

我刚刚偶然发现了来自 Microsoft 的 KB308061。有一段很有意思:

在中指定编码声明 XML 的 XML 声明部分 文档。例如,以下 声明表明, 文档采用 UTF-16 Unicode 编码 格式:

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

请注意,此声明仅 指定一个编码格式 XML 文档并且不修改或 控制实际的编码格式 数据

【讨论】:

  • 感谢您的指点。但是,我不能假设输入文件是 Iso-8859-15。
  • 我知道Load() 方法关注xml标头,正如我所想。否则,他们对XmlDocument 的实现会很糟糕。
【解决方案2】:

不要只使用调试器或控制台来显示字符串 as 一个字符串。

相反,转储字符串的内容,一次一个字符。例如:

foreach (char c in filename)
{
    Console.WriteLine("{0}: {1:x4}", c, (int) c);
}

这将根据 Unicode 代码点向您显示字符串的真实内容,而不是受限于当前字体可以显示的内容。

使用Unicode code charts 查找指定的字符。

【讨论】:

  • 不是真正的答案,但这绝对是调试这种情况的好方法。谢谢。现在,我知道有问题的字符是:0080。这是 Unicode 中的控制字符。有趣的是,这就是 Windows-CP1252 中的 Euro sympo。我觉得string内部应该用Unicode实现,这让我越来越觉得XmlDocument实现有bug。
  • @rds:好的,所以你现在知道它肯定没有正确解码。下一站:文件中有什么,以字节为单位? .NET 一般理解 iso-8859-15 吗?
  • +1 我怀疑文件实际上是用windows-1252 编码的,而不是ISO-8859-15。在 XML 查看器(例如 Web 浏览器)中查看时是否显示欧元字符? Windows 和 .NET 确实支持 ISO-8859-15,但很少使用。
  • 结论:是的,输入文件有0x80。
  • @rds:啊哈。好的,根据en.wikipedia.org/wiki/ISO/IEC_8859-15 应该是 0xA4
【解决方案3】:
  1. 您的 xml 是否正确定义了其编码? encoding="iso-8859-15" .. 是 Iso-latin-15

  2. 理想情况下,您应该将内容放在 CDATA 元素中 .. 这样 xml 看起来像 &lt;f&gt;&lt;![CDATA[€.txt]]&gt;&lt;/f&gt;

  3. 理想情况下,您还应该使用等效的 url 编码(或 http 编码)值转义所有特殊字符,因为 xml 通常用于通过 http 进行通信。

我不知道 € .. 的确切转义码,但应该是这样的

<f><![CDATA[%3E.txt]]></f>

以上应该使€通过xml正确传达。

【讨论】:

  • 理想情况下,您应该将代码放在代码块中,以便之后正确显示
  • CDATA 部分对编码问题没有任何帮助。事实上,由于它们仅包含原始字符数据,因此它们会阻止您使用像 &amp;#x20AC; 这样的字符引用,而这正是您在 (3) 中所要使用的。
  • 是的 (2) 不是专门解决问题,而是为了保护更多特殊字符,如果它们将在值中。在 (3) 中,我故意放置 url 编码格式示例 %3E (不是 €),应该在通过 xml 中的代码提取值后对其进行解码。
猜你喜欢
  • 2013-08-09
  • 1970-01-01
  • 2015-07-23
  • 1970-01-01
  • 1970-01-01
  • 2014-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多