通过项目的开发,我发现xml的读写主要是分为以下几种类型:
一种类型是:
<?xml version="1.0" encoding="UTF-8"?>
<POIS>
<POI LightMode="head_light" ShowUnderground="true" name="位置1 经度:89.9998 纬度:0"/>
</POIS>
这种情况是只有一个根节点,下来就是相同的子节点;对于这种情况,xml的读写是下面这样子的:
//xml文件在电脑中放置的路径
QString xmlPath = FileUtils::getInstance()->getConfigPath("./xmls/PoiPoints.xml");
//根节点的加载
QDomDocument dom;
//加载xml文件
QFile xmlFile(xmlPath);
//判断xml是否打开
if (!xmlFile.open(QIODevice::ReadOnly))
{
LOG_FAILD(L"open file initiative poi failed.");
xmlFile.close();
return;
}
//判断xml设置文件名
if (!dom.setContent(&xmlFile))
{
LOG_FAILD(L"read initiative poi as xml content failed.");
xmlFile.close();
return;
}
//xml文件的关闭,这步必须得有,如果没有,读取xml是不起作用的
xmlFile.close();
//读取xml的根节点(相对于本实例就是POIS)
QDomElement root=dom.documentElement();
//读取根节点的子节点(相对于本实例就是POI)
QDomElement element =root.firstChildElement();
QString name, lightMode, showUnderground;
bool bShowUnderground = false;
POIType* poiType;
//循环读取根节点的子节点
while (true)
{
//这步是必须的
if (element.isNull()) break;
//通过子节点的名字来判断子节点里面的元素
if (element.tagName().compare("POI", Qt::CaseInsensitive) == 0)
{
name = element.attribute("name");
lightMode = element.attribute("LightMode");
showUnderground = element.attribute("ShowUnderground", "false");
bShowUnderground = showUnderground.compare("true", Qt::CaseInsensitive) == 0;
poiType = new POIType(name, lightMode, bShowUnderground);
}
//hashPOI是一个哈希表
hashPOI.insert(name, poiType);
//进行下一个子节点,这步也是必须的
element = element.nextSiblingElement();
}
一种类型是:
<?xml version="1.0" encoding="utf-8"?>
<DataModel>
<ObjectType Name="GDJT_SB" Header="设备" Caption="设备" Table="GDJT_SB" Icon="Ventilator" InfoLogoIcon="INFO_SB">
<Field Name="ID" Header="标识" Caption ="" Column="" DataType="" SystemType="Id" PresentType="VisibleInDetail" OrderByType="Asc1" Editor="IDEditor" EditorParams=""/>
<Field Name="ID_3D" Header="场景ID" Caption ="" Column="" DataType="" SystemType="ID_3D" PresentType="VisibleInDetail"/>
</ObjectType>
<ObjectType Name="GDJT_WXJL" Header="维修记录" Caption="" Table="GDJT_WXJL" Icon="Clear" InfoLogoIcon="">
<Field Name="ID" Header="标识" Caption ="" Column="" DataType="" SystemType="Id" PresentType="VisibleInDetail" OrderByType="Asc1" Editor="IDEditor" EditorParams=""/>
<Field Name="BH" Header="编号" Caption ="" Column="" DataType="" SystemType="Name" PresentType=""/>
</ObjectType>
</DataModel>
这种情况是有一个根节点,有几个并列的根节点下面的子节点,还有几个根节点下面子节点的子节点,对于这种xml的读取,读取的方法是:
//获取xml所在的文件夹的路径
QString xmlDir = FileUtils::getInstance()->getConfigPath("Xmls/TypedMetaDatas");
//读取xml所在的文件夹
QDir dir(xmlDir);
//获取xml所在的路径
QString xmlFilePath = xmlDir + QDir::separator() + xmlFilePath;
//获取xml文件
QDomDocument dom;
//加载xml的文件路径
QFile xmlFile(xmlPath);
//判断xml是否打开
if (!xmlFile.open(QIODevice::ReadOnly))
{
xmlFile.close();
return;
}
//判断xml的目录
if (!dom.setContent(&xmlFile)) return;
//xml文件的关闭,这步必须得有,如果没有,读取xml是不起作用的
xmlFile.close();
//读取xml的根节点(相对于本实例就是DataModel)
QDomElement root=dom.documentElement();
//读取根节点的子节点(相对于本实例就是ObjectType)
QDomElement objectTypeElement =root.firstChildElement();
QString name, header, caption, table, icon, logoIcon, column, dataType, systemType, presentType,preferWidth, orderByType,editor,editorParams,classifyType,defaultClassify;
//循环读取根节点的子节点
while (true)
{
//这步是必须的
if (objectTypeElement.isNull()) break;
//获取objectType节点中的name属性
name = objectTypeElement.attribute("Name");
if (!name.isEmpty())
{
header = objectTypeElement.attribute("Header", name);
caption = objectTypeElement.attribute("Caption", header);
table = objectTypeElement.attribute("Table",name);
if (table.isNull() || table.isEmpty())
{
table = name;
}
icon = objectTypeElement.attribute("Icon");
logoIcon = objectTypeElement.attribute("InfoLogoIcon");
//获取objectType下面的子节点(本实例中就是Field)
QDomElement fieldElement = objectTypeElement.firstChildElement();
while (true)
{
if (fieldElement.isNull()) break;
if (fieldElement.tagName() == "Field")
{
name = fieldElement.attribute("Name");
header = fieldElement.attribute("Header", name);
caption = fieldElement.attribute("Caption", header);
column = fieldElement.attribute("Column", name);
dataType = fieldElement.attribute("DataType", "String");
systemType = fieldElement.attribute("SystemType", "Custom");
presentType = fieldElement.attribute("PresentType", "VisibleInDetail | EditNone");
preferWidth = fieldElement.attribute("PreferWidth");
orderByType = fieldElement.attribute("OrderByType", "None");
editor = fieldElement.attribute("Editor");
editorParams = fieldElement.attribute("EditorParams");
classifyType = fieldElement.attribute("ClassifyType");
defaultClassify = fieldElement.attribute("DefaultClassify");
}
fieldElement = fieldElement.nextSiblingElement();
}
}
objectTypeElement = objectTypeElement.nextSiblingElement();
}
********************************************************************************
xml的写入,也可以分为几种情况:
一种情况:
<?xml version="1.0" encoding="UTF-8"?>
<POIS>
<POI LightMode="head_light" ShowUnderground="true" name="位置1 经度:89.9998 纬度:0"/>
</POIS>
这是一个根节点,一个子节点,这种xml的写入的写法为:
QString xmlPath = FileUtils::getInstance()->getConfigPath("./xmls/PoiPoints.xml");
QDomDocument dom;
QFile xmlFile(xmlPath);
if (!xmlFile.open(QIODevice::ReadOnly))
{
LOG_FAILD(L"open file initiative nav failed.");
xmlFile.close();
return;
}
if (!dom.setContent(&xmlFile))
{
LOG_FAILD(L"read initiative nav as xml content failed.");
xmlFile.close();
return;
}
xmlFile.close();
QDomProcessingInstruction instruction = doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
dom.appendChild(instruction);
QDomElement root = dom.createElement("POIS");
dom.appendChild(root);
QDomElment node=root.createElement("POI");
root.appendChild(node);
root.setAttribute("name", "位置1 经度:89.9998 纬度:0");
root.setAttribute("LightMode", lightMode);
root.setAttribute("ShowUnderground", ShowUnderground);
QFile file("PoiPoints.xml");
//以下几步很重要,在写入之后一定要保存,不然xml的写入不起作用
if (!filexml.open(QFile::WriteOnly | QFile::Truncate)) return;
QTextStream ts(&filexml);
ts.reset();
ts.setCodec("utf-8");
dom.save(ts, 4, QDomNode::EncodingFromTextStream);
filexml.close();
一种情况是:
<?xml version="1.0" encoding="UTF-8"?>
<POIS>
<POI>
<ShowUnderground>"true"</ShowUnderground>
<LightMode>"head_light"</LightMode>
<name>"位置1 经度:89.9998 纬度:0"</name>
</POI>
</POIS>
这是一个根节点,一个根节点下面有一个子节点,一个子节点下面有很多子节点:
QString xmlPath = FileUtils::getInstance()->getConfigPath("./xmls/PoiPoints.xml");
QDomDocument dom;
QFile xmlFile(xmlPath);
if (!xmlFile.open(QIODevice::ReadOnly))
{
LOG_FAILD(L"open file initiative nav failed.");
xmlFile.close();
return;
}
if (!dom.setContent(&xmlFile))
{
LOG_FAILD(L"read initiative nav as xml content failed.");
xmlFile.close();
return;
}
xmlFile.close();
QDomProcessingInstruction instruction = doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
dom.appendChild(instruction);
QDomElement root = dom.createElement("POIS");
dom.appendChild(root);
QDomElment node=root.createElement("POI");
root.appendChild(node);
QDomElement nameNode=dom.createElement("name");
node.appendChild(nameNode);
QDomText nameText=dom.createTextNode("位置1 经度:89.9998 纬度:0");
QFile file("PoiPoints.xml");
//以下几步很重要,在写入之后一定要保存,不然xml的写入不起作用
if (!filexml.open(QFile::WriteOnly | QFile::Truncate)) return;
QTextStream ts(&filexml);
ts.reset();
ts.setCodec("utf-8");
dom.save(ts, 4, QDomNode::EncodingFromTextStream);
filexml.close();