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给出的解决方案。

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • JSONArray转换成List<T>

    JSONArray转换成List<T>常用的方法:1.首先有一个JSONArray对象,比如是jsonArrayJSONObjectjsonObject1=newJSONObject();JSONObject1.put(“username”,”zhangsan”);JSONObjectjsonObject2=newJSONObject();JSONObject2.put(“username”,”lisi”);JSONArrayjsonArray=newJSONArray();jsonArray.add(j

    2022年6月23日
    45
  • C语言的字符串分割

    说起来很有意思,自认为对C语言理解得还是比较深刻的。但居然到今天才知道有个strtok函数,试用了一下突然感慨以前做了多少重复劳动。每次需要解析配置文件,每次需要分割字符串,居然都是自己去分割字符串,

    2021年12月24日
    38
  • 最详细的解决:UnboundLocalError: local variable ‘a‘ referenced before assignment

    最详细的解决:UnboundLocalError: local variable ‘a‘ referenced before assignment代码及报错如下解决很多人都非常困惑,为什么在test3中可以直接输出a,但是在test3中,使用a+=1的时候,就直接报错呢?首先,我们需要明确一个概念,就是全局变量与局部变量。如下图,大家觉得打印的a会是1还是3?答案是1,因为定义在test3外部的a是全局变量,而定义在test3内部的a是局部变量。此时,外面这个a与里面这个a没有任何关系。只不过是名字一样而已。其次,我们需要明确在函数内部是可以直接访问到全局变量的,所以上图中test1是可以直接输出a,b的。但是如果是直接在test2中实

    2022年6月16日
    40
  • datetime.date()_datenum函数使用

    datetime.date()_datenum函数使用比如在windowscmd命令行窗口执行date命令后这个环境变量的值为当前日期:2014-03-01 星期六那么如下的各个操作的意义如下:%date:~0,4% 表示从左向右指针向右偏0位,然后从指针偏移到的位置开始提取4位字符,结果是2014(年的值)%date:~5,2% 表示指针从左向右偏移5位,然后从偏移处开始提取2位字符,结果是03(月的值)%date:~8,

    2022年9月20日
    0
  • 三菱PLC学习方法分享

    三菱PLC学习方法分享  学习plc不是为了研究,而是为了工作需要和应用。下面是我学习PLC的方法,供大家参考!  与PLC自动化相关的知识点很多,比如PLC控制、模拟控制、定位、通信、配置、嵌入式系统、变频器、机械传动、液压系统(不知道是不是自动化)等。知识点太多。以常见的PLC为例,三菱、西门子、欧姆龙、松下、LG、达美、卡恩斯等品牌,加上各种国产品牌和众多知识点。如何学好它们?我理解的学习方法是“巧学”。  以我熟悉的三菱plc为例:  一、基础:一定要打好基础——基础是什么?  1.安装编程软件。  

    2022年10月9日
    0
  • vi编辑时出现E325:ATTENTION「建议收藏」

    vi编辑时出现E325:ATTENTION「建议收藏」报错信息:vi编辑时出现E325:ATTENTION描述:这是由于在编辑该文件的时候异常退出了,因为vim在编辑文件时会创建一个交换文件swapfile以保证文件的安全性。解决办法:为了去掉这个警告,我们需要删除这个swp文件:rm-f.config.swp

    2022年5月19日
    48

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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