XML 规范中定义了以下转义字符:
符号 | 说明 | 替换值 |
< | 小于 | < |
> | 大于 | > |
& | 逻辑与 | & |
' | 单引号 | ' |
" | 双引号 | " |
当 XML 的元素值为上表中的特殊符号时,在 XML 中表示这些符号时要用规定的替换值。
libroxml 是一个用 C 语言开发的开源 XML 解析工具,它在 github 上的网址是:https://github.com/blunderer/libroxml,优点是比较小巧。我在使用过程中发现 libroxml 不能处理转义字符。比如有一个名为 MyConfig.xml 的 XML 文件,其内容如下:
<configure>
<hardware_name>TestCircuitBoard&1</hardware_name>
<hardware_count>10</hardware_count>
<configure>
写一个 C 程序调用 libroxml 获取文件中的元素值,内容如下:
/**************************************************
* Author: HAN Wei
* Author's blog: http://blog.csdn.net/henter/
* Date: April 1st, 2017
* Description: demonstrate that XML escape characters
cannot be translated by libroxml
**************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "roxml.h"
int main(void)
{
node_t *root_node, *config_node, *hd_name_node, *text_node;
char hd_name[128];
memset(hd_name, 0, sizeof(hd_name));
if ( !(root_node = roxml_load_doc("MyConfig.xml")) )
{
printf("Load config XML file failed at %s, line %d!\n", __FILE__, __LINE__);
return (-1);
}
if ( !(config_node = roxml_get_chld(root_node, NULL, 0)) )
{
printf("Search node in config XML file failed at %s, line %d!\n", __FILE__, __LINE__);
roxml_close(root_node);
return (-1);
}
if ( !(hd_name_node = roxml_get_nodes(config_node, ROXML_ELM_NODE, "hardware_name", 0)) )
{
printf("Search node in config XML file failed at %s, line %d!\n", __FILE__, __LINE__);
roxml_close(root_node);
return (-1);
}
if ( !(text_node = roxml_get_txt(hd_name_node, 0)) )
{
printf("Search node in config XML file failed at %s, line %d!\n", __FILE__, __LINE__);
roxml_close(root_node);
return (-1);
}
if ( strlen(roxml_get_content(text_node, NULL, 0, NULL)) > sizeof(hd_name) )
{
printf("Hardware name byte length is beyond the upperbound in config XML file at %s, line %d!\n", __FILE__, __LINE__);
roxml_close(root_node);
return (-1);
}
strcpy(hd_name, roxml_get_content(text_node, NULL, 0, NULL));
printf("hardware name in XML file: %s\n", hd_name);
roxml_close(root_node);
#if defined(_WIN32) || defined(_WIN64)
system("pause");
#endif
return 0;
}
使用 2.3.0 版本的libroxml,程序运行的结果为:hardware name in XML file: TestCircuitBoard&1
而期望的结果是: hardware name in XML file: TestCircuitBoard&1
这说明 libroxml 不能处理 XML 中的转义字符,至少在 2.3.0 及更早的版本中存在此问题。已经在 github 上向开发者反馈了这个问题,希望能在后继版本中修复。
——————————————————————————————————
如果使用另外一个 C 语言开发的 XML 解析工具 Mini-XML (网址:https://github.com/michaelrsweet/mxml),当读取 XML 中的元素值时,它能够正确转换其中的转义字符。比如在取出的字符串中自动将 & 转换成 &。在向 XML 中写入元素值时,它也能够正确转换,比如要写入 & 时,Mini-XML 会自动将 & 转换成 & ,然后向 XML 文件中写入 & 。
对于使用 C++ 开发的开源 XML 解析工具 TinyXML-2,它也能正确地转换转义字符。在其网站 http://www.grinninglizard.com/tinyxml2docs/index.html 上的说明如下:
TinyXML-2 recognizes the pre-defined "character entities", meaning special characters. Namely:
& &
< <
> >
" "
' '
These are recognized when the XML document is read, and translated to their UTF-8 equivalents. For instance, text with the XML of: Far & Away will have the Value() of "Far & Away" when queried from the XMLText object, and will be written back to the XML stream/file as an ampersand.