北京理工大学 20981 陈罡
expat xml解析库是一个非常强大的xml解析库,有了它的支持可以将很多参数设置或者内容编排、组织都集成到程序中去。5mbox的杂志内容解析、显示的基础就是expat解析库。目前,我已经让这个库可以在s60 2nd, 3rd以及moto mobilinux上面顺利运行了,还差win mobile平台和uiq平台,就基本上都有了。
这次借助开发win mobile5的东风,既frame buffer库、jpeg/png/gif库之后,就把expat库给移植上去。在我的概念里面,写得好的c、c++代码要比java的代码可移植性更高!
简单的看了一下,expat 2.0主要有用的文件有5个,它们分别是:
xmlparse.c : 定义了dtd的支持和外部XML_Parser的函数
xmlrole.c : 定义了关键字和内容列表什么的
xmltok.c : 这个就是解析部分的包装了,呵呵,难得作者用c语言实现了所谓的"vtable"虚拟函数表
xmltok_impl.c : 这个是对普通xmltag的解析的实现
xmltok_ns.c : 这个是对名字空间的解析的实现
第一步,需要把原有的.c改为.cpp文件,然后在.h中,把必要的声明部分都加入:
#ifdef __cplusplus
extern "C" {
#endif
....声明部分代码
#ifdef __cplusplus
}
#endif
然后就是编译,会发现有一些地方会出现类型不对的问题,这主要是expat的作者用enum来表示这些变量了(而不是用defene),而c++的编译器对类型检查非常严格,因此会出这些问题。强制类型转换一下,然后
再一些没有初始化的变量上把初始值加上。这样就没有警告了。
第二步,发现一些奇特的错误如下所示:
\expat\xmltok_impl.c(90) : error C2061: syntax error : identifier 'scanComment'
\expat\xmltok_impl.c(90) : error C2059: syntax error : ';'
\xmltok_impl.c(90) : error C2059: syntax error : 'type'
\expat\xmltok_impl.c(128) : error C2061: syntax error : identifier 'scanDecl'
\expat\xmltok_impl.c(128) : error C2059: syntax error : ';'
\expat\xmltok_impl.c(128) : error C2059: syntax error : 'type'
\expat\xmltok_impl.c(175) : error C2061: syntax error : identifier 'checkPiTarget'
\expat\xmltok_impl.c(175) : error C2059: syntax error : ';'
\expat\xmltok_impl.c(175) : error C2059: syntax error : 'type'
\expat\xmltok_impl.c(220) : error C2061: syntax error : identifier 'scanPi'
\expat\xmltok_impl.c(220) : error C2059: syntax error : ';'
\expat\xmltok_impl.c(220) : error C2059: syntax error : 'type'
\expat\xmltok_impl.c(282) : error C2061: syntax error : identifier 'scanCdataSection'
\expat\xmltok_impl.c(282) : error C2059: syntax error : ';'
\expat\xmltok_impl.c(282) : error C2059: syntax error : 'type'
等等,类似这样的错误。
这个错误是如何引起的呢?
仔细看xmltok.c文件,就会发现它有#include "xmltok_impl.c",这是什么意思呢?
原来,作者是靠#include把xmltok_impl.c里面的函数“集成”到xmltok.c中使用。
从vs2005的输出看来,似乎不支持这种在一个.cpp文件中#include另外一个.cpp文件的方法。
通过源代码浏览可以看出,作者用xmltok.c这个文件include了xmltok_impl.c和xmltok_ns.c才会
出现上述的定义问题。
解决的方法是,注释掉这个#include "xmltok_impl.c"以及#include "xmltok_ns.c",然后把这两个
.c文件的内容直接复制到xmltok.c里面#include这两个.c的相应位置。重新编译就可以通过了。
expat库的基本使用方法如下:
#include
#include "xmlparse.h" // 这是v1.0版的expat的头文件
#include "expat.h" // 这是v2.0版的expat的头文件
//tag中的字符处理函数
void CharacterDataHandler(void *userData, const XML_Char *s, int len)
{
char* str = (char*)malloc (len + 1);
strncpy (str, s, len);
puts (str);
}
// tag的开头处理函数
void startElement(void *userData, const char *name, const char **atts)
{
int i;
int *depthPtr = userData;
for (i = 0; i < *depthPtr; i++)
putchar('\t');
//puts(name);
printf ("XML: <%s", name);
i = 0;
while (atts[i] && *atts[i] && atts[i][0] != 0)
{
if (i % 2)
{
printf ("=");
printf ("\"%s\"", atts[i]);
}
else
{
printf (" ");
printf ("%s", atts[i]);
}
i++;
}
printf (">\n");
*depthPtr += 1;
}
// tag的结束处理函数
void endElement(void *userData, const char *name)
{
int *depthPtr = userData;
*depthPtr -= 1;
}
int main()
{
char buf[BUFSIZ];
// 创建XML_Parser对象
XML_Parser parser = XML_ParserCreate(NULL);
int done;
int depth = 0;
// 设置自定义数据
XML_SetUserData(parser, &depth);
// 设置tag的处理函数
XML_SetElementHandler(parser, startElement, endElement);
// 设置tag中包含的字符处理函数
// 例如:这部分字符
XML_SetCharacterDataHandler(parser, CharacterDataHandler);
// 这个循环就是多次load文件中的xml数据,然后处理
do {
size_t len = fread(buf, 1, sizeof(buf), stdin);
done = len < sizeof(buf);
if (!XML_Parse(parser, buf, len, done)) {
fprintf(stderr,
"%s at line %d\n",
XML_ErrorString(XML_GetErrorCode(parser)),
XML_GetCurrentLineNumber(parser));
return 1;
}
} while (!done);
// 最后不要忘记释放这个xml解析器的对象
XML_ParserFree(parser);
return 0;
}
为了后来人能够不必象我一样在往嵌入式系统中修改和移植expat遇到这么多麻烦的问题,加之expat本身
就是开源的软件。我打算开放这个expat v2.0 for win mobile 5的源代码。
希望能够对各位有用!
|
文件: |
expat_wm5_port.rar |
大小: |
69KB |
下载: |
下载 | |
注意,这个移植不是生成dll或者lib的,而是直接可以加入到工程中的代码。使用方法是在win mobile中添加新的目录,然后把整个expat目录中的文件都添加进去,然后在使用的地方加入#include "expat.h"。然后在vs2005中添加相关的include目录,就可以在vs2005中编译和运行了。
祝大家好运!
阅读(3591) | 评论(9) | 转发(0) |