在Delphi 2010中从XML中读取°度符号

8
以下XML文本由于包含无效的°符号,无法从Delphi中读取:
V1:   <Item Id="1" Description="90° Hinge"/>

看起来,Delphi 不支持在XML中使用“标准”方法:

V2:   <Item Id="1" Description="90&deg; Hinge"/>

Delphi似乎能够很好地处理这个问题:

V3:   <Item Id="1" Description="90&#176; Hinge"/>

由于我从RESTful Web服务获取数据,我并没有特别控制经过的XML数据包,我只需要能够读取它们。

问题

  1. 如果V2是标准的XML方式,那么为什么Delphi不支持呢?还是有一种特殊的处理方式我不知道吗?
  2. V1 XML格式本身就有问题吗?如果是这样的话,我应该请求RESTful接口以V3格式导出°符号。

使用Delphi 2010。任何帮助都将不胜感激。

3个回答

9

Delphi本身并不会解析XML,第三方的XML引擎会解析,无论是MSXML、OpenXML、AtomXML等。TXMLDocument组件和支持接口只是一个包装框架,大部分的解析工作是由其他人完成的。

V1可能是格式错误的。这取决于XML实际使用的字符集。

V2实际上不是标准化的。并非所有的XML引擎都支持它。显然,你在Delphi中使用的那个引擎不支持它。

V3是标准化的,所有的XML引擎都支持该语法。


2
关于 V3,我会说“所有上述的 XML 引擎都支持该语法”(或者至少应该支持)。 - kobik
1
@Kobik,如果有什么不支持数字字符引用的东西,我会很难将其归类为XML解析器。 - Rob Kennedy
@kobik NCRs是XML标准的一部分,因此如果解析器无法处理它们,则不是XML解析器。 - David Heffernan
看起来我的文本编辑器Notepad++又把编码切换回了ANSI(如下所示),因此无论我在XML头中放入什么,它实际上都没有以那种方式编码 - Rick Wheeler

9
V1:   <Item Id="1" Description="90° Hinge"/>

在这里,您直接编码了字符。您的代码能否解析它取决于XML文档使用的字符集。因此,如果您的XML文档使用UTF-8并且正确编码,则您的XML代码将能够解析它。

V2:   <Item Id="1" Description="90&deg; Hinge"/>

这里使用了一个命名实体deg。在XML中,只有五个预定义的命名实体quotampaposltgt。虽然XML文档可以定义其他命名实体,但这很少见。因此,deg似乎不是您的文档中有效的命名实体。

V3:   <Item Id="1" Description="90&#176; Hinge"/>

这个版本使用数字字符引用(NCR)。您可以使用NCR指定任何Unicode代码点。
关于接下来你应该做什么,我们可以立即排除命名实体。我也建议避免对所有非ASCII字符使用NCRs。那只会导致无法阅读的文档。当然,如果您必须使用非Unicode感知工具来处理文档,则使用NCRs是唯一的方法。
因此,我们只能直接对非ASCII字符进行编码。您应确保您的XML使用UTF-8字符集进行正确编码,这种方法将有效,并且会产生可读和干净的文档。

我检查了我的XML文档,发现它没有使用UTF-8编码,所以我将XML头更改为<?xml version="1.0" encoding="UTF-8"?>,但这似乎没有任何效果。我正在使用MSXML,它仍然似乎在UTF-8中引发°编码错误。 - Rick Wheeler
1
更改标题不会更改实际文件的编码。如果文件已经正确编码,您可以直接编码任何Unicode字符。 - David Heffernan
看起来我的文本编辑器Notepad++又把编码切换回了ANSI(如下所示),因此无论我在XML头中放入什么,它实际上都没有以那种方式编码 - Rick Wheeler
不,Notepad++ 不会更改您的编码。您的文件一直都是 ANSI 编码。正如我所说,仅在头部中声明文件为 utf8 并不能使其成为 utf8 编码。我已经告诉过您,如果您的文件正确编码,则可以直接编码任何 Unicode 字符,除了保留字符如 < > & 等。 - David Heffernan
好的,这是否意味着Delphi无法正确地使用UTF-8编码生成文件?我使用TXMLDocument创建了文件,创建了节点,然后将其保存到文件中。之后我所做的就是在Notepad++中打开它并进行了一些小修改。但不知何故,它变成了ANSI格式,可能是直接从Delphi生成或在Notepad++中保存后发生的。您有任何想法在什么情况下会发生这种情况吗? - Rick Wheeler
你可以解决所有问题,因为你有代码。我没有。我建议你向Leonardo寻求帮助,因为你接受了他的答案。 - David Heffernan

1
仅在David的回答上进行详细说明,只要它们在当前编码中有效,XML不会排除文本节点中的任何值(除了极少数保留字符)。
您的问题中缺少一些事实:
1. 您是否使用文本编辑器生成此XML? 如果是这样,则必须检查保存文件时使用的编码。尝试使用UTF-8。如果您的文档是使用“windows”编码生成的,则尝试将编码属性添加到XML控制标记中,即<?xml version="1.0" encoding="iso-8859-1"?>
2. 您是否使用Delphi字符串函数生成此XML? 如果是这种情况,则Delphi使用的编码默认为UTF-8,但如果您从外部源读取片段,则可能会无意中混合其他编码。对于这个问题,除了使用XML库内置函数创建XML外,没有什么万能药。
当我不得不处理这些事情时(特别是XML签名!),我会使用字符串包装器,并使用显式编码(我使用type Latin1String = type AnsiString(28591))。

谢谢,这是正确的答案。我最初使用Delphi生成了该文件,并使用其默认设置。但是,后来我使用Notepad++打开和编辑了该文件,它似乎将其恢复为ANSI编码。所以我去格式菜单中选择了UTF-8选项,然后确保我的°字符看起来正确,嘭——它就工作了!非常感谢,我已经学到了新东西,而且才早上10点钟! - Rick Wheeler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接