iOS 上的 OmniXML:无效的 Unicode
OmniXML on iOS: Invalid Unicode
我最近转而使用 Delphi XE7 中包含的 OmniXML,以允许定位 iOS。 XML 数据来自云服务,包括具有 base64 编码二进制数据的节点。
现在我在调用 XMLDocument.LoadFromStream 时得到这个异常 "Invalid Unicode Character value for this platform"
,似乎是这个 base64 换行序列失败了:
具有 base64 数据的节点看起来类似于:
<data>TVRMUQAAAAIAAAAAFFo3FAAUAAEA8AADsAAAAEAAAABAAHAAwABgAAAAAAAAAAAQEBAAAAAAAA
AAMQAAABNUgAAP/f/AAMABAoAAAAEAAAAAEVNVExNAAAAAQAAAAAUWjcUABQAAQD/wAA
AAA=</data>
我将其追溯到 XML.Internal.OmniXML
中的这些行:
psCharHexRef:
if CharIs_WhiteSpace(ReadChar) then
raise EXMLException.CreateParseError(INVALID_CHARACTER_ERR, MSG_E_UNEXPECTED_WHITESPACE, [])
else
begin
case ReadChar of
'0'..'9': CharRef := LongWord(CharRef shl 4) + LongWord(Ord(ReadChar) - 48);
'A'..'F': CharRef := LongWord(CharRef shl 4) + LongWord(Ord(ReadChar) - 65 + 10);
'a'..'f': CharRef := LongWord(CharRef shl 4) + LongWord(Ord(ReadChar) - 97 + 10);
';':
if CharIs_Char(Char(CharRef)) then
begin
Result := Char(CharRef);
Exit;
end
else
raise EXMLException.CreateParseError(INVALID_CHARACTER_ERR, MSG_E_INVALID_UNICODE, []);
这是最后一行中引发的异常,因为 CharIs_Char(#13)
为假(其中 #13 是从 
读取的 CharRef 的值)
我该如何解决?
这显然是 Omni 中的一个错误XML。看起来开发人员正在尝试实施 XML1.0 which states :
...XML processors MUST accept any character in the range specified for Char.
Character Range
[2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
/* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
CharIs_Char
的实现,但是看起来像:
function CharIs_Char(const ch: Char): Boolean;
begin
// [2] Char - any Unicode character, excluding the surrogate blocks, FFFE, and FFFF
Result := not Ch.IsControl;
end;
这不包括所有控制字符,包括 #x9
(TAB)、#xA
(LF) 和 #xD
(CR)。事实上,由于 XML 在解析期间剥离(或可选地用 LF 替换)回车 return 文字,因此包含实际回车 return 的唯一方法是在实体值文字中使用字符引用(规范的第 2.3 节)。
这似乎是一个阻碍,应该作为 QC 报告提交。
我最近转而使用 Delphi XE7 中包含的 OmniXML,以允许定位 iOS。 XML 数据来自云服务,包括具有 base64 编码二进制数据的节点。
现在我在调用 XMLDocument.LoadFromStream 时得到这个异常 "Invalid Unicode Character value for this platform"
,似乎是这个 base64 换行序列失败了:
具有 base64 数据的节点看起来类似于:
<data>TVRMUQAAAAIAAAAAFFo3FAAUAAEA8AADsAAAAEAAAABAAHAAwABgAAAAAAAAAAAQEBAAAAAAAA
AAMQAAABNUgAAP/f/AAMABAoAAAAEAAAAAEVNVExNAAAAAQAAAAAUWjcUABQAAQD/wAA
AAA=</data>
我将其追溯到 XML.Internal.OmniXML
中的这些行:
psCharHexRef:
if CharIs_WhiteSpace(ReadChar) then
raise EXMLException.CreateParseError(INVALID_CHARACTER_ERR, MSG_E_UNEXPECTED_WHITESPACE, [])
else
begin
case ReadChar of
'0'..'9': CharRef := LongWord(CharRef shl 4) + LongWord(Ord(ReadChar) - 48);
'A'..'F': CharRef := LongWord(CharRef shl 4) + LongWord(Ord(ReadChar) - 65 + 10);
'a'..'f': CharRef := LongWord(CharRef shl 4) + LongWord(Ord(ReadChar) - 97 + 10);
';':
if CharIs_Char(Char(CharRef)) then
begin
Result := Char(CharRef);
Exit;
end
else
raise EXMLException.CreateParseError(INVALID_CHARACTER_ERR, MSG_E_INVALID_UNICODE, []);
这是最后一行中引发的异常,因为 CharIs_Char(#13)
为假(其中 #13 是从 
读取的 CharRef 的值)
我该如何解决?
这显然是 Omni 中的一个错误XML。看起来开发人员正在尝试实施 XML1.0 which states :
...XML processors MUST accept any character in the range specified for Char.
Character Range
[2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
/* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
CharIs_Char
的实现,但是看起来像:
function CharIs_Char(const ch: Char): Boolean;
begin
// [2] Char - any Unicode character, excluding the surrogate blocks, FFFE, and FFFF
Result := not Ch.IsControl;
end;
这不包括所有控制字符,包括 #x9
(TAB)、#xA
(LF) 和 #xD
(CR)。事实上,由于 XML 在解析期间剥离(或可选地用 LF 替换)回车 return 文字,因此包含实际回车 return 的唯一方法是在实体值文字中使用字符引用(规范的第 2.3 节)。
这似乎是一个阻碍,应该作为 QC 报告提交。