如何使用 RapidXML 读取 UTF-8 XML 并将其与 C++ 一起使用
How to read UTF-8 XML with RapidXML and use it with C++
我开发了一个 C++ 应用程序并实现了一个翻译器 class,它使用 XML 文件中的数据来翻译字符串。我现在遇到了一些特殊字符的严重问题,例如德国变音符号 ÖÄÜ...
在 Visual Studio 我在调试视图中看到以下内容,它读取以下示例字符串 "Dateiäüö":
由于这个问题,我在 Whosebug 上发现了这个 post:
How to read Unicode XML values with rapidxml
并更改了我的 RapidXML class 以使用 wchar_t:
std::string RapidXMLParser::getValueUTF8(const std::string path)
{
std::vector<std::string> tags = splitPath(path);
rapidxml::file<wchar_t> xmlFile(filename.data());
docUTF8.parse<0>(xmlFile.data());
rapidxml::xml_node<wchar_t>* element = findElementUTF8(path);
if (element)
{
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring temp = element->value();
std::string result = converter.to_bytes(temp);
return result;
}
else
return "";
}
但这并没有解决我的问题:
源 XML 文件已通过 UTF-8 验证程序检查,没有问题。如果我将编码更改为 ANSI,一切都适用于 Windows(但这不是解决方案!)。如果我在 Linux 上编译相同的代码,我得到带有变音符号的 ANSI 编码 XML 的空字符串和 UTF-8 编码的 XML...
的崩溃
该程序使用 wxwidgets 作为其界面,该菜单项呈现与调试器显示的字符相同的字符。在 Linux 上,空字符串会导致缺少菜单项或空行。
我希望有人对如何解决这个问题有很好的建议,或者对使用 XML 文件等可编辑数据源进行 UTF-8 翻译的替代方法提出建议。
编辑:
我的 XML 解析器可以在 RapidXML 和 TinyXML 之间切换。我也用 TinyXML 测试过这个,我遇到了同样的问题:
经过几个小时的努力解决这个问题,解决方案非常简单。
永远不要相信你的调试器!!!问题是由 wxwidgets 引起的...它显示的字符与我在调试器中看到的字符相同,但是如果我在呈现菜单之前将 utf8 转换为 utf16项目,它显示的字符串正确!
解决方案是不要在我的 XMLParser 中使用显示的 codecvt 代码,而是在输出之前的我的 wxwidgets 代码中使用。在 Linux 我现在遇到了问题,codecvt 不是 g++ 标准的一部分...但这是另一回事了。
天哪...我希望这对遇到类似问题的人有用。
我认为你的 findElementUTF8()
应该 return 一个 rapidxml::xml_node<char>*
rapidxml::xml_node<char>* element = findElementUTF8(path);
因为UTF8通常用char*表示。以下代码适用于 windows API 和 codecvt
// äüö UTF8 encoded
byte b8[] = { 0xc3, 0xa4, 0xc3, 0xbc, 0xc3, 0xb6, 0x00 };
std::string sb8 = (char*)b8;
wchar_t win_conv[16]{ 0 };
MultiByteToWideChar(CP_UTF8, 0, (char*)b8, -1, win_conv, ARRAYSIZE(win_conv));
std::wstring utf16_conv = std::wstring_convert<
std::codecvt_utf8_utf16<wchar_t>>{}.from_bytes(sb8);
assert(utf16_conv == win_conv);
我开发了一个 C++ 应用程序并实现了一个翻译器 class,它使用 XML 文件中的数据来翻译字符串。我现在遇到了一些特殊字符的严重问题,例如德国变音符号 ÖÄÜ...
在 Visual Studio 我在调试视图中看到以下内容,它读取以下示例字符串 "Dateiäüö":
由于这个问题,我在 Whosebug 上发现了这个 post: How to read Unicode XML values with rapidxml 并更改了我的 RapidXML class 以使用 wchar_t:
std::string RapidXMLParser::getValueUTF8(const std::string path)
{
std::vector<std::string> tags = splitPath(path);
rapidxml::file<wchar_t> xmlFile(filename.data());
docUTF8.parse<0>(xmlFile.data());
rapidxml::xml_node<wchar_t>* element = findElementUTF8(path);
if (element)
{
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring temp = element->value();
std::string result = converter.to_bytes(temp);
return result;
}
else
return "";
}
但这并没有解决我的问题:
源 XML 文件已通过 UTF-8 验证程序检查,没有问题。如果我将编码更改为 ANSI,一切都适用于 Windows(但这不是解决方案!)。如果我在 Linux 上编译相同的代码,我得到带有变音符号的 ANSI 编码 XML 的空字符串和 UTF-8 编码的 XML...
的崩溃该程序使用 wxwidgets 作为其界面,该菜单项呈现与调试器显示的字符相同的字符。在 Linux 上,空字符串会导致缺少菜单项或空行。
我希望有人对如何解决这个问题有很好的建议,或者对使用 XML 文件等可编辑数据源进行 UTF-8 翻译的替代方法提出建议。
编辑: 我的 XML 解析器可以在 RapidXML 和 TinyXML 之间切换。我也用 TinyXML 测试过这个,我遇到了同样的问题:
经过几个小时的努力解决这个问题,解决方案非常简单。 永远不要相信你的调试器!!!问题是由 wxwidgets 引起的...它显示的字符与我在调试器中看到的字符相同,但是如果我在呈现菜单之前将 utf8 转换为 utf16项目,它显示的字符串正确!
解决方案是不要在我的 XMLParser 中使用显示的 codecvt 代码,而是在输出之前的我的 wxwidgets 代码中使用。在 Linux 我现在遇到了问题,codecvt 不是 g++ 标准的一部分...但这是另一回事了。
天哪...我希望这对遇到类似问题的人有用。
我认为你的 findElementUTF8()
应该 return 一个 rapidxml::xml_node<char>*
rapidxml::xml_node<char>* element = findElementUTF8(path);
因为UTF8通常用char*表示。以下代码适用于 windows API 和 codecvt
// äüö UTF8 encoded
byte b8[] = { 0xc3, 0xa4, 0xc3, 0xbc, 0xc3, 0xb6, 0x00 };
std::string sb8 = (char*)b8;
wchar_t win_conv[16]{ 0 };
MultiByteToWideChar(CP_UTF8, 0, (char*)b8, -1, win_conv, ARRAYSIZE(win_conv));
std::wstring utf16_conv = std::wstring_convert<
std::codecvt_utf8_utf16<wchar_t>>{}.from_bytes(sb8);
assert(utf16_conv == win_conv);