邢台网站设计哪家好,网站免费的不用下载,企业网站建设有没有模板,建筑公司的愿景和使命1. 创建XML文档
#xff08;1#xff09;创建一个XML文档非常简单#xff0c;其流程如下#xff1a;
① 用xmlNewDoc函数创建一个文档指针doc。
② 用xmlNewNode函数创建一个节点指针root_node。
③ 用xmlDocSetRootElement将root_node设置为doc的根结点。…1. 创建XML文档
1创建一个XML文档非常简单其流程如下
① 用xmlNewDoc函数创建一个文档指针doc。
② 用xmlNewNode函数创建一个节点指针root_node。
③ 用xmlDocSetRootElement将root_node设置为doc的根结点。
④ 给root_node添加一系列的子节点并设置子节点的内容和属性。
⑤ 用xmlSaveFile将XML文档存入文件。
⑥ 用xmlFreeDoc关闭文档指针并清除本文档中所有节点动态申请的内存。
有多种方式可以添加子节点如可以用xmlNewTextChild直接添加一个文本子节点。也可以先创建新节点然后用xmlAddChild将新节点加入到上层节点中。 (2)创建xml文件举例
CreateXmlFile.c源代码如下
#include stdio.h
#include libxml/parser.h
#include libxml/tree.h
int main()
{ //定义文档和节点指针 xmlDocPtr doc xmlNewDoc(BAD_CAST 1.0); xmlNodePtr root_node xmlNewNode(NULL,BAD_CAST root); //设置根节点 xmlDocSetRootElement(doc,root_node); //在根节点中直接创建节点 xmlNewTextChild(root_node, NULL, BAD_CAST newNode1, BAD_CAST newNode1 content); xmlNewTextChild(root_node, NULL, BAD_CAST newNode2, BAD_CAST newNode2 content); xmlNewTextChild(root_node, NULL, BAD_CAST newNode3, BAD_CAST newNode3 content); //创建一个节点设置其内容和属性然后加入根结点 xmlNodePtr node xmlNewNode(NULL,BAD_CAST node2); xmlNodePtr content xmlNewText(BAD_CAST NODE CONTENT); xmlAddChild(root_node,node); xmlAddChild(node,content); xmlNewProp(node,BAD_CAST attribute,BAD_CAST yes); //创建一个儿子和孙子节点 node xmlNewNode(NULL, BAD_CAST son); xmlAddChild(root_node,node); xmlNodePtr grandson xmlNewNode(NULL, BAD_CAST grandson); xmlAddChild(node,grandson); xmlAddChild(grandson, xmlNewText(BAD_CAST This is a grandson node)); //存储xml文档 int nRel xmlSaveFile(CreateXml.xml,doc); if (nRel ! -1) { printf(一个xml文档被创建写入%d个字节\n, nRel); } //释放文档内节点动态申请的内存 xmlFreeDoc(doc); return 1;
}
编译 gcc CreateXmlFile.c -o CreateXmlFile -I/usr/local/include/libxml2 -lxml2。
执行./CreateXmlFile会生成一个XML文件CreatedXml.xml。打开后如下所示
?xml version1.0?
root newNode1newNode1 content/newNode1 newNode2newNode2 content/newNode2 newNode3newNode3 content/newNode3 node2 attributeyesNODE CONTENT/node2 son grandsonThis is a grandson node/grandson /son
/root
最好使用类似XMLSPY这样的工具打开因为这些工具可以自动整理XML文件的栅格否则很有可能是没有任何换行的一个XML文件可读性较差。
2. 解析XML文档
1XML解析流程
解析一个XML文档从中取出想要的信息例如节点中包含的文字或者某个节点的属性。其流程如下
① 用xmlReadFile函数读入一个文件并返回一个文档指针doc。
② 用xmlDocGetRootElement函数得到根节点curNode。
③ 此时curNode-xmlChildrenNode就是根节点的首个儿子节点该儿子节点的兄弟节点可用next指针进行轮询。
④ 轮询所有子节点找到所需的节点用xmlNodeGetContent取出其内容。
⑤ 用xmlHasProp查找含有某个属性的节点属性列表指针xmlAttrPtr将指向该节点的属性列表。
⑥ 取出该节点的属性用xmlGetProp取出其属性值。
⑦ xmlFreeDoc函数关闭文档指针并清除本文档中所有节点动态申请的内存。 2XML解析举例
ParseXmlFile.c源代码如下
#include stdio.h
#include libxml/parser.h
#include libxml/tree.h
int main(int argc, char* argv[])
{ xmlDocPtr doc; //定义解析文件指针 xmlNodePtr curNode; //定义结点指针 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,Document not parsed successfully.); return -1; } //获取根节点 curNode xmlDocGetRootElement(doc); if (NULL curNode) { fprintf(stderr,empty document); xmlFreeDoc(doc); return -1; } //确认根元素名字是否符合 if (xmlStrcmp(curNode-name, BAD_CAST root)) { fprintf(stderr,document of the wrong type, root node ! root); xmlFreeDoc(doc); return -1; } curNode curNode-xmlChildrenNode; xmlNodePtr propNodePtr curNode; while(curNode ! NULL) { //取出节点中的内容 if ((!xmlStrcmp(curNode-name, (const xmlChar *) newNode1))) { szKey xmlNodeGetContent(curNode); printf(newNode1: %s\n, szKey); 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(get attribute%s\n, szAttr) ; xmlFree(szAttr); } attrPtr attrPtr-next; } xmlFreeDoc(doc); return 0;
}
编译 gcc ParseXmlFile.c -o ParseXmlFile -I/usr/local/include/libxml2 -lxml2。
执行 ./ParseXmlFile CreateXml.xml执行结果如下
newNode1: newNode1 content
get attributeyes
3. 修改XML文档
有了上面的基础修改XML文档的内容就简单了。首先打开一个已经存在的XML文档顺着根结点找到需要添加、删除、修改的地方调用相应的XML函数对节点进行增、删、改操作。
需要注意的是并没有xmlDelNode或者xmlRemoveNode函数删除节点需使用以下一段代码 if (!xmlStrcmp(curNode-name, BAD_CAST newNode1)) { xmlNodePtr tempNode; tempNode curNode-next; xmlUnlinkNode(curNode); xmlFreeNode(curNode); curNode tempNode; continue; }
此段代码完成将当前节点从文档中断链unlink这样此XML文档就不会再包含这个节点该节点断链后需使用xmlFreeNode来释放该节点申请的动态内存空间。
4. 使用XPath查找XML文档
在libxml2中使用XPath非常简单其流程如下
① 定义一个XPath上下文指针xmlXPathContextPtr context并且使用xmlXPathNewContext函数来初始化这个指针。
② 定义一个XPath对象指针xmlXPathObjectPtr result并且使用xmlXPathEvalExpression函数来计算XPath表达式得到查询结果将结果存入对象指针中。
③ 使用result-nodesetval得到节点集合指针其中包含了所有符合XPath查询结果的节点。
④ 使用xmlXPathFreeContext释放上下文指针。
⑤ 使用xmlXPathFreeObject释放XPath对象指针。 XPath操作代码示例如下
xmlXPathObjectPtr getNodeSet(xmlDocPtr doc, const xmlChar *szXpath)
{ xmlXPathContextPtr context; //XPath上下文指针 xmlXPathObjectPtr result; //XPath对象指针用来存储查询结果 context xmlXPathNewContext(doc); //创建一个XPath上下文指针 if (context NULL) { printf(context is NULLn); return NULL; } result xmlXPathEvalExpression(szXpath, context); //查询XPath表达式得到一个查询结果 xmlXPathFreeContext(context); //释放上下文指针 if (result NULL) { printf(xmlXPathEvalExpression return NULLn); return NULL; } if (xmlXPathNodeSetIsEmpty(result-nodesetval)) //检查查询结果是否为空 { xmlXPathFreeObject(result); printf(nodeset is emptyn); return NULL; } return result;
}
5. 用iconv解决XML中字符集问题
libxml2中默认的内码是UTF-8所有使用libxml2进行处理的xml文件必须首先显式或者默认转换为UTF-8编码才能被处理。
要在XML中使用中文就必须能够在UTF-8和GB2312之间进行转换。libxml2提供了默认的内码转换机制并且在libxml2的Tutorial中有一个例子事实证明这个例子并不很适合用来转换中文。
有些场合需要使用iconv来进行编码转换libxml2本身也是使用iconv进行编码转换的。iconv是一个专门用来进行编码转换的库基本上支持目前所有常用的编码它是glibc库的一个部分。
本节其实和libxml没有太大关系可以把它简单看作是一个编码转换方面的专题。下文提供了一个通用转码函数并在此基础上实现了两个转码封装函数即从UTF-8转换到GB2312的函数u2g以及反向转换的函数g2u。其代码如下
#include iconv.h
#include string.h
//代码转换从一种编码转为另一种编码
int code_convert(char* from_charset, char* to_charset, char* inbuf, int inlen, char* outbuf, int outlen)
{ iconv_t cd; char** pin inbuf; char** pout outbuf; cd iconv_open(to_charset,from_charset); if(cd 0) return -1; memset(outbuf,0,outlen); if(iconv(cd,(const char**)pin,(unsigned int *)inlen,pout,(unsigned int*)outlen) -1) return -1; iconv_close(cd); return 0;
}
//UNICODE码转为GB2312码
//成功则返回一个动态分配的char*变量需要在使用完毕后手动free失败返回NULL
char* u2g(char *inbuf)
{ int nOutLen 2 * strlen(inbuf) - 1; char* szOut (char*)malloc(nOutLen); if (-1 code_convert(utf-8,gb2312,inbuf,strlen(inbuf),szOut,nOutLen)) { free(szOut); szOut NULL; } return szOut;
}
//GB2312码转为UNICODE码
//成功则返回一个动态分配的char*变量需要在使用完毕后手动free失败返回NULL
char* g2u(char *inbuf)
{ int nOutLen 2 * strlen(inbuf) - 1; char* szOut (char*)malloc(nOutLen); if (-1 code_convert(gb2312,utf-8,inbuf,strlen(inbuf),szOut,nOutLen)) { free(szOut); szOut NULL; } return szOut;
}
下面以UTF-8到GB2312转码流程说明上文中转码函数的使用使用流程如下
① 得到一个UTF-8的字符串szSrc。
② 定义一个char *的字符指针szDes并不需要给它动态申请内存。
③ 调用szDes u2g(szSrc)这样szDes就指向转换后GB2312编码的字符串。
④ 使用完这个字符串后使用free(szDes)来释放内存。
如果转码文件可以选择系统调用来进行文件转码。下文中f表示fromt表示to其转码方法如下
system(iconv –f 源格式 –t 目标格式 源文件 目标文件)
system(iconv –f GB18030 –t UTF-8 test_gb.txt test_utf.txt)