Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1514261
  • 博文数量: 114
  • 博客积分: 10010
  • 博客等级: 上将
  • 技术积分: 1357
  • 用 户 组: 普通用户
  • 注册时间: 2006-11-19 18:13
文章分类
文章存档

2010年(8)

2009年(9)

2008年(27)

2007年(62)

2006年(8)

我的朋友

分类: WINDOWS

2007-12-02 14:14:11

北京理工大学  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中编译和运行了。

祝大家好运!

阅读(3475) | 评论(9) | 转发(0) |
给主人留下些什么吧!~~

pirate_wb2008-03-04 16:06:30

你好陈罡,我现在在做s60 3rd的一个应用,但是目前expat无法在上面使用,你说在3rd上实现了,如果不介意的话能否共享一下你在3rd上的实现。 pirate_wb@163.com

chenwayne2008-01-08 12:55:10

你可以考虑看看我的for win mobile 5的port试试,应该是可以的,检查一下是不是有指针越界或者死循环的问题。

igogo2008-01-08 11:37:58

我想在MTK平台下用expat,发现如果定义static void XMLCALL startElement(void *userData, const char *name, const char **atts),在 XML_SetElementHandler(parser, startElement, endElement);就会死机,如果用static void XMLCALL startElement(void *UserData, const char *Name, const char **Atts),则可以正确设置,开机,但是无法执行到那个函数内。能帮忙想想可能是什么问题吗