tinyxml2使用

1.概述

tinyxml2 github地址
本文涵盖了日常编码中会使用tinyxml2库进行的一些操作,包括:解析xml文件或者xml格式内容的字符串、获取xml节点属性与内容、增加节点或属性、删除节点或属性、将doc对象保存为xml文件或者字符串、从一个文档拷贝节点到另一个文档中等。
本文以类似svg内容存储的数据来进行实例操作,以下为实例操作涉及到的数据。

<?xml version="1.0" encoding="UTF-8"?>
<draw width="200" height="100" version="1" original="true" author="FabianD" createtime="2021-04-08">
    <geometry id="1">
        <line x1="5" y1="5" x2="5" y2="10"/>
        <circle cx="5" cy="5" r="5"/>
    </geometry>
    <remark>势均力敌,才能生生不息</remark>
</draw>

2.构造数据并创建xml文件

 using namespace tinyxml2;
 XMLDocument doc;//定义doc对象
    
 //<1.增加xml文档声明
 //方式1
const char* declaration="<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
XMLError result = doc.Parse(declaration);
//方式2,生成的内容同上
XMLDeclaration* declarationElement = doc.NewDeclaration();
doc.InsertFirstChild(declarationElement);

 //<2.添加节点
XMLElement* drawElement = doc.NewElement("draw");
doc.InsertEndChild(drawElement);

//<3.添加属性并设置属性值
drawElement->SetAttribute("width", 200.0);//double类型
drawElement->SetAttribute("height", 100.0);//double类型
drawElement->SetAttribute("version", 1);//int类型
drawElement->SetAttribute("original", true);//bool类型
std::string author = "FabianD";
drawElement->SetAttribute("author", author.c_str());//const char*类型
drawElement->SetAttribute("createtime", "2021-04-08");//const char*类型

//<4.添加子节点
XMLElement* geometryElement = doc.NewElement("");//暂不设置节点名称
geometryElement->SetName("geometry");//通过SetName函数设置节点名称
geometryElement->SetAttribute("id", 1);
drawElement->InsertEndChild(geometryElement);

 //添加直线节点至geometryElement
XMLElement* lineElement = doc.NewElement("line");
lineElement->SetAttribute("x1", 5);
lineElement->SetAttribute("y1", 5);
lineElement->SetAttribute("x2", 5);
lineElement->SetAttribute("y2", 10);
geometryElement->InsertEndChild(lineElement);

//添加圆节点至geometryElement
XMLElement* circleElement = doc.NewElement("circle");
circleElement->SetAttribute("cx", 5);
circleElement->SetAttribute("cy", 5);
circleElement->SetAttribute("r", 5);
geometryElement->InsertEndChild(circleElement);

//添加remarkElement至根节点
XMLElement* remarkElement = doc.NewElement("remark");
remarkElement->SetText("势均力敌,才能生生不息");//设置节点内容
drawElement->InsertEndChild(remarkElement);

//<5.保存至文件中
result = doc.SaveFile("Draw.xml");//会清除原来文件中的内容    

3.解析xml文件并读取数据

using namespace tinyxml2;
XMLDocument doc;
XMLError result;
//<1.加载解析文件
result = doc.LoadFile("Draw.xml");
if (result == XML_SUCCESS) {
    //<2.获取根节点
    XMLElement* drawElement = doc.RootElement();//获取根节点
    if (drawElement) {
        //<3.获取属性值
        //方式1
        double width = 0;
        result = drawElement->QueryDoubleAttribute("width", &width);
        if (result == XML_SUCCESS) {
            std::cout << "Width:" << width << std::endl;
        }else {
            std::cout << "根节点没有width属性" << std::endl;
        }
        //方式2
        const char* heightPtr = drawElement->Attribute("height");
        if (heightPtr) {
            double height = std::stod(heightPtr);//stod为新特性下的函数
            std::cout << "Height:" << height << std::endl;
        }else {
            std::cout << "根节点没有height属性" << std::endl;
        }
        //方式3
        int version = drawElement->IntAttribute("version", 0);//第二个参数为默认返回值,这种方式在找不到属性时会返回默认值,适合确定有属性存在的情况
        std::cout << "Version:" << version << std::endl;
        //获取其他类型属性值
        bool original = false;
        result = drawElement->QueryBoolAttribute("original", &original);
        if (result == XML_SUCCESS) {
            std::cout << "Original:" << original << std::endl;
        }
        const char* authorPtr = drawElement->Attribute("author");
        if (authorPtr) {
            std::cout << "Author:" << authorPtr << std::endl;
        }
        
        //<4.获取子节点
        XMLElement* geometryElement = drawElement->FirstChildElement("geometry");//传入节点名称
        if (geometryElement) {
            XMLElement* childElement = geometryElement->FirstChildElement();//不传入节点名称,返回第一个子节点
            //遍历获取子节点
        	while (childElement) {
	            if (!std::strcmp(childElement->Name(), "line")) {
	                //获取直线节点相关属性
	                double x1 = childElement->DoubleAttribute("x1");
	                double y1 = childElement->DoubleAttribute("y1");
	                std::cout << "LineX1:" << x1 << std::endl;
	                //...
	             }else if (!std::strcmp(childElement->Name(), "circle")) {
	                //获取圆节点相关属性
	                double cx = childElement->DoubleAttribute("cx");
	                double cy = childElement->DoubleAttribute("cy");
	                std::cout << "CircleCx:" << cx << std::endl;
	                //...
	            }
	            childElement = childElement->NextSiblingElement();//获取同一级的下一节点
    	   }
	  	}
      	//获取remark子节点
       XMLElement* remarkElement = drawElement->FirstChildElement("remark");
       if (remarkElement) {
          const char* remark = remarkElement->GetText();//获取节点内容
          std::cout << "Remark:" << remark << std::endl;
       }

       //<5.修改节点
       //修改节点属性值及内容
       if (remarkElement) {
          remarkElement->SetText("至死不渝");
          remarkElement->SetAttribute("type", "love");
       }
       //删除属性及节点
       drawElement->DeleteAttribute("version");//删除version属性
       geometryElement->DeleteChild(geometryElement->FirstChildElement("line"));//删除line节点
       //geometryElement->DeleteChildren();//删除所有子节点
       doc.SaveFile("Draw.xml");//重新保存
       }else {
        std::cout << "文件没有根节点" << std::endl;
      }
}else { 
    std::cout << "解析失败:" << result << std::endl;
}

4.其他一些操作

using namespace tinyxml2;
XMLDocument doc;
XMLError result = doc.LoadFile("Draw.xml");
if (result == XML_SUCCESS) {
    //<1.读取xml文件内容至const char*中
    XMLPrinter printer;
    doc.Print(&printer);
    const char* contentPtr = printer.CStr();
    std::cout << "xml content:" << contentPtr << std::endl;

    //<2.解析字符串内容
    XMLDocument docx;
    result = docx.Parse(contentPtr);
    if(result==XML_SUCCESS){
        if (docx.RootElement()) {
            std::cout << docx.RootElement()->Name();
        }
    }

    //<3.复制doc中的节点到另一个doc中
    XMLDocument docTarget;
    result = docTarget.LoadFile("Draw.xml");
    if (result == XML_SUCCESS) {
        XMLElement* drawElementSource = doc.RootElement();
        XMLElement* drawElementTarget = docTarget.RootElement();
        if (drawElementTarget) {
            XMLElement* geometryElementTarget = drawElementTarget->FirstChildElement("geometry");
            if (geometryElementTarget) {
                XMLNode* geometryElementSource = geometryElementTarget->DeepClone(&doc);//复制节点到新doc中
                drawElementSource->InsertFirstChild(geometryElementSource);//执行插入操作
                result = doc.SaveFile("Draw.xml");
            }
        }
    }
}

5.总结

tinyxml2经常用到的几个对象:

1.tinyxml2::XMLNode:XMLDocment、XMLElement的基类

  • XMLNode* InsertFirstChild(XMLNode* node): 在对象(文档/节点)最前面插入节点node。
  • XMLNode* InsertEndChild(XMLNode* node): 在对象(文档/节点)最后面插入节点node。
  • XMLNode* InsertAfterChild(XMLNode* afterNode,XMLNode* node): 在节点afterNode后面插入节点node。
  • void DeleteChild(XMLNode*): 删除子节点node。
  • void DeleteChildren(): 删除所有子节点。
  • static void DeleteChild(XMLNode*): 删除节点node。
  • XMLNode* DeepClone(XMLDocument* target): 拷贝一份数据到target文档中,返回有同样数据的XMLNode*。
  • XMLElement* FirstChildElement(const char* name==NULL): 获取对象(文档/节点)下节点名称为name的第一个子节点。
  • XMLElement* LastChildElement(const char* name==NULL): 获取对象(文档/节点)下节点名称为name的最后一个子节点。
  • XMLNode* Parent(): 获取(文档/节点)的父节点。
  • XMLElement* NextSiblingElement(const char* name==NULL): 获取对象(文档/节点)同级中往后名称为name的节点。
  • XMLElement* PreviousSiblingElement(const char* name==NULL): 获取对象(文档/节点)同级中往前名称为name的节点。

2.tinyxml2::XMLDocument:

  • XMLError LoadFile(const char*): 用来加载解析xml文件。
  • XMLError SaveFile(const char*): 用来保存数据至xml文件。
  • XMLError Parse(const char*): 用来解析字符串内容。
  • XMLDeclaration* NewDeclaration(): 用来创建doc的文档声明,创建后,还需要将其插入XMLDocument对象中才有作用。
  • XMLElement* NewElement(): 用来创建doc的节点,创建后,还需要将其插入XMLDocument对象中才有作用。

3.tinyxml2::XMLElement:

  • void SetAttribute(const char*, T value): 设置属性,T可以是任意基础类型。
  • void SetName( const char* str, bool staticMem=false ): 设置节点名称。
  • XMLError QueryIntAttribute( const char* name, int* value ): 获取名称为name,type为int的属性的值,如果该值不是int类型,返回值将不是XML_SUCCESS。同类型的函数还有:QueryDoubleAttribute、QueryBoolAttribute等。
  • const char* XMLElement::Attribute( const char* name, const char* value ): 获取名称为name的属性值,如果没有该属性,则返回默认值value。
  • int IntAttribute(const char* name, int defaultValue): 获取名称为name的属性值,如果没有该属性,则返回默认值defaultValue。
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值