tinyxml2使用方法

tinyxml2使用方法最近项目中使用到xml,最终选用了tinyxml2,学习后写个使用总结。

大家好,又见面了,我是你们的朋友全栈君。

最近项目中使用到xml,最终选用了tinyxml2,学习后写个总结。

TinyXml2 主要类型:

XMLNode: XMLNode is a base class for every object that is in the XMLDocument Object Model (DOM), except XMLAttributes.Nodes have siblings, aparent, and children which can be navigated. A node is always in a XMLDocument.The type of a XMLNode can be queried, and it can be cast to its more definedtype.

XMLDocument: A Document binds together all the functionality.It can be saved,loaded, and printed to the screen.All Nodes are connected and allocated to aDocument.If the Document is deleted, all its Nodes are also deleted.

A XMLDocumentallocates memory for all its Nodes.When the XMLDocument gets deleted, all itsNodes will also be deleted.

A Document cancontain:         Element   (container or leaf)

                                                                 Comment(leaf)

                                                                 Unknown(leaf)

                                                                 Declaration(leaf )

XMLDeclaration: In correct XML the declaration is the first entry in the file.

                   <?xmlversion=”1.0″ standalone=”yes”?>

         TinyXML-2will happily read or write files without a declaration,however.    The text of the declaration isn’tinterpreted. It is parsed and written as a string.

XMLComment: 对应于XML文档中的注释部分的对象。

XMLElement: The element is a container class. It has a value, the elementname,and can contain other elements, text, comments, and unknowns.Elements alsocontain an arbitrary number of attributes.

XMLText:         Note that a text nodecan have child element nodes, for example:

         <root>Thisis <b>bold</b></root>

         Atext node can have 2 ways to output the next. “normal” output

         andCDATA. It will default to the mode it was parsed from the XML file and

         yougenerally want to leave it alone, but you can change the output mode with

         SetCData()and query it with CData().

XMLAttribute: An attribute is a name-value pair. Elements have an arbitrary

         numberof attributes, each with a unique name.

         @noteThe attributes are not XMLNodes. You may only query theNext() attribute in alist.

XMLUnknown:  Any tag that TinyXML-2doesn’t recognize is saved as an unknown. It is a tag of text, but should notbe modified.It will be written back to the XML, unchanged, when the file issaved.DTD tags get thrown into XMLUnknowns.

从上面的介绍可知,除了XMLAttribute以外,其他的都继承自XMLNode

tinyxml2把xml文档建立成一棵DOM树,具体实现用的是firstchild–nextsiblingtree,下图是对该树的模型的一个简单介绍:

tinyxml2使用方法

firstchild-nextsibling是一种多叉树常用的实现方法,每个结点只需要知道它的第一个孩子结点(first child node)和它的下一个兄弟结点(next sibling node),这样一整棵树的结构就会建立起来,也可以用根结点的指针为起点来对整棵树进行遍历。

写xml文件,有些意外的XMLText应该可以插入子节点,但是最后生成的文件并没有子节点。

static void Write()
{
	XMLDocument Doc;
	XMLDeclaration* pDecaration=Doc.NewDeclaration("This is a Declaration!");
	Doc.LinkEndChild(pDecaration);
	XMLComment* pComment = Doc.NewComment("This is a Document Comment!");
	Doc.LinkEndChild(pComment);
	XMLElement* pElementRoot = Doc.NewElement("School");
	Doc.LinkEndChild(pElementRoot);
	XMLComment* pCommentRoot = Doc.NewComment("This is a School Comment!");
	pElementRoot->LinkEndChild(pCommentRoot);
	{
		XMLElement* pElementTeachers = Doc.NewElement("teachers");
		pElementRoot->LinkEndChild(pElementTeachers);
		pElementTeachers->LinkEndChild(Doc.NewElement("Wang"));
		pElementTeachers->LinkEndChild(Doc.NewElement("Li"));
		pElementTeachers->LinkEndChild(Doc.NewElement("Zhao"));
	}
	XMLElement* pElementStudents = Doc.NewElement("students");
	pElementRoot->LinkEndChild(pElementStudents);
	{
		XMLElement* pElementLiMing = Doc.NewElement("LiMing");
		pElementLiMing->SetText("Li Ming is a good Student!");
		pElementLiMing->SetAttribute("sex", "male");
		pElementLiMing->SetAttribute("height", 174);
		pElementLiMing->SetAttribute("weight", 80.4);
		pElementLiMing->SetAttribute("Is_good_at_math", false);
		pElementStudents->LinkEndChild(pElementLiMing);
	}
	{
		XMLElement* pElementCuiHua = Doc.NewElement("CuiHua");
		XMLElement* pElementSex = Doc.NewElement("sex");
		pElementSex->SetText("female");
		XMLText* pText = Doc.NewText("this is a Text!");
		pText->LinkEndChild(pElementSex);
		pElementCuiHua->LinkEndChild(pText);
		pElementStudents->LinkEndChild(pElementCuiHua);
	}
	{
		XMLElement* pElementHanmeimei = Doc.NewElement("Hanmeimei");
		pElementStudents->LinkEndChild(pElementHanmeimei);
		XMLText* pTextCData = Doc.NewText("this is a CData Text:if (a < b && a < 0)");
		pTextCData->SetCData(true);
		pElementHanmeimei->LinkEndChild(pTextCData);
	}

	XMLUnknown* pUnknow = Doc.NewUnknown("this is a Unknow!");
	pElementRoot->LinkEndChild(pUnknow);
	Doc.SaveFile("test.xml");
}

生成的文件:

<?This is a Declaration!?>
<!--This is a Document Comment!-->
<School>
    <!--This is a School Comment!-->
    <teachers>
        <Wang/>
        <Li/>
        <Zhao/>
    </teachers>
    <students>
        <LiMing sex="male" height="174" weight="80.400000000000006" Is_good_at_math="false">Li Ming is a good Student!</LiMing>
        <CuiHua>this is a Text!</CuiHua>
        <Hanmeimei><![CDATA[this is a CData Text:if (a < b && a < 0)]]></Hanmeimei>
    </students>
    <!this is a Unknow!>
</School>

读xml文件

static void Read()
{
	XMLDocument Doc;
	Doc.LoadFile("test.xml");
	XMLElement* pElementRoot = Doc.RootElement();
	{
		XMLElement* pElementTeachers = pElementRoot->FirstChildElement("teachers");
		pElementTeachers->FirstChildElement("Wang");
		pElementTeachers->FirstChildElement("Li");
		pElementTeachers->FirstChildElement("Zhao");
	}
	XMLElement* pElementStudents = pElementRoot->FirstChildElement("students"); 
	{
		XMLElement* pElementLiMing = pElementStudents->FirstChildElement("LiMing");
		const char* pText=pElementLiMing->GetText();
		const char* pSex=pElementLiMing->Attribute("sex");
		int iHeight=pElementLiMing->IntAttribute("height");
		double dbHeight=pElementLiMing->DoubleAttribute("weight");
		bool bIsGood=pElementLiMing->BoolAttribute("Is_good_at_math");
	}
	{
		XMLElement* pElementCuiHua = pElementStudents->FirstChildElement("CuiHua");
		XMLNode* pNode=pElementCuiHua->FirstChild();
		XMLText* pText = pNode->ToText();
		//XMLElement* pElementSex = pText->FirstChildElement("sex");
		//const char* pSex = pElementSex->GetText();
	}
	{
		XMLElement* pElementHanmeimei = pElementStudents->FirstChildElement("Hanmeimei");
		XMLText* pTextCData = pElementHanmeimei->FirstChild()->ToText();
		bool bCData=pTextCData->CData();
	}
}

最后说下中文的问题,由于tinyxml2使用utf8编码,如果输入中文,输出的是乱码,以下是解决方案,使用字符转换,需要c++11的支持。

#include <string>
#include <vector>
#include <codecvt>
#ifdef UNICODE
typedef wchar_t tchar;
#else
typedef char tchar;
#endif

typedef std::basic_string < tchar, std::char_traits<tchar>, std::allocator<tchar> > tstring;
std::string unicode_to_utf8(std::wstring const& strUnicode)
{
	std::wstring_convert<std::codecvt_utf8<wchar_t>> cutf8;
	return cutf8.to_bytes(strUnicode);
}
std::wstring utf8_to_unicode(std::string const& strutf8)
{
	std::wstring_convert<std::codecvt_utf8<wchar_t>> cutf8;
	return cutf8.from_bytes(strutf8);
}
std::wstring gb2312_to_unicode(std::string const &strGb2312)
{
	std::vector<wchar_t> buff(strGb2312.size());
#ifdef _MSC_VER
	std::locale loc("zh-CN");
#else
	std::locale loc("zh_CN.GB18030");
#endif
	wchar_t* pwszNext = nullptr;
	const char* pszNext = nullptr;
	mbstate_t state = {};
	int res = std::use_facet<std::codecvt<wchar_t, char, mbstate_t> >
		(loc).in(state,
		strGb2312.data(), strGb2312.data() + strGb2312.size(), pszNext,
		buff.data(), buff.data() + buff.size(), pwszNext);

	if (std::codecvt_base::ok == res)
	{
		return std::wstring(buff.data(), pwszNext);
	}
	return L"";
}

std::string unicode_to_gb2312(std::wstring const& strUnicode)
{
#ifdef _MSC_VER
	std::locale loc("zh-CN");
#else
	std::locale loc("zh_CN.GB18030");
#endif
	const wchar_t* pwszNext = nullptr;
	char* pszNext = nullptr;
	mbstate_t state = {};

	std::vector<char> buff(strUnicode.size() * 2);
	int res = std::use_facet<std::codecvt<wchar_t, char, mbstate_t> >
		(loc).out(state,
		strUnicode.data(), strUnicode.data() + strUnicode.size(), pwszNext,
		buff.data(), buff.data() + buff.size(), pszNext);

	if (std::codecvt_base::ok == res)
	{
		return std::string(buff.data(), pszNext);
	}
	return "";
}
inline std::string tstring_to_utf8(tstring const& strToConvert){
#ifdef UNICODE
	return unicode_to_utf8(strToConvert);
#else
	auto strUnicode=gb2312_to_unicode(strToConvert);
	return unicode_to_utf8(strUnicode);
#endif 
}
inline tstring utf8_to_tstring(std::string const& strToConvert){
#ifdef UNICODE
	return utf8_to_unicode(strToConvert);
#else
	auto strUnicode = utf8_to_unicode(strToConvert);
	return unicode_to_gb2312(strUnicode);
#endif 
}

这时候,我们可能需要对XMLElement,XMLDocument等做个wrapper,封装字符转换。感谢
ml232528给出的解决方案。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/132973.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 重建二叉树(Java)

    重建二叉树(Java)题目:输入一个链表的头结点,从尾到头反过来打印出每个结点的值。链表的结点定义如下:structListNode{ intm_nKey; ListNode*m_pNext;}第一思路:我的第一思路是从头到尾输出类比数组那样,于是乎想把链表中的链表结点的指针反转过来,改变链表的方向,然后实现从头到尾输出(结果为从尾到头输出),可是发现修改链表的指针,反转链表的结构比较麻烦。于是乎放弃。最优…

  • 数据结构–循环队列[通俗易懂]

    数据结构–循环队列[通俗易懂]文章目录顺序存储结构循环队列代码实现注意顺序存储结构所谓顺序存储结构就是用一组地址连续的存储单元依次存放从队头到队尾的元素。声明两个指针rear、front分别用来指示队尾元素的下一位置和队头元素的位置。初始化时rear=front=0,插入新的元素时尾指针加1,元素出队列时队头指针加1。不过这样做有个问题,不论是入队还是出队,队头或队尾指针都是加1,这样做有一个问题,就是元素…

  • 几种server模型

    几种server模型

  • Android开发中,怎样调用摄像机拍照以及怎样从本地图库中选取照片

    Android开发中,怎样调用摄像机拍照以及怎样从本地图库中选取照片这是属于我的第一篇博文,首先说明一下,文章属性为原创,其实不能说是原创,我是在学习的过程中根据自己的理解整理的。文章内容大多为书本上的内容,书本是郭霖的《第一行代码》。    正文:现在很多应用程序会调用摄像头的拍照功能,比如哪个程序要上传一张图片作为用户头像,这是启用摄像头拍照会很方便。当然,还有第二种方法,就是在本地图库选取已经被保存的图片。现在,我就根据自己学习的过程,将这部分

  • Java程序概述

    Java程序概述Java程序概述一、Java开发环境1、Java程序编译执行的过程2、Java平台概述3、JDK部分常用工具二、Application三、Applet四、Servlet五、JSP和JavaBean六、脚本一、Java开发环境1、Java程序编译执行的过程Java程序在编译执行过程中,首先把源文件(.java文件)编译成字节码文件,即类文件(.class);然后由解释器负责解释执行类文件。2、Java平台概述Java平台包括Java应用程序接口(API)和Java虚拟机(JavaVirtual

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号