4、SAX方式使用iksemel
笔者的习惯,先上例子程序(直接来自iksemel的doc):
//test.c
#include <stdio.h> #include <iksemel.h>
int pr_tag (void *udata, char *name, char **atts, int type) { switch (type) { case IKS_OPEN: printf ("TAG <%s>\n", name); break; case IKS_CLOSE: printf ("TAG %s>\n", name); break; case IKS_SINGLE: printf ("TAG <%s/>\n", name); break; } if (atts) { int i = 0; while (atts[i]) { printf (" ATTRIB %s='%s'\n", atts[i], atts[i+1]); i += 2; } } return IKS_OK; }
enum ikserror pr_cdata (void *udata, char *data, size_t len) { int i; printf ("CDATA ["); for (i = 0; i < len; i++) putchar (data[i]); printf ("]\n"); return IKS_OK; }
int main (int argc, char *argv[]) { iksparser *p; p = iks_sax_new (NULL, pr_tag, pr_cdata); switch (iks_parse (p, argv[1], 0, 1)) { case IKS_OK: puts ("OK"); break; case IKS_NOMEM: puts ("Not enough memory"); exit (1); case IKS_BADXML: puts ("XML document is not well-formed"); exit (2); case IKS_HOOK: puts ("Our hooks didn't like something"); exit (2); } iks_parser_delete (p); return 0; }
|
编译:
gcc -o test test.c -liksemel
这个可能会出现错误,因为我们前面安装 iksemel 的时候选择的自己设定的路径,不是系统默认路径。
可以通过下面方法解决:
gcc -o test test.c -liksemel -I/data/soft/iksemel-1.3/include -L/data/soft/iksemel-1.3/lib
通过"-I"添加头文件的搜索路径,通过"-L"添加库文件的搜索路径,通过"-l"添加动态链接库的文件名。
下面运行:
./test "
Hello
World"
./test "
"
可能会出现下面的情况:
./test: error while loading shared libraries: libiksemel.so.3: cannot open shared object file: No such file or directory
这个问题因为刚刚编译的时候没有选择静态编译,那么按照默认的编译就动态编译的。
动态编译后,由于可执行文件在运行时要调用系统库文件,
那么沿着系统默认的库文件搜索路径搜索,就可能找不到我们现在所需的库文件。
致使出现 "error while loading shared libraries" 等错误。
我们可以这样解决:
方法一:静态编译
在编译时加上 -static 参数
方法二:重新配置系统环境变量 LD_LIBRARY_PATH
这时需要指定 libiksemel.so.0 库文件的路径,也就是配置系统环境变量 LD_LIBRARY_PATH ,
使系统能够找到 libiksemel.so.0 。
例如:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/data/soft/iksemel-1.3/lib
这样就应该不会又问题。
[root@localhost xmltest]# ./test "
Hello
World"
TAG
CDATA [Hello]
TAG
CDATA [World]
TAG OK
[root@localhost xmltest]# ./test "
"
TAG
ATTRIB a='12'
ATTRIB b='42'
OK
主要用到的函数的介绍:
iksparser* iks_sax_new (void* USER_DATA, iksTagHook*
TAGHOOK, iksCDataHook* CDATAHOOK);
该函数分配内存和初始化一个 SAX 解析器。如果分配内存失败,返回NULL。
int iks_parse (iksparser* PRS, char *DATA, size_t LEN, int
FiNiSH);
这个函数处理XML文本数据。
iksparser* PRS:上一个函数的返回指针。
char *DATA:XML文本数据
size_t LEN:数据长度。如果等于0,那么DATA必须为一个空字符串
int FiNiSH:如果为0,那么这个函数等待更多的数据输入。如果想处理一次就退出,那么可以这样调用:
iks_parse (my_parser, NULL, 0, 1);
返回值:
`IKS_OK'
OK,没有任何问题
`IKS_NOMEM'
内存不足
`IKS_BADXML'
XML文件数据格式不对
`IKS_HOOK'
自定义的hook函数决定的错误。
void iks_parser_delete (iksparser* PRS);
释放相关的内存。
iksTagHook
int iksTagHook (void* USER_DATA, char* NAME, char** ATTS, int TYPE);
这个函数是标记( Tag )分析器。 NAME 是标记的名字。如果没有属性,ATTS = NULL,
否则ATTS是一个二维数组指针,指向属性(char*)数组。
TYPE 值:
`IKS_OPEN'
开始标记tag, i.e.
`IKS_CLOSE'
结束标记tag, i.e. `IKS_SINGLE'
独立标记 tag, i.e.
iksCDataHook
int iksCDataHook (void* USER_DATA, char* DATA, size_t LEN);
该函数用来处理数据的。
DATA is a pointer to the character data. Encoding is UTF-8 and it
isn't terminated with a null character. Size of the data is given
with LEN in bytes. This function can be called several times with
smaller sized data for a single string. If return value isn't
`IKS_OK', it is passed immediately to the caller of the
`iks_parse'.