像使用数据库一样使用xml

xml简介

XML 没什么特别的。它仅仅是纯文本而已。有能力处理纯文本的软件都可以处理 XML。因此其应用范围非常广。不过,能够读懂 XML 的应用程序可以有针对性地处理 XML 的标签。标签的功能性意义依赖于应用程序的特性。##优点XML 简化数据共享在真实的世界中,计算机系统和数据使用不兼容的格式来存储数据。XML 数据以纯文本格式进行存储,因此提供了一种独立于软件和硬件的数据存储方法。这让创建不同应用程序可以共享的数据变得更加容易。XML 简化数据传输通过 XML,可以在不兼容的系统之间轻松地交换数据。对开发人员来说,其中一项最费时的挑战一直是在因特网上的不兼容系统之间交换数据。由于可以通过各种不兼容的应用程序来读取数据,以 XML 交换数据降低了这种复杂性。XML 简化平台的变更升级到新的系统(硬件或软件平台),总是非常费时的。必须转换大量的数据,不兼容的数据经常会丢失。XML 数据以文本格式存储。这使得 XML 在不损失数据的情况下,更容易扩展或升级到新的操作系统、新应用程序或新的浏览器。XML 使您的数据更有用由于 XML 独立于硬件、软件以及应用程序,XML 使您的数据更可用,也更有用。不同的应用程序都能够访问您的数据。

语言结构

通俗的说来,可以将xml的数据看成是一个树状的结构,而树叉上又分布有各种元素,以及其属性值,对于简单应用来说,xml具有一个根节点,根节点下还具有很多级别的节点,我们可以在用节点来存储信息,下面的节点分为节点名称和节点内容以及节点属性等,以下图为例:

根节点为“ModelData”,其下包括子节点“SHPAPE”,其节点下还具有“X”、“Y”、“Z”、“R”的节点,而节点还具有内容,分别为100,50,30,10,“SHPAPE”节点还具有属性值,其“TYPE”属性为“SPHERE”,而“SHPAPE” 的节点值为001;
单单对于这些数据的应用可能一时理不清头绪,下面将使用tinyxml对xml的读写按照数据库的操作来进行使用,就简单的多了。

tinyxml

下载tinyxml

在github上搜索tinyxml,找到相应的版本的库进行下载,这里给出一个网址:https://github.com/leethomason/tinyxml2.git
编程用到的文件为<tinystr.h><tinyxml.h><tinystr.cpp><tinyxml.cpp><tinyxmlerror.cpp><tinyxmlparser.cpp>将这些文件拷贝到自己的工程目录下。

应用实例

(1)在MFC环境下进行测试,首先将上述文件的头文件引用
(2)创建xml文件

// 创建xml文档
	TiXmlDocument *pDoc = new TiXmlDocument();  
	TiXmlDeclaration *pDeclaration = new TiXmlDeclaration( "1.0", "UTF-8", "yes" );
	pDoc->LinkEndChild(pDeclaration);


	TiXmlElement *pRootNodeA = new TiXmlElement("ModelData");
	pDoc->LinkEndChild(pRootNodeA);
	//根节点
	TiXmlElement *pRootNode = new TiXmlElement("SHPAPE");
	pRootNodeA->LinkEndChild(pRootNode);
	//设置节点的属性
	pRootNode->SetAttribute("TYPE","SPHERE");

	//子节点NodeX
	TiXmlElement *NodeX = new TiXmlElement("X");
    pRootNode->LinkEndChild(NodeX);
	//子节点NodeY
	TiXmlElement *NodeY = new TiXmlElement("Y");
	pRootNode->LinkEndChild(NodeY);
	//子节点NodeZ
	TiXmlElement *NodeZ = new TiXmlElement("Z");
	pRootNode->LinkEndChild(NodeZ);
	//子节点NodeR
	TiXmlElement *NodeR = new TiXmlElement("R");
	pRootNode->LinkEndChild(NodeR);
	
	
	//设置节点的值
	TiXmlText *valueT = new TiXmlText("001");
	pRootNode->LinkEndChild(valueT);
	
	//给节点赋值
	TiXmlText *valueX= new TiXmlText("100");
	NodeX->LinkEndChild(valueX);
	TiXmlText *valueY= new TiXmlText("50");
	NodeY->LinkEndChild(valueY);
	TiXmlText *valueZ= new TiXmlText("30");
	NodeZ->LinkEndChild(valueZ);
	TiXmlText *valueR= new TiXmlText("10");
	NodeR->LinkEndChild(valueR);
	pDoc->SaveFile( "C:\Users\Desktop\DesktopChildStation.xml" );  

	//delete valueT;
	delete valueR;
	delete valueX;
	delete valueY;
	delete valueZ;
	AfxMessageBox(_T("创建成功"));

(2)添加到xml文件

//打开xml文档
	TiXmlDocument *pDoc = new TiXmlDocument("C:\Users\Desktop\DesktopChildStation.xml" );  
	pDoc->LoadFile();

	//获取根节点
	TiXmlElement *pRootNodeA = pDoc->RootElement();
	//根节点
	TiXmlElement *pRootNode = new TiXmlElement("SHPAPE");
	pRootNodeA->LinkEndChild(pRootNode);
	//设置节点的属性
	pRootNode->SetAttribute("TYPE","SPHERE");
	//直接在根节点下插入数据
	//子节点NodeX
	TiXmlElement *NodeX = new TiXmlElement("X");
	pRootNode->LinkEndChild(NodeX);
	//子节点NodeY
	TiXmlElement *NodeY = new TiXmlElement("Y");
	pRootNode->LinkEndChild(NodeY);
	//子节点NodeZ
	TiXmlElement *NodeZ = new TiXmlElement("Z");
	pRootNode->LinkEndChild(NodeZ);
	//子节点NodeR
	TiXmlElement *NodeR = new TiXmlElement("R");
	pRootNode->LinkEndChild(NodeR);
	//给节点赋值
	TiXmlText *valueX= new TiXmlText("5");
	NodeX->LinkEndChild(valueX);
	TiXmlText *valueY= new TiXmlText("7");
	NodeY->LinkEndChild(valueY);
	TiXmlText *valueZ= new TiXmlText("9");
	NodeZ->LinkEndChild(valueZ);
	TiXmlText *valueR= new TiXmlText("11");
	NodeR->LinkEndChild(valueR);

	pDoc->SaveFile( "C:\Users\Desktop\DesktopChildStation.xml" );  

	delete valueR;
	delete valueX;
	delete valueY;
	delete valueZ;
	AfxMessageBox(_T("增加成功"));

(3)修改xml中的值

TiXmlDocument *pDoc = new TiXmlDocument("C:\Users\Desktop\DesktopChildStation.xml" );  
	pDoc->LoadFile();

	TiXmlElement *pRootNodeA = pDoc->RootElement();
	for (TiXmlElement *SphereNode = pRootNodeA->FirstChildElement();SphereNode != NULL;SphereNode = SphereNode->NextSiblingElement())
	{
		

		//遍历子节点
		for(TiXmlElement *sonElement=SphereNode->FirstChildElement(); sonElement !=NULL;sonElement=sonElement->NextSiblingElement())  
		{  
			//全部修改为0
			sonElement->Clear();
			TiXmlText *pValue = new TiXmlText("0");
			sonElement->LinkEndChild(pValue);
			
		}  
	}
	pDoc->SaveFile("C:\Users\Desktop\DesktopChildStation.xml");
	AfxMessageBox(_T("修改成功"));

(4)读取xml中的值

//打开xml文档
	TiXmlDocument *pDoc = new TiXmlDocument("C:\Users\Desktop\DesktopChildStation.xml" );  
	pDoc->LoadFile();

	TiXmlElement *pRootNodeA = pDoc->RootElement();
	CString rootname;
	rootname =	pRootNodeA->Value();//
	AfxMessageBox(rootname);

	TiXmlElement *SphereNode = pRootNodeA->FirstChildElement();
	rootname = SphereNode->Value();
	pRootNodeA->Type();
	AfxMessageBox(rootname);

	rootname = SphereNode->LastChild()->Value();
	AfxMessageBox(rootname);

可以看出,直接使用tinyxml来对xml进行操作是十分繁琐的事情,故可以将其进行进一步的封装,生成符合自己使用习惯的方法。

tinyxml的封装

主要涉及到两个文件,这里直接给出源码

封装源码

(1)xmlOperat.h

#pragma once
#include "afxcmn.h"
#include "stdafx.h"
#include "tinyxml.h"
#include "tinystr.h"
using namespace std;
                                  
class xml_user 
{
public:
	bool Connect(CString InPath);
	TiXmlElement* GetRoot();
	CString GetLabelName(TiXmlElement* Label);
	CString GetLabelData(TiXmlElement* Label);
	TiXmlElement* GetLabelByName(TiXmlElement* root,CString Name);
	CString GetNodeData(TiXmlElement* root,CString Labelname,CString node);
	bool GetLabelExist(TiXmlElement* root,CString LabelName);
	void AddLabel(TiXmlElement *parent,CString Labelname,CString LabelData);
	void ModifyLabelData(TiXmlElement *parent,CString Labelname,CString LabelData);
	void SetAttr(TiXmlElement *Label,CString Attr,CString AttrData);
	CString GetAttr(TiXmlElement *Label,CString mType);
	TiXmlElement* GetNodeByAttr(TiXmlElement *Root,CString Attr,CString AttrData);
	CString* GetChildList(TiXmlElement * parent);
	CString Path;
	TiXmlDocument *pDoc;
	void xml_user::Save();
	CString GetAttr(TiXmlElement *parent,CString Label,CString mType);
};

(2)xmlOperate.cpp

#include "stdafx.h"
#include "windows.h"
#include <iostream>
#include <afxwin.h>
//#include "UseAdo.h"
#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#endif
#include <string.h>
#include <stdio.h>
#include "xmlOperate.h"
#include "tinyxml.h"
#include "tinystr.h"

using namespace std;



bool xml_user::Connect(CString InPath)
{
	CFileFind finder;
	bool bResult = finder.FindFile(InPath);
	if (bResult == 1)
	{	//打开xml文档
		string xmlpath = CW2A(InPath.GetString());
		pDoc = new TiXmlDocument(xmlpath.data() );  
		pDoc->LoadFile();
		//获取根节点
		TiXmlElement *pRoot = pDoc->RootElement();
		if (pRoot == NULL)
		{
			AfxMessageBox(_T("xml连接失败"));
			return FALSE;
		}
		Path = InPath;
		return TRUE;
	}
	else
	{
		AfxMessageBox(_T("该文件不存在"));
		return FALSE;
	}
}

void xml_user::Save()
{
	string xmlpath =CW2A(Path.GetString());
	pDoc->SaveFile(xmlpath.data());
}

//获取根节点
TiXmlElement* xml_user::GetRoot()
{
	CFileFind finder;
	bool bResult = finder.FindFile(Path);
	if (bResult == 1)
	{	//打开xml文档
		string xmlpath = CW2A(Path.GetString());
		pDoc = new TiXmlDocument(xmlpath.data() );  
		pDoc->LoadFile();

		//获取根节点
		TiXmlElement *pRoot = pDoc->RootElement();
		return pRoot;
	}
	else
	{
		AfxMessageBox(_T("该文件不存在"));
		return NULL;
	}

}

//获取标签的名字
CString xml_user::GetLabelName(TiXmlElement* Label)
{
	char temp[100];
	sprintf(temp,"%s",Label->Value());
	CString LabelName(temp);
	return LabelName;
}

//获取标签的数值
CString xml_user::GetLabelData(TiXmlElement* Label)
{
	char temp[255];
	sprintf(temp,"%s",Label->GetText());
	CString LabelName(temp);
	return LabelName;
}

//查找标签下的节点的值
CString xml_user::GetNodeData(TiXmlElement* root,CString Labelname,CString node)
{

	TiXmlElement *Label = GetLabelByName(root,Labelname);
	if (Label == NULL)
	{
		return NULL;
	}

	TiXmlElement *hChild = Label->FirstChildElement();
	while(hChild != NULL)
	{
		if (node.Compare(GetLabelName(hChild)) == 0)
		{
			return GetLabelData(hChild);
		}
		hChild = hChild->NextSiblingElement();
	}
	//AfxMessageBox(_T("为找到相应的定义"));
	return NULL;
}

//通过标签的内容来查找
TiXmlElement* xml_user::GetLabelByName(TiXmlElement* root,CString Name)
{
	TiXmlElement *Level_1 = root->FirstChildElement();
	while(Level_1 != NULL)
	{
		if (Name.Compare(GetLabelName(Level_1)) == 0)
		{
			return Level_1;
		}
		else
		{
			//return GetLabelByName(Level_1,Name);
			TiXmlElement *Level_2 = GetLabelByName(Level_1,Name);
			if (Level_2 != NULL)
			{
				return Level_2;
			}
			else
				Level_1 = Level_1->NextSiblingElement();
		}
		//Level_1 = Level_1->NextSiblingElement();
	}
	return NULL;
	
}

//判断标签是否存在
bool xml_user::GetLabelExist(TiXmlElement *root,CString LabelName)
{
	if (GetLabelByName(root,LabelName) == NULL)
	{
		return FALSE;
	}
	else
		return TRUE;
}

//添加节点
void xml_user::AddLabel(TiXmlElement *parent,CString Labelname,CString LabelData)
{
	if (LabelData.GetLength() > 0)
	{
		string lablename = CW2A(Labelname.GetString());
		TiXmlElement *pChild = new TiXmlElement(lablename.data());parent->LinkEndChild(pChild);
		string labeldata = CW2A(LabelData.GetString());
		TiXmlText *Value= new TiXmlText(labeldata.data());pChild->LinkEndChild(Value);
	}
	else
	{
		string lablename = CW2A(Labelname.GetString());
		TiXmlElement *pChild = new TiXmlElement(lablename.data());parent->LinkEndChild(pChild);
	}
	Save();
}

//修改节点的值,存在则修改,不存在就创建
void xml_user::ModifyLabelData(TiXmlElement *parent,CString Labelname,CString LabelData)
{
	if (GetLabelExist(parent,Labelname))//有的话进行修改
	{
		TiXmlElement* Label = GetLabelByName(parent,Labelname);
		Label->Clear();
		string temp =CW2A(LabelData.GetString());
		TiXmlText *pValue = new TiXmlText(temp.data());Label->LinkEndChild(pValue);;
	}
	else
	{
		AddLabel(parent,Labelname,LabelData);//没有的话进行创建
	}

	Save();
}

//设置属性
void xml_user::SetAttr(TiXmlElement *Label,CString Attr,CString AttrData)
{
	string attr = CW2A(Attr.GetString());
	string attrdata = CW2A(AttrData.GetString());
	Label->SetAttribute(attr.data(),attrdata.data());
	Save();
}

//获取属性
CString xml_user::GetAttr(TiXmlElement *Label,CString mType)
{
	string type = CW2A(mType.GetString());
	char tempAttr[100];
	sprintf(tempAttr,"%s",Label->Attribute(type.data()));

	CString Attribution(tempAttr);
	return Attribution;
}

//通过属性获得节点
TiXmlElement* xml_user::GetNodeByAttr(TiXmlElement *Root,CString Attr,CString AttrData)
{
	TiXmlElement *Level_1 = Root->FirstChildElement();
	while(Level_1 != NULL)
	{
		if (AttrData.Compare(GetAttr(Level_1,Attr)) == 0)
		{
			return Level_1;
		}
		else
		{
			TiXmlElement *Level_2 = GetNodeByAttr(Level_1,Attr,AttrData);
			if (Level_2 != NULL)
			{
				return Level_2;
			}

		}
		Level_1 = Level_1->NextSiblingElement();
	}
	return NULL;

}

CString*  xml_user::GetChildList(TiXmlElement * parent)
{
	TiXmlElement *Level_1 = parent->FirstChildElement();
	CString  ChildNameList[250];
	int i = 0;
	while(Level_1 != NULL)
	{
		//AfxMessageBox(GetLabelName(Level_1));
		ChildNameList[i] = GetLabelName(Level_1);
		i++;
		Level_1 = Level_1->NextSiblingElement();
	}
	return ChildNameList;
}

CString xml_user::GetAttr(TiXmlElement *parent,CString Label,CString mType)
{

	TiXmlElement *hChild = GetLabelByName(parent,Label);//
	CString name = GetAttr(hChild,mType);
	/*AfxMessageBox(name);

	CString temp = GetAttr(hChild,mType);*/
	return name;
}

实际应用

        xml_user p_Record;
	p_Record.Connect(xmlpath);
	TiXmlElement *Root = p_Record.GetRoot();
	CString temp = p_Record.GetNodeData(Root,_T("SPAPE"),_T("X"));//获取x的值
原文地址:https://www.cnblogs.com/gaozihan/p/10149623.html