近要做一个VRP的算法,测试集都是放在Xml文件中,而我的算法使用C++来写,所以需要用C++来读取Xml文件。
  在百度上搜“C++读取Xml文件”,可以出来很多博客,大多数是关于tinyXml的,所以这篇博文也是讲述如何用tinyXML来读取XML文件。
  有些内容可能参考到了@marchtea的博文《C++读取XML,tinyXml的使用》:http://www.cnblogs.com/marchtea/archive/2012/11/08/2760593.html
  tinyXml是一个免费开源的C++库,可以到官网上下载:https://sourceforge.net/projects/tinyxml/
  下载下来解压之后,可以看到下面这些文件:
  我是在windows下用VS来写C++的,按照@marchtea的说法,只需要直接打开tinyxml.sln可以,不过我还是用了笨办法:
  把tinystr.cpp,tinyxml.cpp,tinyxmlerror.cpp,tinyxmlparser.cpp,tinystr.h,tinyxml.h拷贝到工程目录下;
  然后加入头文件引用:#include"tinystr.h"#include"tinyxml.h"。
  接下来来分享一下我读取VRP问题中的solomonbenchmark的方法,这些方法都是参考自tinyXml的官方教程,在下载的文件夹中有"doc"子文件夹,打开它,有一个叫做"tutorial0"的html文件,打开它可以看到详细的教程。
  OK,nowbegins!
  我要读取的Xml文件有如下的格式(只列举部分):
<!--要读取的Xml文件-->
<?xmlversion="1.0"encoding="UTF-8"standalone="yes"?>
<instance>
<network>
<nodes>
<nodeid="0"type="0">
<cx>40.0</cx>
<cy>50.0</cy>
</node>
<!--有N+1个这样的node节点-->
</nodes>
</network>
<requests>
<requestid="1"node="1">
<tw>
<start>145</start>
<end>175</end>
</tw>
<quantity>20.0</quantity>
<service_time>10.0</service_time>
</request>
<!--有N个这样的request节点-->
</requests>
</instance>
  这里稍微解释一下为什么nodes节点的数目会比requests节点多1个。这是因为nodes节点包括了顾客节点(N个)和仓库节点(1个),而requests属性只属于顾客节点。
  我是把xml文件中的这些数据读入到类对象数组中,每个类对象代表一个节点,类的定义如下:
//Customer.h
#ifndef_Customer_H
#define_Customer_H
classCustomer{
public:
Customer(intid=0,floatx=0,floaty=0,floatstartTime=0,floatendTime=0,floatquantity=0,floatserviceTime=0);
voidsetId(intid);//设置成员id的值
voidsetX(floatx);//设置成员x的值
voidsetY(floaty);//设置成员y的值
voidsetStartTime(floatstartTime);//设置成员startTime的值
voidsetEndTime(floatendTime);//设置成员endTime的值
voidsetQuantity(floatquantity);//设置成员quantity的值
voidsetServiceTime(floatserviceTime);//设置成员serviceTime的值
voidshow();//显示顾客节点信息
private:
intid;
floatx;
floaty;
floatstartTime;
floatendTime;
floatquantity;
floatserviceTime;
};
#endif
  OK,那么现在开始贴一下main.cpp代码(Customer.cpp比较简单,不贴了)
//main.cpp
#include"Customer.h"
#include"tinystr.h"
#include"tinyxml.h"
#include<iostream>
#include<vector>
#include<string>
#include<stdlib.h>
#include<iomanip>
usingnamespacestd;
staticconstintNUM_OF_CUSTOMER=51;//顾客数量
staticconstchar*FILENAME="RC101_050.xml";//文件名
intmain(){
vector<Customer*>customerSet(0);//顾客集,每个元素是Customer对象的指针
inti,j,k,count;
inttemp1;//存放整型数据
floattemp2;//存放浮点型数据
Customer*customer;//临时顾客节点指针
for(i=0;i<NUM_OF_CUSTOMER;i++){//先初始化顾客集
customer=newCustomer();
customerSet.push_back(customer);
}
TiXmlDocumentdoc(FILENAME);//读入XML文件
if(!doc.LoadFile())return-1;//如果无法读取文件,则返回
TiXmlHandlehDoc(&doc);//hDoc是&doc指向的对象
TiXmlElement*pElem;//指向元素的指针
pElem=hDoc.FirstChildElement().Element();//指向根节点
TiXmlHandlehRoot(pElem);//hRoot是根节点
//读取x,y,它们放在network->nodes->node节点中
TiXmlElement*nodeElem=hRoot.FirstChild("network").FirstChild("nodes").FirstChild("node").Element();//当前指向了node节点
count=0;//记录移动到了哪个node节点,并且把该node节点的信息录入到顺序对应的customer中
for(nodeElem;nodeElem;nodeElem=nodeElem->NextSiblingElement()){//挨个读取node节点的信息
customer=customerSet[count];//当前顾客节点,注意不能赋值给一个新的对象,否则会调用复制构造函数
TiXmlHandlenode(nodeElem);//nodeElem所指向的节点
TiXmlElement*xElem=node.FirstChild("cx").Element();//cx节点
TiXmlElement*yElem=node.FirstChild("cy").Element();//cy节点
nodeElem->QueryIntAttribute("id",&temp1);//把id放到temp1中,属性值读法
customer->setId(temp1);
temp2=atof(xElem->GetText());//char转float
customer->setX(temp2);
temp2=atof(yElem->GetText());
customer->setY(temp2);
count++;
}
//读取其余信息
TiXmlElement*requestElem=hRoot.FirstChild("requests").FirstChild("request").Element();//指向了request节点
count=1;
for(requestElem;requestElem;requestElem=requestElem->NextSiblingElement()){
customer=customerSet[count];//当前顾客节点,注意不能赋值给一个新的对象,否则会调用复制构造函数
TiXmlHandlerequest(requestElem);//指针指向的对象
TiXmlElement*startTimeElem=request.FirstChild("tw").FirstChild("start").Element();//starttime
TiXmlElement*endTimeElem=request.FirstChild("tw").FirstChild("end").Element();//endtime
TiXmlElement*quantityElem=request.FirstChild("quantity").Element();//quantity
TiXmlElement*serviceTimeElem=request.FirstChild("service_time").Element();//servicetime
//分别读取各项数据
temp2=atof(startTimeElem->GetText());
customer->setStartTime(temp2);
temp2=atof(endTimeElem->GetText());
customer->setEndTime(temp2);
temp2=atof(quantityElem->GetText());
customer->setQuantity(temp2);
temp2=atof(serviceTimeElem->GetText());
customer->setServiceTime(temp2);
count++;
}
//将读取到的信息输出到控制台
cout<<setiosflags(ios_base::left)<<setw(6)<<"id"<<setw(6)<<"x"<<setw(6)<<
"y"<<setw(12)<<"startTime"<<setw(12)<<"endTime"<<setw(12)<<"quantity"<<setw(14)<<"serviceTime"<<endl;
for(i=0;i<NUM_OF_CUSTOMER;i++){
customer=customerSet[i];
customer->show();
}
system("pause");
return0;
}