解析XML文件!把对应的项printf出来
首先给大家一个解析xml的源代码,自己可以随意的改写 (1)XML解析流程解析一个XML文档,从中取出想要的信息,例如节点中包含的文字,或者某个节点的属性。其流程如下:①用xmlReadFile函数读入一个文件,并返回一个文档指针doc。②用xmlDocGetRootElement函数得到根节点curNode。③此时curNode->xmlChildrenNode就是根节点
首先给大家一个解析xml的源代码,自己可以随意的改写
(1)XML解析流程
解析一个XML文档,从中取出想要的信息,例如节点中包含的文字,或者某个节点的属性。其流程如下:
①用xmlReadFile函数读入一个文件,并返回一个文档指针doc。
②用xmlDocGetRootElement函数得到根节点curNode。
③此时curNode->xmlChildrenNode就是根节点的首个儿子节点,该儿子节点的兄弟节点可用next指针进行轮询。
④轮询所有子节点,找到所需的节点,用xmlNodeGetContent取出其内容。
⑤用xmlHasProp查找含有某个属性的节点,属性列表指针xmlAttrPtr将指向该节点的属性列表。
⑥取出该节点的属性,用xmlGetProp取出其属性值。
⑦ xmlFreeDoc函数关闭文档指针,并清除本文档中所有节点动态申请的内存。
(2)XML解析举例
ParseXmlFile.c源代码如下:
#include<stdio.h>
#include<libxml/parser.h>
#include<libxml/tree.h>
intmain(int argc, char* argv[])
{
xmlDocPtrdoc; //定义解析文件指针
xmlNodePtrcurNode; //定义结点指针
xmlChar*szKey; //临时字符串变量
char*szDocName;
if(argc <= 1)
{
printf("Usage:%s docname", argv[0]);
return(0);
}
szDocName= argv[1];
doc =xmlReadFile(szDocName,"GB2312",XML_PARSE_RECOVER);
//解析文件
//检查解析文档是否成功,如果不成功,libxml将报错并停止解析。
//一个常见错误是不适当的编码,XML标准文档除了用UTF-8或UTF-16外还可用其它编码保存
if(NULL == doc)
{
fprintf(stderr,"Documentnot parsed successfully.");
return-1;
}
//获取根节点
curNode= xmlDocGetRootElement(doc);
if(NULL == curNode)
{
fprintf(stderr,"emptydocument");
xmlFreeDoc(doc);
return-1;
}
//确认根元素名字是否符合
if(xmlStrcmp(curNode->name, BAD_CAST "root"))
{
fprintf(stderr,"documentof the wrong type, root node != root");
xmlFreeDoc(doc);
return-1;
}
curNode= curNode->xmlChildrenNode;
xmlNodePtrpropNodePtr = curNode;
while(curNode!= NULL)
{
//取出节点中的内容
if((!xmlStrcmp(curNode->name, (const xmlChar *) "newNode1")))
{
szKey =xmlNodeGetContent(curNode);
printf("newNode1:%s\n", );
xmlFree(szKey);
}
//查找带有属性attribute的节点
if(xmlHasProp(curNode,BAD_CAST "attribute"))
{
propNodePtr = curNode;
}
curNode = curNode->next;
}
//查找属性
xmlAttrPtr attrPtr =propNodePtr->properties;
while (attrPtr != NULL)
{
if(!xmlStrcmp(attrPtr->name, BAD_CAST "attribute"))
{
xmlChar* szAttr =xmlGetProp(propNodePtr,BAD_CAST "attribute");
printf("getattribute=%s\n", szAttr) ;
xmlFree(szAttr);
}
attrPtr = attrPtr->next;
}
xmlFreeDoc(doc);
return 0;
}
编译 gcc ParseXmlFile.c -oParseXmlFile -I/usr/local/include/libxml2 -lxml2。
执行 ./ParseXmlFile CreateXml.xml
结果就会显示在屏幕上。
接下来我要做的就是运用上面的源代码将我自己的xml文件解析出来。
#include <stdio.h>
#include <assert.h>//设定插入点
#include <ctype.h>//字符处理
#include <errno.h>//定义错误码
#include <float.h>//浮点数处理
#include <limits.h>//定义各种数据类型最值常量
#include <locale.h>//定义本地化函数
#include <math.h>//定义数学函数
#include <stdio.h>//定义输入/输出函数
#include <stdlib.h>//定义杂项函数及内存分配函数
#include <string.h>//字符串处理
#include <time.h>//定义关于时间的函数
#include <wchar.h>//宽字符处理及输入/输出
#include <wctype.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
int main(int argc, char* argv[])
{
xmlDocPtr doc; //定义解析文件指针
xmlNodePtr curNode; //定义结点指针
xmlChar *szKey; //临时字符串变量
char *szDocName;
char line[1024*512];
char dest_gb18030[1024*512];
char dest_utf8[1024*512];
int ret ;
FILE *fp = fopen("/root/czy/test/test/123_GB18030.xml","r");
if(fp == NULL)
{
printf("oh my dear,open fail...\n");
return 1;
}
memset(line,0,sizeof(line));
if( NULL == fread(line,1,sizeof(line)-1,fp))
{
printf("oh fread fail...\n");
return 2;
}
printf( "----- :%s\n",line );
ret = gb18030toutf8(line,strlen(line),dest_gb18030,1024*512);
// ret = gb18030toutf8(dest_gb18030,strlen(dest_gb18030),dest_utf8,80);
//printf( "ret=%d\n\n\n",ret);
//printf( "gb18030:%s\n",line );
printf( " utf-8:%s\n\n\n\n\n\n", dest_gb18030 );
ret = utf8togb18030(dest_gb18030,strlen(dest_gb18030),dest_utf8,1024*512);
// printf( "ret=%d\n\n\n ",ret);
// printf( " utf-8:%s\n ",dest_gb18030);
// printf( "gb18030:%s\n ",dest_utf8);
// xmlDocPtr doc; //定义解析文件指针
// xmlNodePtr curNode; //定义结点指针
// xmlChar *szKey; //临时字符串变量
// char *szDocName;
doc = xmlReadMemory(dest_gb18030,sizeof(dest_gb18030),szDocName,"UTF-8",XML_PARSE_RECOVER);
// xmlReadMemory这个函数的作用是读出内存的,因为我是先转换后解析的,所有我要把我自己转换出来的XML文件解析出来,就要把那段内存读出来。原来的xmlReadFile是用来读文件的。
// doc = xmlReadFile(szDocName,"GB18030",XML_PARSE_RECOVER);
if (NULL == doc)
{
fprintf(stderr,"Document not parsed successfully.");
return -1;
}
curNode = xmlDocGetRootElement(doc);
if (NULL == curNode)
{
fprintf(stderr,"empty document");
xmlFreeDoc(doc);
return -1;
}
printf("@@@@@@@@@@@@@@@@@%s\n",curNode->name);
if (xmlStrcmp(curNode->name, BAD_CAST "print_task"))
//上面这个if 语句是用来做对比的,如果因为我不知道我的curNode->name会指到哪里,所以我在上面写了一个printf语句找到了这个位置,就是我要解析的XML文件的print_task处。
{
fprintf(stderr,"document of the wrong type, print node != print");
xmlFreeDoc(doc);
return -1;
}
curNode = curNode->xmlChildrenNode;
xmlNodePtr propNodePtr = curNode;
while(curNode != NULL)
{
printf("!!!!!!!!!!!!%s\n",curNode->name);
if ((!xmlStrcmp(curNode->name, (const xmlChar *) "text")))
{
szKey = xmlNodeGetContent(curNode);
printf("text: %s\n", szKey);
xmlFree(szKey);
}
else if ((!xmlStrcmp(curNode->name, (const xmlChar *) "line")))
{
szKey = xmlNodeGetContent(curNode);
printf("text: %s\n", szKey);
memset(dest_utf8,0,sizeof(dest_utf8));
ret = utf8togb18030(szKey,strlen(szKey),dest_utf8,1024*512);
printf( "test%s\n ",dest_utf8);
xmlFree(szKey);
}
if (xmlHasProp(curNode,BAD_CAST "align"))
{
propNodePtr = curNode;
}
curNode = curNode->next;
}
//查找属性
xmlAttrPtr attrPtr = propNodePtr->properties;
while (attrPtr != NULL)
{
if (!xmlStrcmp(attrPtr->name, BAD_CAST "align")) //align 是我自己文件的一个属性,大家可以自己改成自己想要解析文件的属性
{
xmlChar* szAttr = xmlGetProp(propNodePtr,BAD_CAST "align");
printf("get attribute=%s\n", szAttr) ;
xmlFree(szAttr);
}
attrPtr = attrPtr->next;
}
xmlFreeDoc(doc);
return 0;
}
这是我修改的源代码,改动的地方我已经做出了注释
接着我的代码还需要一个动态库来链接
#include<iconv.h>
#include <stdio.h>
#include<iconv.h>
#include <stdio.h>
int utf8togb18030(const char *sourcebuf,size_t sourcelen,char *destbuf,size_t destlen)
{
iconv_t cd;
if( (cd = iconv_open("gb18030","utf-8")) ==0 )
return -1;
memset(destbuf,0,destlen);
const char **source = &sourcebuf;
char **dest = &destbuf;
if(-1 == iconv(cd,source,&sourcelen,dest,&destlen))
return -1;
iconv_close(cd);
return 0;
}
int gb18030toutf8(const char *sourcebuf,size_t sourcelen,char *destbuf,size_t destlen)
{
iconv_t cd;
if( (cd = iconv_open("utf-8","gb18030")) ==0 )
return -1;
memset(destbuf,0,destlen);
const char **source = &sourcebuf;
char **dest = &destbuf;
if(-1 == iconv(cd,source,&sourcelen,dest,&destlen))
return -1;
iconv_close(cd);
return 0;
}
动态库的代码已给出,现在要做的就是生成动态库
gcc -shared -fpic -o libmy.so iconv1.c
然后在做解析
gcc-I/root/czy/test/libxml/libxml2-2.9.0/include -o t main.c -L./ -lmy -lxml2-L/root/czy/test/libxml/libiconv-1.14/lib/.libs –liconv
接着运行./t 就会得到了我们所要的文件了
这里给出一个需要注意的地方,如果 ./t 没有出现结果,反而出错了,这可能就是因为我们没有定义环境变量
这时只需要们加上一条命令 就可以解决了,命令如下:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)