XML_CPP_资料_libXml2_01_Code_ZC(?.pro)
ZC:最下面有 ?.pro文件的设置写法
ZC: Win7x64,qt-opensource-windows-x86-msvc2010_opengl-5.3.2.exe,cn_visual_studio_2010_ultimate_x86_dvd_532347.iso
ZC: 需要和 编译出来的exe放在同一个目录的3个DLL为:iconv.dll、libxml2.dll、zlib1.dll (在下载的libXml2里面有这3个文件)(这一点需要注意 ! ! 不然编译出来的exe在Debug时会报错,而且 从报错的现象上看 也看不出是∵少了这3个DLL...很蛋疼)
1、
#include "mainwindow.h" #include "ui_mainwindow.h" #include <libxml/parser.h> #include <libxml/tree.h> #include <libxml/xpath.h> #include "iconv.h" #include <QDebug> #include <QTextCodec> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pbtnParseEncodeError_clicked() { // ZC: VS2010不管cpp文件的编码 将字符串常亮用Ansi编码,并且 xmlParseMemory默认使用UTF8编码操作,于是 就会报编码的错误。 // ZC: 可以看到 libXML2 的错误信息,是通过console打印出来的 char buf[] ="<?xml version=\"1.0\" encoding=\"UTF-8\"?> <JMSB> <HEAD> <CLJG>中过</CLJG> " \ "<JLTS>recordNo</JLTS>"\ "<CCXX></CCXX>"\ "</HEAD>"\ "</JMSB>"; xmlDocPtr doc = xmlParseMemory((char*)buf, strlen(buf) + 1); xmlFreeDoc(doc);//xmlGenericError xmlSetGenericErrorFunc } // ZC: 创建xml文档 void MainWindow::on_pbtnTest01_clicked() { 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("CreatedXml.xml", doc); if (nRel != -1) { QTextCodec *codec = QTextCodec::codecForName("GBK"); //QTextCodec *codec = QTextCodec::codecForName("UTF-8"); QString str01 = codec->toUnicode("一个xml文档被创建,写入"); QString str02 = codec->toUnicode("个字节"); qDebug() << str01 + QString::number(nRel) + str02; //qDebug() << "一个xml文档被创建,写入" << nRel << "个字节"; } //释放文档内节点动态申请的内存 xmlFreeDoc(doc); } // ZC: 解析xml文档 void MainWindow::on_pbtnParserXML_clicked() { xmlDocPtr doc; //定义解析文档指针 xmlNodePtr curNode; //定义结点指针(你需要它为了在各个结点间移动) xmlChar *szKey; //临时字符串变量 char *szDocName = "CreatedXml.xml"; doc = xmlReadFile(szDocName, "GB2312", XML_PARSE_RECOVER); //解析文件 //检查解析文档是否成功,如果不成功,libxml将指一个注册的错误并停止。 //一个常见错误是不适当的编码。XML标准文档除了用UTF-8或UTF-16外还可用其它编码保存。 //如果文档是这样,libxml将自动地为你转换到UTF-8。更多关于XML编码信息包含在XML标准中. if (NULL == doc) { qDebug() << "Document not parsed successfully."; return; } curNode = xmlDocGetRootElement(doc); //确定文档根元素 /*检查确认当前文档中包含内容*/ if (NULL == curNode) { qDebug() << "Empty document"; xmlFreeDoc(doc); return; } /*在这个例子中,我们需要确认文档是正确的类型。“root”是在这个示例中使用文档的根类型。*/ if (xmlStrcmp(curNode->name, BAD_CAST "root")) { qDebug() << "document of the wrong type, root node != root"; xmlFreeDoc(doc); return; } curNode = curNode->xmlChildrenNode; xmlNodePtr propNodePtr = curNode; while(curNode != NULL) { //取出节点中的内容 if ((!xmlStrcmp(curNode->name, (const xmlChar *)"newNode1"))) { szKey = xmlNodeGetContent(curNode); qDebug() << "newNode1: " << 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"); qDebug() << "get attribute = " << szAttr; xmlFree(szAttr); } attrPtr = attrPtr->next; } xmlFreeDoc(doc); } // ZC: 修改xml文档 void MainWindow::on_pbtnModifyXML_clicked() { xmlDocPtr doc; //定义解析文档指针 xmlNodePtr curNode; //定义结点指针(你需要它为了在各个结点间移动) char *szDocName = "CreatedXml.xml"; doc = xmlReadFile(szDocName, "GB2312", XML_PARSE_RECOVER); //解析文件 if (NULL == doc) { fprintf(stderr,"Document not parsed successfully. \n"); return; } curNode = xmlDocGetRootElement(doc); /*检查确认当前文档中包含内容*/ if (NULL == curNode) { fprintf(stderr,"empty document\n"); xmlFreeDoc(doc); return; } curNode = curNode->children; while (NULL != curNode) { //删除newNode1 if (!xmlStrcmp(curNode->name, BAD_CAST "newNode1")) { xmlNodePtr tempNode; tempNode = curNode->next; xmlUnlinkNode(curNode); // ZC: 解除link xmlFreeNode(curNode); // ZC: 释放内存 curNode = tempNode; continue; } //修改node2的属性值 if (!xmlStrcmp(curNode->name, BAD_CAST "node2")) { xmlSetProp(curNode,BAD_CAST "attribute", BAD_CAST "no"); } //修改newNode2的内容 if (!xmlStrcmp(curNode->name, BAD_CAST "newNode2")) { xmlNodeSetContent(curNode, BAD_CAST "content changed"); } //增加一个属性 if (!xmlStrcmp(curNode->name, BAD_CAST "newNode3")) { xmlNewProp(curNode, BAD_CAST "newAttr", BAD_CAST "YES"); } //增加一个子节点 if (!xmlStrcmp(curNode->name, BAD_CAST "son")) { xmlNewTextChild(curNode, NULL, BAD_CAST "newGrandSon", BAD_CAST "new content"); } curNode = curNode->next; } //存储xml文档 int nRel = xmlSaveFile("ChangedXml.xml",doc); if (nRel != -1) { QTextCodec *codec = QTextCodec::codecForName("GBK"); QString str01 = codec->toUnicode("一个xml文档被创建,写入"); QString str02 = codec->toUnicode("个字节"); qDebug() << str01 +QString::number(nRel) + str02; } xmlFreeDoc(doc); } xmlXPathObjectPtr Get_NodeSet(xmlDocPtr doc, const xmlChar *szXpath) { xmlXPathContextPtr context; //XPATH上下文指针 xmlXPathObjectPtr result; //XPATH对象指针,用来存储查询结果 context = xmlXPathNewContext(doc); //创建一个XPath上下文指针 if (context == NULL) { printf("context is NULL\n"); return NULL; } result = xmlXPathEvalExpression(szXpath, context); //查询XPath表达式,得到一个查询结果 xmlXPathFreeContext(context); //释放上下文指针 if (result == NULL) { printf("xmlXPathEvalExpression return NULL\n"); return NULL; } if (xmlXPathNodeSetIsEmpty(result->nodesetval)) //检查查询结果是否为空 { xmlXPathFreeObject(result); printf("nodeset is empty\n"); return NULL; } return result; } void MainWindow::on_pbtnXPATH_clicked() { xmlDocPtr doc = NULL; //定义解析文档指针 xmlNodePtr curNode = NULL; //定义结点指针(你需要它为了在各个结点间移动) char *szDocName = "CreatedXml.xml"; doc = xmlReadFile(szDocName, "GB2312", XML_PARSE_RECOVER); //解析文件 if (NULL == doc) { fprintf(stderr,"Document not parsed successfully. \n"); return; } xmlChar *szXpath =BAD_CAST ("/root/node2[@attribute='yes']"); xmlXPathObjectPtr app_result = Get_NodeSet(doc,szXpath); //查询并得到结果 if (NULL == app_result) { printf("app_result is NULL\n"); return; } xmlChar *szValue = NULL; if(app_result) { xmlNodeSetPtr nodeset = app_result->nodesetval; for (int i = 0; i < nodeset->nodeNr; i++) { curNode = nodeset->nodeTab[i]; if(curNode != NULL) { szValue = xmlGetProp(curNode,BAD_CAST "attribute"); if (szValue != NULL) { printf("attribute = %s\n", szValue); xmlFree(szValue); } szValue = xmlNodeGetContent(curNode); if (szValue != NULL) { printf("content = %s\n", szValue); xmlFree(szValue); } } } xmlXPathFreeObject (app_result); } xmlFreeDoc(doc); } //代码转换:从一种编码转为另一种编码 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; } void MainWindow::on_pbtnZhongWen_clicked() { //定义文档和节点指针 xmlDocPtr doc = xmlNewDoc(BAD_CAST"1.0"); xmlNodePtr root_node = xmlNewNode(NULL,BAD_CAST"root"); //设置根节点 xmlDocSetRootElement(doc,root_node); //一个中文字符串转换为UTF-8字符串,然后写入 char* szOut = g2u("节点1的内容"); //在根节点中直接创建节点 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"); xmlNewChild(root_node, NULL, BAD_CAST "node1",BAD_CAST szOut); free(szOut); //创建一个节点,设置其内容和属性,然后加入根结点 xmlNodePtr node = xmlNewNode(NULL,BAD_CAST"node2"); xmlNodePtr content = xmlNewText(BAD_CAST"NODE CONTENT"); xmlAddChild(root_node,node); xmlAddChild(node,content); szOut = g2u("属性值"); xmlNewProp(node,BAD_CAST"attribute",BAD_CAST szOut); free(szOut); //创建一个中文节点 szOut = g2u("中文节点"); xmlNewChild(root_node, NULL, BAD_CAST szOut,BAD_CAST "content of chinese node"); free(szOut); //存储xml文档 int nRel = xmlSaveFormatFileEnc("CreatedXml_cn.xml",doc,"GB2312",1); if (nRel != -1) { QTextCodec *codec = QTextCodec::codecForName("GBK"); QString str01 = codec->toUnicode("一个xml文档被创建,写入"); QString str02 = codec->toUnicode("个字节"); qDebug() << str01 + QString::number(nRel) + str02; } xmlFreeDoc(doc); }
2、界面
3、"libxml2_z.pro" (公司的笔记本,"F:\ZZ_Qt5\Qt532_vs2010\libxml2_z")
4、
#-------------------------------------------------
#
# Project created by QtCreator 2016-12-21T15:02:53
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = libxml2_z
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
INCLUDEPATH += F:\ZC_IDE\VC_3rd\libxml2\iconv-1.9.2.win32\include \
F:\ZC_IDE\VC_3rd\libxml2\libxml2-2.6.30.win32\include \
F:\ZC_IDE\VC_3rd\libxml2\zlib-1.2.3.win32\include
LIBPATH += F:/ZC_IDE/VC_3rd/libxml2/iconv-1.9.2.win32/lib \
F:/ZC_IDE/VC_3rd/libxml2/libxml2-2.6.30.win32/lib \
F:/ZC_IDE/VC_3rd/libxml2/zlib-1.2.3.win32/lib
LIBS += -liconv \
-llibxml2 \
-lzlib
#ZC: (1)设置libxml2的头文件目录 (2)设置libxml2的lib文件的目录 (3)指明lib文件 (4)将dll文件复制到exe所在目录(或system32)
5、
6、