1、基本介绍
TinyXML2是一个开源、简单、小巧、高效的C++ XML解析器,它只有一个.h文件和一个.cpp文件组成,可以轻松集成到其它程序中。非常方便我们使用c++对xml进行处理。
可以读取、修改和保存的文档对象模型(Document Object Model, DOM)。它不能解析DTD(Document Type Definitions, 文档类型定义)或XSL(eXtensible Stylesheet Language, 扩展样式表语言)。在TinyXML2中,XML数据被解析为可以浏览和操作的C++对象,然后写入磁盘和其它输出流。
2、本地编译
首先现在源码:tinyxml2 源码
解压目录:
编译静态库
直接在目录下执行cmake和make就可以编译生成。
编译动态库
如果需要编译动态库,则需要把makefile文件里面的libtinyxml2.a修改成libtinyxml2.so,再执行make指令。则编译libtinyxml2.so
3、tinyxml2 源码解析
我们在使用tinyxml2的时候都是声明使用tinyxml2的命名空间,其内部比较重要的几个类都是继承XMLNode的。
namespace tinyxml2
{
class XMLDocument;
class XMLElement;
class XMLAttribute;
class XMLComment;
class XMLText;
class XMLDeclaration;
class XMLUnknown;
class XMLPrinter;
}
3.1 XMLNode 基础父类
class TINYXML2_LIB XMLNode
{friend class XMLDocument;friend class XMLElement;
public:const XMLDocument* GetDocument();XMLDocument* GetDocument();//转换成特定的子类对象virtual XMLElement* ToElement();virtual XMLText* ToText();virtual XMLComment* ToComment();virtual XMLDocument* ToDocument();virtual XMLDeclaration* ToDeclaration();virtual XMLUnknown* ToUnknown();virtual const XMLElement* ToElement();virtual const XMLText* ToText();virtual const XMLComment* ToComment();virtual const XMLDocument* ToDocument();virtual const XMLDeclaration* ToDeclaration();virtual const XMLUnknown* ToUnknown() ;const char* Value() const;void SetValue( const char* val, bool staticMem=false );int GetLineNum() const { return _parseLineNum; }const XMLNode* Parent();XMLNode* Parent();bool NoChildren();const XMLNode* FirstChild();XMLNode* FirstChild();const XMLElement* FirstChildElement( const char* name = 0 ) const;XMLElement* FirstChildElement( const char* name = 0 );const XMLNode* LastChild();XMLNode* LastChild();const XMLElement* LastChildElement( const char* name = 0 ) const;XMLElement* LastChildElement( const char* name = 0 );const XMLNode* PreviousSibling();XMLNode* PreviousSibling();const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ;XMLElement* PreviousSiblingElement( const char* name = 0 );const XMLNode* NextSibling();XMLNode* NextSibling();const XMLElement* NextSiblingElement( const char* name = 0 ) const;XMLElement* NextSiblingElement( const char* name = 0 );XMLNode* InsertEndChild( XMLNode* addThis );XMLNode* LinkEndChild( XMLNode* addThis ) ;XMLNode* InsertFirstChild( XMLNode* addThis );XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );void DeleteChildren();void DeleteChild( XMLNode* node );virtual XMLNode* ShallowClone( XMLDocument* document );XMLNode* DeepClone( XMLDocument* target );virtual bool ShallowEqual( const XMLNode* compare );virtual bool Accept( XMLVisitor* visitor );void SetUserData(void* userData);void* GetUserData();//省略部分代码
};
3.2 XMLDocument 文档类
XMLDocument 是将所有功能绑定在一起,可以保存、加载和打印数据。所有的节点都是里连接到文档上面进行操作的,如果删除文档,则所有节点都会被删除。具体的接口解释如下:
class TINYXML2_LIB XMLDocument : public XMLNode
{//省略部分代码
public:virtual XMLDocument* ToDocument() virtual const XMLDocument* ToDocument()/*从字符串分析XML文件。成功时返回XML_SUCCESS0,或错误ID。*/XMLError Parse( const char* xml, size_t nBytes=static_cast<size_t>(-1) );/*载入xml文件*/XMLError LoadFile( const char* filename );/*载入xml文件*/XMLError LoadFile( FILE* );/*保存xml到文件*/XMLError SaveFile( const char* filename, bool compact = false );/*保存xml到文件*/XMLError SaveFile( FILE* fp, bool compact = false );/*如果此文档的前导字节顺序标记为UTF8,则返回true*/bool HasBOM();/*设置写入文件时是否写入BOM表。*/void SetBOM( bool useBOM );/*返回DOM的根元素。等效于FirstChildElement().要获取第一个节点,请使用FirstChild()*/XMLElement* RootElement();const XMLElement* RootElement();/*打印*/void Print( XMLPrinter* streamer=0 );virtual bool Accept( XMLVisitor* visitor );/*创建与本文档关联的新元素,内存由本文档管理。*/XMLElement* NewElement( const char* name );/*创建与本文档关联的新注释文本,内存由本文档管理。*/XMLComment* NewComment( const char* comment );/*创建与本文档关联的新文本,内存由本文档管理。*/XMLText* NewText( const char* text );/*创建与关联的新声明本文件。对象的内存由文档管理。*/XMLDeclaration* NewDeclaration( const char* text=0 );/*创建与关联的新未知本文件。对象的内存由文档管理。*/XMLUnknown* NewUnknown( const char* text );/*删除与此文档关联的节点。它将与DOM断开链接。*/void DeleteNode( XMLNode* node );//清除Error.void ClearError();//如果分析文档时出错,则返回true。bool Error() //错误IDXMLError ErrorID();//错误名字const char* ErrorName();static const char* ErrorIDToName(XMLError errorID);//返回“长格式”错误描述。A希望有帮助使用位置、行号和/或其他信息进行诊断。/const char* ErrorStr();//返回发生错误的行,如果未知,则返回零。int ErrorLineNum();void Clear();void DeepCopy(XMLDocument* target);//省略部分代码
};
3.3 XMLElement 元素容器类
XMLElement元素类,素是一个容器类。它有一个值,元素名,并且可以包含其他元素、文本、注释和未知项。元素还可以包含任意数量的属性。具体的接口解释如下:
class TINYXML2_LIB XMLElement : public XMLNode {friend class XMLDocument;
public:const char* Name();//设置void SetName( const char* str, bool staticMem=false );virtual XMLElement* ToElement();virtual const XMLElement* ToElement();virtual bool Accept( XMLVisitor* visitor );//返回属性的值const char* Attribute( const char* name, const char* value=0 );int IntAttribute(const char* name, int defaultValue = 0);unsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0);int64_t Int64Attribute(const char* name, int64_t defaultValue = 0);uint64_t Unsigned64Attribute(const char* name, uint64_t defaultValue = 0);bool BoolAttribute(const char* name, bool defaultValue = false);double DoubleAttribute(const char* name, double defaultValue = 0);float FloatAttribute(const char* name, float defaultValue = 0);XMLError QueryIntAttribute( const char* name, int* value );XMLError QueryUnsignedAttribute( const char* name, unsigned int* value );XMLError QueryInt64Attribute(const char* name, int64_t* value);XMLError QueryUnsigned64Attribute(const char* name, uint64_t* value);XMLError QueryBoolAttribute( const char* name, bool* value ) ;XMLError QueryDoubleAttribute( const char* name, double* value );XMLError QueryFloatAttribute( const char* name, float* value );XMLError QueryStringAttribute(const char* name, const char** value);/*查询到相应的子元素,并对其修改*/XMLError QueryAttribute( const char* name, int* value );XMLError QueryAttribute( const char* name, unsigned int* value );XMLError QueryAttribute(const char* name, int64_t* value);XMLError QueryAttribute(const char* name, uint64_t* value);XMLError QueryAttribute( const char* name, bool* value );XMLError QueryAttribute( const char* name, double* value );XMLError QueryAttribute( const char* name, float* value );XMLError QueryAttribute(const char* name, const char** value);//设置该名称的element的值。如果元素不存在则创建。void SetAttribute( const char* name, const char* value );void SetAttribute( const char* name, int value )void SetAttribute( const char* name, unsigned value );void SetAttribute(const char* name, int64_t value);void SetAttribute(const char* name, uint64_t value);void SetAttribute( const char* name, bool value );void SetAttribute( const char* name, double value );void SetAttribute( const char* name, float value );//删除名称为name的元素void DeleteAttribute( const char* name );//返回列表中的第一个元素const XMLAttribute* FirstAttribute();//查找列表中的指定名字的元素const XMLAttribute* FindAttribute( const char* name );const char* GetText();//用于设置元素内文本的方法。void SetText( const char* inText );void SetText( int value );void SetText( unsigned value );void SetText(int64_t value);void SetText(uint64_t value);void SetText( bool value );void SetText( double value );void SetText( float value );/*查询子文本节点值的便利方法。这可能是最好的如示例所示。*/XMLError QueryIntText( int* ival );XMLError QueryUnsignedText( unsigned* uval );XMLError QueryInt64Text(int64_t* uval);XMLError QueryUnsigned64Text(uint64_t* uval);XMLError QueryBoolText( bool* bval );XMLError QueryDoubleText( double* dval );XMLError QueryFloatText( float* fval );int IntText(int defaultValue = 0);/*查询子文本节点值的便利方法*/unsigned UnsignedText(unsigned defaultValue = 0);int64_t Int64Text(int64_t defaultValue = 0);uint64_t Unsigned64Text(uint64_t defaultValue = 0);bool BoolText(bool defaultValue = false);double DoubleText(double defaultValue = 0);float FloatText(float defaultValue = 0);/*创建新的XMLElement并将其添加为最后一个(右)的方便方法此节点的子级。返回创建和插入的元素。*/XMLElement* InsertNewChildElement(const char* name);XMLComment* InsertNewComment(const char* comment);XMLText* InsertNewText(const char* text);XMLDeclaration* InsertNewDeclaration(const char* text);XMLUnknown* InsertNewUnknown(const char* text);
protected:char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );//省略不必要代码
};
3.4 XMLAttribute属性操作类
XMLAttribute是属性操作类,其具有具体的属性数量,每个属性都有唯一的名称,可以操作和设置。具体的接口解释如下:
class TINYXML2_LIB XMLAttribute
{//省略不必要代码//属性名字const char* Name() const;//属性值const char* Value() const;//如果文档是从文件分析的,则获取属性所在的行号。int GetLineNum() const { return _parseLineNum; }//列表中的下一个属性。const XMLAttribute* Next();/*IntValue将属性设置为特定类型,并返回值。 */int IntValue();int64_t Int64Value();uint64_t Unsigned64Value();uint64_t Unsigned64Value()//以特定类型形式查询,并返回值。unsigned UnsignedValue();bool BoolValue();double DoubleValue();float FloatValue();/*QueryType将属性解释为Type,并返回值*/XMLError QueryIntValue( int* value ) const;XMLError QueryUnsignedValue( unsigned int* value ) const;XMLError QueryInt64Value(int64_t* value) const;XMLError QueryUnsigned64Value(uint64_t* value) const;XMLError QueryBoolValue( bool* value ) const;XMLError QueryDoubleValue( double* value ) const;XMLError QueryFloatValue( float* value ) const;//将属性设置为特定值。void SetAttribute( const char* value );void SetAttribute( int value );void SetAttribute( unsigned value );void SetAttribute(int64_t value);void SetAttribute(uint64_t value);void SetAttribute( bool value );void SetAttribute( double value );void SetAttribute( float value );//省略不必要代码
};
3.5 XMLComment 注释类
class XMLComment : public XMLNode
{friend class XMLDocument;
public:virtual XMLComment* ToComment();virtual const XMLComment* ToComment();virtual bool Accept( XMLVisitor* visitor ) const;virtual XMLNode* ShallowClone( XMLDocument* document ) const;virtual bool ShallowEqual( const XMLNode* compare ) const;char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);//省略不必要代码
};
3.6 XMLText 文本操作类
XML文本操作类,文本节点可以有两种方式输出下一个。“正常”输出和CDATA。它将默认为从XML文件解析的模式,并且通常希望不使用它,但可以使用以下命令更改输出模式SetCData()并使用CData进行查询。
class TINYXML2_LIB XMLText : public XMLNode
{//省略不必要代码virtual bool Accept( XMLVisitor* visitor ) const;//明这应该是CDATA还是标准文本。void SetCData( bool isCData );//如果这是CDATA文本元素,则返回true。bool CData();virtual XMLNode* ShallowClone( XMLDocument* document ) const;virtual bool ShallowEqual( const XMLNode* compare ) const;//省略不必要代码
};
3.7 XMLDeclaration 声明类
在正确的XML中,声明是文件中的第一个条目。
class TINYXML2_LIB XMLDeclaration : public XMLNode
{//省略不必要代码virtual XMLDeclaration* ToDeclaration();virtual const XMLDeclaration* ToDeclaration();virtual bool Accept( XMLVisitor* visitor );virtual XMLNode* ShallowClone( XMLDocument* document )virtual bool ShallowEqual( const XMLNode* compare );//省略不必要代码
};
4、使用示例
使用tinyxml2解析xml。
4.1 test.xml:
<?xml version="2.0" encoding="utf-8" ?>
<MediaCodecs><Decoders><MediaCodec name="OMX.google.amrnb.decoder" type="audio/3gpp" /><MediaCodec name="OMX.google.amrwb.decoder" type="audio/amr-wb" /><MediaCodec name="OMX.google.aac.decoder" type="audio/mp4a-latm" /><MediaCodec name="OMX.google.h264.decoder" type="video/avc"><Limit name="size" min="2x2" max="2048x2048" /><Limit name="alignment" value="2x2" /><Limit name="block-size" value="16x16" /><Limit name="block-count" range="1-8160" /><Limit name="blocks-per-second" range="1-489600" /><Limit name="bitrate" range="1-40000000" /><Feature name="adaptive-playback" /></MediaCodec></Decoders><Settings><Setting name="max-video-encoder-input-buffers" value="9" /><Setting name="supports-multiple-secure-codecs" value="false" /><Setting name="supports-secure-with-non-secure-codec" value="true" /></Settings><Encoders><MediaCodec name="OMX.google.amrnb.encoder" type="audio/3gpp" /><MediaCodec name="OMX.google.mpeg4.encoder" type="video/mp4v-es" ><Limit name="size" min="176x144" max="640x480" /><Limit name="alignment" value="16x16" /><Limit name="block-size" value="16x16" /><Limit name="blocks-per-second" min="1" max="1485" /><Limit name="bitrate" range="192000-1440000" /></MediaCodec></Encoders>
</MediaCodecs>
4.2 测试代码
#include <iostream>
#include <vector>
#include <string>
#include "include/tinyxml2.h"
using namespace std;
using namespace tinyxml2;#define LINE_PRINT (cout << "------------------------------------------------------" << endl)class XmlUtil
{
public:XmlUtil();~XmlUtil();
public:bool loadXmlFile(const char *path);bool getXMLDeclarationTest(string& strDecl);bool getMediaInfo();bool getDecoderInfo(XMLElement *element);bool getSettingsInfo(XMLElement *element);bool getEncoderInfo(XMLElement *element);bool mLoadFile;XMLDocument mDocFile;
};XmlUtil::XmlUtil() {mLoadFile = false;
}XmlUtil::~XmlUtil() {}bool XmlUtil::loadXmlFile(const char *patch) {if (mLoadFile) {return true;}if (mDocFile.LoadFile(patch) != 0) {cout << "load xml file fail." << endl;return false;}mLoadFile = true;return true;
}bool XmlUtil::getXMLDeclarationTest(string& strDecl) {XMLNode* decl = mDocFile.FirstChild();if (NULL!=decl) { XMLDeclaration* declaration = decl->ToDeclaration(); if (NULL != declaration) { strDecl = declaration->Value();return true;}}return false;
}bool XmlUtil::getMediaInfo() {LINE_PRINT;cout << "获取Decoder Info" << std::endl;XMLElement *root = mDocFile.RootElement();if (root != NULL) {cout << "get root element:" << root->Name() << endl;XMLElement *decoderElemet = root->FirstChildElement("Decoders");XMLElement *settingElemet = root->FirstChildElement("Settings");XMLElement *encoderElemet = root->FirstChildElement("Encoders");if (decoderElemet != NULL) {cout << "get decoder element:" << decoderElemet->Name() << endl;getDecoderInfo(decoderElemet);}if (settingElemet != NULL) {cout << "get setting element:" << settingElemet->Name() << endl;getSettingsInfo(settingElemet);}if (encoderElemet != NULL) {cout << "get encoder element:" << encoderElemet->Name() << endl;getEncoderInfo(encoderElemet);}}
}bool XmlUtil::getDecoderInfo(XMLElement *element) {LINE_PRINT;if (element == NULL) {return false;}cout << "查找Decoders组件下面支持的MediaCodec类型" << endl;for (XMLElement *elem = element->FirstChildElement(); elem != NULL; elem = elem->NextSiblingElement()) {cout << "name:" << elem->Attribute("name") << "\ttype:" << elem->Attribute("type") << endl;XMLElement* childElement = elem->FirstChildElement();while (childElement != NULL) {if (strcmp(childElement->Attribute("name"), "size") == 0) {cout << "\t"<<childElement->Attribute("name") << " min:"<< childElement->Attribute("min") << " max:"<<childElement->Attribute("max") << endl;}if (strcmp(childElement->Attribute("name"), "alignment") == 0) {cout << "\t"<<childElement->Attribute("name") << " value:"<< childElement->Attribute("value") << endl;}if (strcmp(childElement->Attribute("name"), "block-size") == 0) {cout << "\t"<<childElement->Attribute("name") << " value:"<< childElement->Attribute("value") << endl;}if (strcmp(childElement->Attribute("name"), "block-count") == 0) {cout << "\t"<<childElement->Attribute("name") << " range:"<< childElement->Attribute("range") << endl;}if (strcmp(childElement->Attribute("name"), "blocks-per-second") == 0) {cout << "\t"<<childElement->Attribute("name") << " range:"<< childElement->Attribute("range") << endl;}if (strcmp(childElement->Attribute("name"), "bitrate") == 0) {cout << "\t"<<childElement->Attribute("name") << " range:"<< childElement->Attribute("range") << endl;}if (strcmp(childElement->Name(), "Feature") == 0) {cout << "\t"<<"Feature:"<<childElement->Attribute("name") << endl;}childElement = childElement->NextSiblingElement();}}}bool XmlUtil::getSettingsInfo(XMLElement *element) {LINE_PRINT;if (element == NULL) {return false;}cout << "查找Settings下面Setting" << endl;for (XMLElement *elem = element->FirstChildElement(); elem != NULL; elem = elem->NextSiblingElement()) {cout << "name:" << elem->Attribute("name") << "\tvalue:" << elem->Attribute("value") << endl;}LINE_PRINT;
}bool XmlUtil::getEncoderInfo(XMLElement *element) {LINE_PRINT;if (element == NULL) {return false;}cout << "查找Encoders组件下面支持的MediaCodec类型" << endl;for (XMLElement *elem = element->FirstChildElement(); elem != NULL; elem = elem->NextSiblingElement()) {cout << "name:" << elem->Attribute("name") << "\ttype:" << elem->Attribute("type") << endl;XMLElement* childElement = elem->FirstChildElement();while (childElement != NULL) {if (strcmp(childElement->Attribute("name"), "size") == 0) {cout << "\t"<<childElement->Attribute("name") << " min:"<< childElement->Attribute("min") << " max:"<<childElement->Attribute("max") << endl;}if (strcmp(childElement->Attribute("name"), "alignment") == 0) {cout << "\t"<<childElement->Attribute("name") << " value:"<< childElement->Attribute("value") << endl;}if (strcmp(childElement->Attribute("name"), "block-size") == 0) {cout << "\t"<<childElement->Attribute("name") << " value:"<< childElement->Attribute("value") << endl;}if (strcmp(childElement->Attribute("name"), "block-count") == 0) {cout << "\t"<<childElement->Attribute("name") << " range:"<< childElement->Attribute("range") << endl;}if (strcmp(childElement->Attribute("name"), "blocks-per-second") == 0) {cout << "\t"<<childElement->Attribute("name") << " min:"<< childElement->Attribute("min") << " max:" << childElement->Attribute("max") << endl;}if (strcmp(childElement->Attribute("name"), "bitrate") == 0) {cout << "\t"<<childElement->Attribute("name") << " range:"<< childElement->Attribute("range") << endl;}if (strcmp(childElement->Name(), "Feature") == 0) {cout << "\t"<<"Feature:"<<childElement->Attribute("name") << endl;}childElement = childElement->NextSiblingElement();}}LINE_PRINT;
}int main()
{XmlUtil xmlutil;LINE_PRINT;xmlutil.loadXmlFile("test.xml");string declartion;xmlutil.getXMLDeclarationTest(declartion);cout << "获取xml声明测试:" << declartion.c_str() << endl;LINE_PRINT;xmlutil.getMediaInfo();
}
4.3 输出
------------------------------------------------------
获取xml声明测试:xml version="2.0" encoding="utf-8"
------------------------------------------------------
------------------------------------------------------
获取Decoder Info
get root element:MediaCodecs
get decoder element:Decoders
------------------------------------------------------
查找Decoders组件下面支持的MediaCodec类型
name:OMX.google.amrnb.decoder type:audio/3gpp
name:OMX.google.amrwb.decoder type:audio/amr-wb
name:OMX.google.aac.decoder type:audio/mp4a-latm
name:OMX.google.h264.decoder type:video/avcsize min:2x2 max:2048x2048alignment value:2x2block-size value:16x16block-count range:1-8160blocks-per-second range:1-489600bitrate range:1-40000000Feature:adaptive-playback
get setting element:Settings
------------------------------------------------------
查找Settings下面Setting
name:max-video-encoder-input-buffers value:9
name:supports-multiple-secure-codecs value:false
name:supports-secure-with-non-secure-codec value:true
------------------------------------------------------
get encoder element:Encoders
------------------------------------------------------
查找Encoders组件下面支持的MediaCodec类型
name:OMX.google.amrnb.encoder type:audio/3gpp
name:OMX.google.mpeg4.encoder type:video/mp4v-essize min:176x144 max:640x480alignment value:16x16block-size value:16x16blocks-per-second min:1 max:1485bitrate range:192000-1440000
------------------------------------------------------
5.使用总结
XMLElement
查找指定字符串的子元素const XMLElement* XMLNode::FirstChildElement( const char* name )
遍历XMLElement:for (XMLElement *elem = element->FirstChildElement(); elem != NULL; elem = elem->NextSiblingElement()) {cout << "name:" << elem->Attribute("name") << "\ttype:" << elem->Attribute("type") << endl;}
获取指定键值的数据const char* XMLElement::Attribute( const char* name, const char* value )
后续再补充基本插入和修改操作代码。