tinyxml解析xml

基于tinyxml做的简单的xml解析。

1.创建xml

bool CreateXmlFile(string& szFileName)
{//创建xml文件,szFilePath为文件保存的路径,若创建成功返回true,否则false
    try
    {
        //创建一个XML的文档对象。
        TiXmlDocument *myDocument = new TiXmlDocument();

        TiXmlElement *RootElement = new TiXmlElement("Response");
        myDocument->LinkEndChild(RootElement);

        TiXmlElement *DeviceListElement = new TiXmlElement("DeviceList");
        RootElement->LinkEndChild(DeviceListElement);

        DeviceListElement->SetAttribute("Num", "3");

        TiXmlElement *ItemElement = new TiXmlElement("Item");
        DeviceListElement->LinkEndChild(ItemElement);


        TiXmlElement *DeviceIDElement = new TiXmlElement("DeviceID");
        TiXmlElement *NameElement = new TiXmlElement("Name");
        ItemElement->LinkEndChild(DeviceIDElement);
        ItemElement->LinkEndChild(NameElement);

        TiXmlText *DeviceIDContent = new TiXmlText("44130000002000000002");
        TiXmlText *NameContent = new TiXmlText("测试平台");
        DeviceIDElement->LinkEndChild(DeviceIDContent);
        NameElement->LinkEndChild(NameContent);

        myDocument->SaveFile(szFileName.c_str());//保存到文件
    }
    catch (string& e)
    {
        return false;
    }
    return true;
}

创建出来的xml如下:

<Response>
    <DeviceList Num="3">
        <Item>
            <DeviceID>44130000002000000002</DeviceID>
            <Name>测试平台</Name>
        </Item>
    </DeviceList>
</Response>

2.读取xml

(1)从文件读取xml

bool ReadXmlFile(string& szFileName)
{//读取Xml文件,并遍历
    try
    {
        //创建一个XML的文档对象。
        TiXmlDocument *myDocument = new TiXmlDocument(szFileName.c_str());
        myDocument->LoadFile();
        //获得根元素,即Response。
        TiXmlElement *RootElement = myDocument->RootElement();
        //输出根元素名称,即输出Response。
        cout << RootElement->Value() << endl;
        //获得第一个DeviceList节点。
        TiXmlElement *DeviceListElement = RootElement->FirstChildElement();
        TiXmlAttribute *NumAttribute = DeviceListElement->FirstAttribute();
        cout << NumAttribute->Value()<< endl;

        //获得第一个Person的name节点和age节点和ID属性。
        TiXmlElement *ItemElement = DeviceListElement->FirstChildElement();
        for (int i = 0; i < 3; i++)
        {
            if (ItemElement)
            {
                TiXmlElement *DeviceIDElement = ItemElement->FirstChildElement();
                //这里注意判断是否存在,否则容易崩溃
                if (DeviceIDElement && DeviceIDElement->FirstChild())
                {
                    cout << DeviceIDElement->FirstChild()->Value() << endl;

                    TiXmlElement *NameElement = DeviceIDElement->NextSiblingElement();
                    if (NameElement && NameElement->FirstChild())
                    {
                        cout << NameElement->FirstChild()->Value() << endl;

                        TiXmlElement *ParentIDElement = NameElement->NextSiblingElement();
                        if (ParentIDElement && ParentIDElement->FirstChild())
                        {
                            cout << ParentIDElement->FirstChild()->Value() << endl;
                        }
                    }
                }

                ItemElement = ItemElement->NextSiblingElement();
            }
        }
    }
    catch (string& e)
    {
        return false;
    }
    return true;
}

(2)从字符串解析xml

bool ReadXmlString(string& xmlString, VEC_DEVICE& device_list)
{//读取Xml文件,并遍历
    try
    {
        //创建一个XML的文档对象。
        TiXmlDocument *myDocument = new TiXmlDocument();
        myDocument->Parse(xmlString.c_str());
        //获得根元素,即Response。
        TiXmlElement *RootElement = myDocument->RootElement();
        //输出根元素名称,即输出Response。
        cout << RootElement->Value() << endl;
        //获得第一个DeviceList节点。
        TiXmlElement *DeviceListElement = RootElement->FirstChildElement();
        TiXmlAttribute *NumAttribute = DeviceListElement->FirstAttribute();
        cout << NumAttribute->Value()<< endl;

        //获得第一个Person的name节点和age节点和ID属性。
        TiXmlElement *ItemElement = DeviceListElement->FirstChildElement();
        ST_DEVICE_INFO device_info ;
        for (; ItemElement != NULL; ItemElement = ItemElement->NextSiblingElement())
        {
            if (ItemElement)
            {
                ST_DEVICE_INFO device_info;
                TiXmlElement *DeviceIDElement = ItemElement->FirstChildElement();
                if (DeviceIDElement && DeviceIDElement->FirstChild())
                {
                    string str = "";
                    str = DeviceIDElement->FirstChild()->Value();
                    //注意是否需要从utf-8转为GBK
                    device_info.m_strID = str.c_str();// UtfToGbk(str.c_str());
                    cout << "ID   "<<device_info.m_strID.c_str()<< endl;

                    TiXmlElement *NameElement = DeviceIDElement->NextSiblingElement();
                    if (NameElement && NameElement->FirstChild())
                    {
                        str = "";
                        str = NameElement->FirstChild()->Value();
                        device_info.m_strName = str.c_str();// UtfToGbk(str.c_str());
                        cout << "name  "<< device_info.m_strName << endl;

                        TiXmlElement *ParentIDElement = NameElement->NextSiblingElement();
                        if (ParentIDElement && ParentIDElement->FirstChild())
                        {
                            str = "";
                            str = ParentIDElement->FirstChild()->Value();
                            device_info.m_strParentID = str.c_str();// UtfToGbk(str.c_str());
                            cout << "m_strParentID  "<<device_info.m_strParentID.c_str()<< endl;
                        }

                        device_info.m_nStatus = 1;

                        device_list.push_back(device_info);
                    }
                }
                else
                {
                    continue;
                }
            }
        }
    }
    catch (string& e)
    {
        return false;
    }
    return true;
}

从文件解析xml与从字符串解析xml的不同仅仅在加载xml的方式不同。

从文件是:

TiXmlDocument *myDocument = new TiXmlDocument(szFileName.c_str()); //szFileName为文件路径名
myDocument->LoadFile();

从字符串加载是:

TiXmlDocument *myDocument = new TiXmlDocument();
myDocument->Parse(xmlString.c_str());    //xmlString是字符串

如字符串可以为:

string xmlStr = "
                <?xml version="1.0" encoding="utf - 8" standalone="no" ?> 
                <Response>
                    <DeviceList Num="3">
                        <Item>
                            <DeviceID>44130000002000000002</DeviceID>
                            <Name>测试平台</Name>
                        </Item>
                        <Item>
                            <DeviceID>441301</DeviceID>
                            <Name>惠州市</Name>
                            <ParentID>44130000002000000002</ParentID>
                        </Item>
                        <Item>
                            <DeviceID>44130000002000000068</DeviceID>
                            <Name>邮政储蓄门口</Name>
                            <ParentID>441301</ParentID>
                        </Item>
                        <Item>
                            <DeviceID>44130000002000000068</DeviceID>
                            <Name>邮政储蓄门口</Name>
                            <ParentID>441301</ParentID>
                        </Item>
                        <Item>
                            <DeviceID>44130000002000000068</DeviceID>
                            <Name>邮政储蓄门口</Name>
                            <ParentID>441301</ParentID>
                        </Item>
                        <Item>
                            <DeviceID>44130000002000000068</DeviceID>
                            <Name>邮政储蓄门口</Name>
                            <ParentID>441301</ParentID>
                        </Item>
                        <Item>
                            <DeviceID>44130000002000000068</DeviceID>
                            <Name>邮政储蓄门口</Name>
                            <ParentID>441301</ParentID>
                        </Item>
                        <Item>
                            <DeviceID>44130000002000000068</DeviceID>
                            <Name>邮政储蓄门口</Name>
                            <ParentID>441301</ParentID>
                        </Item>
                    </DeviceList>
                </Response>" ;

有的时候需要从UTF-8转GBK,否则会乱码:

std::string UtfToGbk(const char* utf8)
{
    int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
    wchar_t* wstr = new wchar_t[len + 1];
    memset(wstr, 0, len + 1);
    MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len);
    len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
    char* str = new char[len + 1];
    memset(str, 0, len + 1);
    WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
    if (wstr) delete[] wstr;
    return str;
}

3.完整的demo

以下是VS2013上的一个例子,搞怪的是utf-8转成GBK也不会乱码,转成GBK反而会乱码,原因不明。

// xmlTest.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <iostream>
#include <string>
#include <windows.h>
#include <atlstr.h>
#include <vector>

#define TIXML_USE_STL
#include "tinyxml.h"
#include "tinystr.h"

#pragma comment(lib,"tinyxmlSTL.lib")

using namespace std;

struct ST_DEVICE_INFO
{
    string m_strID;                 //设备ID
    string m_strParentID;           //父ID
    string m_strName;               //设备名

    int m_nType;                    //类型
    int m_nStatus;                  //状态

    float m_fLongitude;             //经度
    float m_fLatitude;              //纬度

    ST_DEVICE_INFO()
    {
        m_strID.clear();
        m_strParentID.clear();
        m_strName.clear();

        m_nType = 0;
        m_nStatus = 0;

        m_fLongitude = 0;
        m_fLatitude = 0;
    }
};
typedef vector<ST_DEVICE_INFO> VEC_DEVICE;

std::string UtfToGbk(const char* utf8)
{
    int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
    wchar_t* wstr = new wchar_t[len + 1];
    memset(wstr, 0, len + 1);
    MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len);
    len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
    char* str = new char[len + 1];
    memset(str, 0, len + 1);
    WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
    if (wstr) delete[] wstr;
    return str;
}

bool CreateXmlFile(string& szFileName)
{//创建xml文件,szFilePath为文件保存的路径,若创建成功返回true,否则false
    try
    {
        //创建一个XML的文档对象。
        TiXmlDocument *myDocument = new TiXmlDocument();

        TiXmlElement *RootElement = new TiXmlElement("Response");
        myDocument->LinkEndChild(RootElement);

        TiXmlElement *DeviceListElement = new TiXmlElement("DeviceList");
        RootElement->LinkEndChild(DeviceListElement);

        DeviceListElement->SetAttribute("Num", "3");

        TiXmlElement *ItemElement = new TiXmlElement("Item");
        DeviceListElement->LinkEndChild(ItemElement);


        TiXmlElement *DeviceIDElement = new TiXmlElement("DeviceID");
        TiXmlElement *NameElement = new TiXmlElement("Name");
        ItemElement->LinkEndChild(DeviceIDElement);
        ItemElement->LinkEndChild(NameElement);

        TiXmlText *DeviceIDContent = new TiXmlText("44130000002000000002");
        TiXmlText *NameContent = new TiXmlText("测试平台");
        DeviceIDElement->LinkEndChild(DeviceIDContent);
        NameElement->LinkEndChild(NameContent);

        myDocument->SaveFile(szFileName.c_str());//保存到文件
    }
    catch (string& e)
    {
        return false;
    }
    return true;
}

bool ReadXmlFile(string& szFileName)
{//读取Xml文件,并遍历
    try
    {
        //创建一个XML的文档对象。
        TiXmlDocument *myDocument = new TiXmlDocument(szFileName.c_str());
        myDocument->LoadFile();
        //获得根元素,即Response。
        TiXmlElement *RootElement = myDocument->RootElement();
        //输出根元素名称,即输出Response。
        cout << RootElement->Value() << endl;
        //获得第一个DeviceList节点。
        TiXmlElement *DeviceListElement = RootElement->FirstChildElement();
        TiXmlAttribute *NumAttribute = DeviceListElement->FirstAttribute();
        cout << NumAttribute->Value()<< endl;

        //获得第一个Person的name节点和age节点和ID属性。
        TiXmlElement *ItemElement = DeviceListElement->FirstChildElement();
        for (int i = 0; i < 3; i++)
        {
            if (ItemElement)
            {
                TiXmlElement *DeviceIDElement = ItemElement->FirstChildElement();
                //这里注意判断是否存在,否则容易崩溃
                if (DeviceIDElement && DeviceIDElement->FirstChild())
                {
                    cout << DeviceIDElement->FirstChild()->Value() << endl;

                    TiXmlElement *NameElement = DeviceIDElement->NextSiblingElement();
                    if (NameElement && NameElement->FirstChild())
                    {
                        cout << NameElement->FirstChild()->Value() << endl;

                        TiXmlElement *ParentIDElement = NameElement->NextSiblingElement();
                        if (ParentIDElement && ParentIDElement->FirstChild())
                        {
                            cout << ParentIDElement->FirstChild()->Value() << endl;
                        }
                    }
                }

                ItemElement = ItemElement->NextSiblingElement();
            }
        }
    }
    catch (string& e)
    {
        return false;
    }
    return true;
}

bool ReadXmlString(string& xmlString, VEC_DEVICE& device_list)
{//读取Xml文件,并遍历
    try
    {
        //创建一个XML的文档对象。
        TiXmlDocument *myDocument = new TiXmlDocument();
        myDocument->Parse(xmlString.c_str());
        //获得根元素,即Response。
        TiXmlElement *RootElement = myDocument->RootElement();
        //输出根元素名称,即输出Response。
        cout << RootElement->Value() << endl;
        //获得第一个DeviceList节点。
        TiXmlElement *DeviceListElement = RootElement->FirstChildElement();
        TiXmlAttribute *NumAttribute = DeviceListElement->FirstAttribute();
        cout << NumAttribute->Value()<< endl;

        //获得第一个Person的name节点和age节点和ID属性。
        TiXmlElement *ItemElement = DeviceListElement->FirstChildElement();
        ST_DEVICE_INFO device_info ;
        for (; ItemElement != NULL; ItemElement = ItemElement->NextSiblingElement())
        {
            if (ItemElement)
            {
                ST_DEVICE_INFO device_info;
                TiXmlElement *DeviceIDElement = ItemElement->FirstChildElement();
                if (DeviceIDElement && DeviceIDElement->FirstChild())
                {
                    string str = "";
                    str = DeviceIDElement->FirstChild()->Value();
                    //注意是否需要从utf-8转为GBK
                    device_info.m_strID = str.c_str();// UtfToGbk(str.c_str());
                    cout << "ID   "<<device_info.m_strID.c_str()<< endl;

                    TiXmlElement *NameElement = DeviceIDElement->NextSiblingElement();
                    if (NameElement && NameElement->FirstChild())
                    {
                        str = "";
                        str = NameElement->FirstChild()->Value();
                        device_info.m_strName = str.c_str();// UtfToGbk(str.c_str());
                        cout << "name  "<< device_info.m_strName << endl;

                        TiXmlElement *ParentIDElement = NameElement->NextSiblingElement();
                        if (ParentIDElement && ParentIDElement->FirstChild())
                        {
                            str = "";
                            str = ParentIDElement->FirstChild()->Value();
                            device_info.m_strParentID = str.c_str();// UtfToGbk(str.c_str());
                            cout << "m_strParentID  "<<device_info.m_strParentID.c_str()<< endl;
                        }

                        device_info.m_nStatus = 1;

                        device_list.push_back(device_info);
                    }
                }
                else
                {
                    continue;
                }
            }
        }
    }
    catch (string& e)
    {
        return false;
    }
    return true;
}

int _tmain(int argc, _TCHAR* argv[])
{
    string fileName = "test.xml";
    CreateXmlFile(fileName);

    cout << "xml文件解析:" << endl;
    ReadXmlFile(fileName);

    cout << endl;
    cout << "字符串解析:" << endl;

    string xmlStr = "
                <?xml version="1.0" encoding="utf - 8" standalone="no" ?> 
                <Response>
                    <DeviceList Num="3">
                        <Item>
                            <DeviceID>44130000002000000002</DeviceID>
                            <Name>测试平台</Name>
                        </Item>
                        <Item>
                            <DeviceID>441301</DeviceID>
                            <Name>惠州市</Name>
                            <ParentID>44130000002000000002</ParentID>
                        </Item>
                        <Item>
                            <DeviceID>44130000002000000068</DeviceID>
                            <Name>邮政储蓄门口</Name>
                            <ParentID>441301</ParentID>
                        </Item>
                        <Item>
                            <DeviceID>44130000002000000068</DeviceID>
                            <Name>邮政储蓄门口</Name>
                            <ParentID>441301</ParentID>
                        </Item>
                        <Item>
                            <DeviceID>44130000002000000068</DeviceID>
                            <Name>邮政储蓄门口</Name>
                            <ParentID>441301</ParentID>
                        </Item>
                        <Item>
                            <DeviceID>44130000002000000068</DeviceID>
                            <Name>邮政储蓄门口</Name>
                            <ParentID>441301</ParentID>
                        </Item>
                        <Item>
                            <DeviceID>44130000002000000068</DeviceID>
                            <Name>邮政储蓄门口</Name>
                            <ParentID>441301</ParentID>
                        </Item>
                        <Item>
                            <DeviceID>44130000002000000068</DeviceID>
                            <Name>邮政储蓄门口</Name>
                            <ParentID>441301</ParentID>
                        </Item>
                    </DeviceList>
                </Response>" ;

    VEC_DEVICE device_list ;
    device_list.clear() ;
    ReadXmlString(xmlStr, device_list) ;
    cout << endl;

    for (int i = 0; i < device_list.size(); i++)
    {
        cout<< "设备ID:" <<device_list[i].m_strID<<"  设备名称:"<<device_list[i].m_strName<<"   父ID: "<<device_list[i].m_strParentID<<endl ;
    }

    system("pause");

    return 0;
}

运行结果:

image

完整工程地址:https://gitee.com/betterwgo/timyxml

原文地址:https://www.cnblogs.com/betterwgo/p/7895891.html