从Unicode创建CData节点时XML无效字符 ID:NaveCabro XE5C++ +Builder。< /P>
我正试图在XMLCDATA部分中转储Unicode解压 这种字符串的小摘录:从Unicode创建CData节点时XML无效字符 ID:NaveCabro XE5C++ +Builder。< /P>,c++,xml,c++builder,C++,Xml,C++builder,我正试图在XMLCDATA部分中转储Unicode解压 这种字符串的小摘录: u"‰PNG\r\n\x1A\n\0\0\0\rIHDR\0\0\0õ\0\0\02\b\x06\0\0\0„\\i\0\0\0\x01sRGB\0®Î\x1Cé\0\0\0\x04gAMA\0\0±\vüa\x05\0\0\0\tpHYs\0\0\x0EÃ\0\0\x0EÃ\x01Ço¨d\0\0\v¼IDATxÚíœypUÕ\x19ÀO\x06…°¤\x04D$ˆ²\b1š\b\x18@...etc" 我知道X
u"‰PNG\r\n\x1A\n\0\0\0\rIHDR\0\0\0õ\0\0\02\b\x06\0\0\0„\\i\0\0\0\x01sRGB\0®Î\x1Cé\0\0\0\x04gAMA\0\0±\vüa\x05\0\0\0\tpHYs\0\0\x0EÃ\0\0\x0EÃ\x01Ço¨d\0\0\v¼IDATxÚíœypUÕ\x19ÀO\x06…°¤\x04D$ˆ²\b1š\b\x18@...etc"
我知道XML文档可以包含非ASCII字符,并且我认为XML CData节的内容不会被XML解析器解析(除了节末指示符“[[>”,它不在我的数据中,并被检查)
创建(写入)CData节时,我仍然会遇到“创建节点时在文本内容中发现无效字符”错误
代码示例:
_di_IXMLDocument pXMLDocument = NewXMLDocument("1.0");
// I've played around with the document encoding with no success, guessing it's only applicable while reading the document.
// pXMLDocument->SetEncoding(L"iso-8859-1");
String myString; // Unicode, contains my data string.
// 1st param of CreateNode method is of type UnicodeString.
di_IXMLNode pCDataNode = pXMLDocument->CreateNode( myString, ntCData );
有没有想过为什么会失败?编码问题?事实证明,问题确实是原始数据字符串中存在的所有转义字符,正如所怀疑的那样 通过在创建XML CData节之前对整个字符串进行Base64编码,解决了这个问题 Rad Studio方法:EncodeBase64,DecodeBase64 标题:Soap.EncdDecd.hpp如果您阅读了,它描述了CDATA节的格式:
CDATA Sections
[18] CDSect ::= CDStart CData CDEnd
[19] CDStart ::= '<![CDATA['
[20] CData ::= (Char* - (Char* ']]>' Char*))
[21] CDEnd ::= ']]>'
如果查看原始数据,它包含十几个字符值,这些字符值被排除在该范围之外具体地说,特别是<码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>码>方方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方,码>码>码>码>码>码>码>方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方一方<码>码>码>方一方一方一方,码>/code>)。这就是为什么您会收到关于非法字符的错误,因为您确实有非法字符
CDATA节不授予您将任意二进制数据放入XML数据的权限。当文本内容包含通常为XML标记保留的字符时,可以使用CDATA节,这样它们就不必转义或作为实体编码。将二进制数据放入XML文档的唯一方法是使用与XML兼容(通常为7bit ASCII)格式,如Base64(但也有其他可用格式,如yEnc)。针对我的情况,我创建了一个函数,将字符串修剪为一组有效的XML字符 伪代码:
//Code released into public domain. No attribution required.
function TrimToXmlText(xmlText: String): string;
begin
/*
http://www.w3.org/TR/xml/#NT-Char
Regarless of entity encoding, the only valid characters allowed are:
Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
I.e. any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
This means that a string such as
"Line one"#31#10"Line two"
is invalid (because of the #31 aka 0x1F).
This means we need to manually strip them out; because the xml library certainly won't do it for us.
*/
SetLength(Result, Length(xmlText));
Int32 o = 0;
for i = 1 to Length(s) do
begin
case Ord(s[i]) of
$9, $A, $D,
$20..$D7FF,
$E000..$FFFD:
begin
o = o+1;
Result[o] = xmlText[i];
end;
end;
end;
SetLength(Result, o);
end;
看起来问题实际上可能是字符串的内容。由于数据的“随机”性质,字符串包含大量的字符文字(转义字符)…并且它们是错误的(根据我的要求)这样解释。会导致问题。因此,在创建CData节点之前,需要对数据字符串进行转义字符分析。
//Code released into public domain. No attribution required.
function TrimToXmlText(xmlText: String): string;
begin
/*
http://www.w3.org/TR/xml/#NT-Char
Regarless of entity encoding, the only valid characters allowed are:
Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
I.e. any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
This means that a string such as
"Line one"#31#10"Line two"
is invalid (because of the #31 aka 0x1F).
This means we need to manually strip them out; because the xml library certainly won't do it for us.
*/
SetLength(Result, Length(xmlText));
Int32 o = 0;
for i = 1 to Length(s) do
begin
case Ord(s[i]) of
$9, $A, $D,
$20..$D7FF,
$E000..$FFFD:
begin
o = o+1;
Result[o] = xmlText[i];
end;
end;
end;
SetLength(Result, o);
end;