前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >tinyxml2使用方法

tinyxml2使用方法

作者头像
全栈程序员站长
发布2022-06-28 14:09:30
1.4K0
发布2022-06-28 14:09:30
举报
文章被收录于专栏:全栈程序员必看

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

最近项目中使用到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使用方法
tinyxml2使用方法

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

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

代码语言:javascript
复制
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");
}

生成的文件:

代码语言:javascript
复制
<?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文件

代码语言:javascript
复制
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的支持。

代码语言:javascript
复制
#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.cn/132973.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年6月9,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档