XML_CPP_资料_libXml2_01_Code

ZC: 这里的代码,就是 http://www.cnblogs.com/cppskill/p/6207609.html(我的文章"XML_CPP_资料_libXml2_01 - CppSkill - 博客园.html")里面的代码...

1、创建xml文档

  1.1、CreateXmlFile.cpp

/********************************************************************
    created:    2007/11/09
    created:    9:11:2007   15:34
    filename:    CreateXmlFile.cpp
    author:        Wang xuebin 
    depend:        libxml2.lib 
    build:        nmake TARGET_NAME=CreateXmlFile
    
    purpose:    创建一个xml文件
*********************************************************************/

#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <iostream.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("CreatedXml.xml",doc);
    if (nRel != -1)
    {
        cout<<"一个xml文档被创建,写入"<<nRel<<"个字节"<<endl;
    }

    //释放文档内节点动态申请的内存
    xmlFreeDoc(doc);
    return 1;
}

  1.2、CreatedXml.xml

<?xml version="1.0"?>
<root>
    <newNode1>newNode1 content</newNode1>
    <newNode2>newNode2 content</newNode2>
    <newNode3>newNode3 content</newNode3>
    <node2 attribute="yes">NODE CONTENT</node2>
    <son>
        <grandson>This is a grandson node</grandson>
    </son>
</root>

2、解析xml文档

  2.1、ParseXmlFile.cpp

/********************************************************************
    created:    2007/11/15
    created:    15:11:2007   11:47
    filename:    ParseXmlFile.cpp
    author:        Wang xuebin 
    depend:        libxml2.lib
    build:        nmake TARGET_NAME=ParseXmlFile
    
    purpose:    解析xml文件
*********************************************************************/

#include <libxml/parser.h>
#include <iostream.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外还可用其它编码保存。
    //如果文档是这样,libxml将自动地为你转换到UTF-8。更多关于XML编码信息包含在XML标准中.
    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; 
    } 
    
    /*在这个例子中,我们需要确认文档是正确的类型。“root”是在这个示例中使用文档的根类型。*/
    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
", 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");
            cout<<"get attribute = "<<szAttr<<endl;
            xmlFree(szAttr);
        }
        attrPtr = attrPtr->next;
    }

    xmlFreeDoc(doc);
    return 0;
}

  2.2、ParseXmlFile.exe CreatedXml.xml

3、修改xml文档

  3.1、ChangeXmlFile.cpp

/********************************************************************
    created:    2007/11/15
    created:    15:11:2007   15:20
    filename:    ChangeXmlFile.cpp
    author:        Wang xuebin 
    depend:        libxml2.lib
    build:        nmake TARGET_NAME=ChangeXmlFile
    
    purpose:    修改XML元素及属性
*********************************************************************/

#include <libxml/parser.h>
#include <iostream.h>

int main(int argc, char* argv[])
{
    xmlDocPtr doc;   //定义解析文档指针 
    xmlNodePtr curNode;  //定义结点指针(你需要它为了在各个结点间移动) 

    char *szDocName;
    if (argc <= 1)  
    {
        printf("Usage: %s docname
", argv[0]);
        return(0);
    }
    szDocName = argv[1];

    doc = xmlReadFile(szDocName,"GB2312",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; 
    } 

    curNode = curNode->children;
    while (NULL != curNode)
    {
        //删除newNode1
        if (!xmlStrcmp(curNode->name, BAD_CAST "newNode1"))
        {
            xmlNodePtr tempNode;
            tempNode = curNode->next;
            xmlUnlinkNode(curNode);
            xmlFreeNode(curNode);
            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)
    {
        cout<<"一个xml文档被创建,写入"<<nRel<<"个字节"<<endl;
    }
    xmlFreeDoc(doc); 
    return 0;
}

  3.2、ChangedXml.xml  (ChangeXmlFile.exe CreatedXml.xml)

<?xml version="1.0"?>
<root>
    
    <newNode2>content changed</newNode2>
    <newNode3 newAttr="YES">newNode3 content</newNode3>
    <node2 attribute="no">NODE CONTENT</node2>
    <son>
        <grandson>This is a grandson node</grandson>
    <newGrandSon>new content</newGrandSon></son>
</root>

4、使用XPATH查找xml文档

  4.1、XPathForXmlFile.cpp

/********************************************************************
    created:    2007/11/15
    created:    15:11:2007   16:01
    filename:    XpathForXmlFile.cpp
    author:        Wang xuebin 
    depend:        libxml2.lib
    build:        nmake TARGET_NAME=XPathForXmlFile
    
    purpose:    使用XPATH查找xml文档中的节点
*********************************************************************/

#include <libxml/parser.h>
#include <libxml/xpath.h>
#include <iostream.h>

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
");
        return NULL; 
    }
    
    result = xmlXPathEvalExpression(szXpath, context); //查询XPath表达式,得到一个查询结果
    xmlXPathFreeContext(context);                //释放上下文指针
    if (result == NULL) 
    {
        printf("xmlXPathEvalExpression return NULL
"); 
        return NULL;  
    }
    
    if (xmlXPathNodeSetIsEmpty(result->nodesetval))   //检查查询结果是否为空
    {
        xmlXPathFreeObject(result);
        printf("nodeset is empty
");
        return NULL;
    }
    
    return result;    
}

int main(int argc, char* argv[])
{
    xmlDocPtr doc = NULL;             //定义解析文档指针 
    xmlNodePtr curNode = NULL;         //定义结点指针(你需要它为了在各个结点间移动) 

    char *szDocName = NULL;
    if (argc <= 1)  
    {
        printf("Usage: %s docname
", argv[0]);
        return(0);
    }
    szDocName = argv[1];

    doc = xmlReadFile(szDocName,"GB2312",XML_PARSE_RECOVER);  //解析文件 
    
    if (NULL == doc) 
    {     
        fprintf(stderr,"Document not parsed successfully. 
");     
        return -1; 
    } 
    
    xmlChar *szXpath =BAD_CAST ("/root/node2[@attribute='yes']"); 
    xmlXPathObjectPtr app_result = get_nodeset(doc,szXpath);  //查询并得到结果
    
    if (NULL == app_result) 
    {
        printf("app_result is NULL
"); 
        return -1;
    }
    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
", szValue);
                    xmlFree(szValue);
                }
                
                szValue = xmlNodeGetContent(curNode);
                if (szValue != NULL) 
                {
                    printf("content = %s
", szValue);
                    xmlFree(szValue);
                }
            }
        }
        xmlXPathFreeObject (app_result);
    }
    xmlFreeDoc(doc);
    return 0;
}

  4.2、XpathForXmlFile.exe CreatedXml.xml

5、用ICONV解决XML中的中文问题

  5.1、wxb_codeConv.c

/********************************************************************
    created:    2007/11/15
    created:    15:11:2007   10:30
    filename:    wxb_codeConv.c
    author:        Wang xuebin 
    depend:        iconv.lib
    build:        不需要build,被包含到其它源代码中
    
    purpose:    提供从UTF-8到GB2312的内码转换,以及反向的转换
*********************************************************************/

#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;
}   

  5.2、CreateXmlFile_cn.cpp

/********************************************************************
    created:    2007/11/17
    created:    9:11:2007   15:34
    filename:    CreateXmlFile.cpp
    author:        Wang xuebin 
    depend:        libxml2.lib iconv.lib
    build:        nmake TARGET_NAME=CreateXmlFile_cn
    
    purpose:    创建一个xml文件,其中包含中文
*********************************************************************/

#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <iostream.h>
#include "wxb_codeConv.c"  //自己写的编码转换函数

int main(int argc, char **argv)
{
    //定义文档和节点指针
    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)
    {
        cout<<"一个xml文档被创建,写入"<<nRel<<"个字节"<<endl;
    }

    xmlFreeDoc(doc);

    return 1;
}

  5.3、CreatedXml_cn.xml

<?xml version="1.0" encoding="GB2312"?>
<root>
  <newNode1>newNode1 content</newNode1>
  <newNode2>newNode2 content</newNode2>
  <newNode3>newNode3 content</newNode3>
  <node1>节点1的内容</node1>
  <node2 attribute="属性值">NODE CONTENT</node2>
  <中文节点>content of chinese node</中文节点>
</root>

6、用XML来做点什么

  6.1、1.xml

<?xml version="1.0" encoding="GB2312"?>
<root>
    <My_Program_Code content="1"></My_Program_Code>
</root>

7、

8、

原文地址:https://www.cnblogs.com/cppskill/p/6213572.html