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、

 

posted @ 2016-12-23 10:23  CppSkill  阅读(337)  评论(0编辑  收藏  举报