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; }
运行结果: