当前位置: 首页 > 工具软件 > TinyXml > 使用案例 >

tinyxml2 01 基本使用

於乐
2023-12-01

加载

文件位置: https://gitcode.net/u014254963/tinyxml2-study/-/blob/master/test/test_tinyxml2_load.cpp

从文件加载

文档翻译

从文件加载的方法为有两个

tinyxml2::XMLDocument::LoadFile(const char *filename)
tinyxml2::XMLDocument::LoadFile(FILE *)
/**
	Load an XML file from disk.
	Returns XML_SUCCESS (0) on success, or
	an errorID.
*/
/**
从磁盘加载一个 xml 文件
成功返回 XML_SUCCESS , 值为 0
或者返回一个错误号
*/
XMLError LoadFile( const char* filename );

/**
	Load an XML file from disk. You are responsible
	for providing and closing the FILE*.

    NOTE: The file should be opened as binary ("rb")
    not text in order for TinyXML-2 to correctly
    do newline normalization.

	Returns XML_SUCCESS (0) on success, or
	an errorID.
*/
/**
从磁盘加载文件.  由您负责提供和关闭 文件指针

注意:
文本应该以二进制("rb")方式打开而不是文本方式, 以便 tinyxml2 正确执行换行规范化
成功返回 XML_SUCCESS , 值为 0
或者返回一个错误号
*/
XMLError LoadFile( FILE* );

测试用例

#include <cstdio>

#include "doctest/doctest.h"
#include "tinyxml2.h"
#include "spdlog/spdlog.h"
#include "khl_xml_config/khl_xml_config.hpp"

TEST_CASE("tinyxml2_load")
{
    std::string simpleXmlPath;

    tinyxml2::XMLDocument doc;
    tinyxml2::XMLError xmlError;

    /**
     * 指定路径加载
     */
    SUBCASE("load_by_path")
    {
        simpleXmlPath = getXmlPath("/data/simple.xml");
        xmlError = doc.LoadFile(simpleXmlPath.c_str());
        CHECK(tinyxml2::XMLError::XML_SUCCESS == xmlError);
    }

    /**
     * 指定路径加载
     */
    SUBCASE("load_by_path_file_not_found")
    {
        simpleXmlPath = getXmlPath("/data/simple.not.exist.xml");
        xmlError = doc.LoadFile(simpleXmlPath.c_str());
        CHECK(tinyxml2::XMLError::XML_ERROR_FILE_NOT_FOUND == xmlError);
    }

    /**
     * 使用 FILE * 加载
     */
    SUBCASE("load_by_file")
    {
        simpleXmlPath = getXmlPath("/data/simple.xml");
        FILE * file = fopen(simpleXmlPath.c_str(),"rb");
        bool openSuccess = NULL != file;
        CHECK(openSuccess);

        xmlError = doc.LoadFile(simpleXmlPath.c_str());
        CHECK(tinyxml2::XMLError::XML_SUCCESS == xmlError);

        bool closeSuccess = 0 == fclose(file);
        CHECK(closeSuccess);
    }
}

从字符串加载

文档翻译

从文档加载的方法有一个

tinyxml2::XMLDocument::Parse
/**
	Parse an XML file from a character string.
	Returns XML_SUCCESS (0) on success, or
	an errorID.

	You may optionally pass in the 'nBytes', which is
	the number of bytes which will be parsed. If not
	specified, TinyXML-2 will assume 'xml' points to a
	null terminated string.
*/
/**
从字符串解析xml
成功返回 XML_SUCCESS , 值为 0
或者返回一个错误号

你可以选择传入`nBytes`,这是将要被解析的字节数。如果没有指定,TinyXML-2将假设` xml `指向一个以null结尾的字符串。
*/
XMLError Parse( const char* xml, size_t nBytes=static_cast<size_t>(-1) );

测试用例

TEST_CASE("tinyxml2_load")
{
    std::string simpleXmlPath;

    tinyxml2::XMLDocument doc;
    tinyxml2::XMLError xmlError;

    /**
     * 从字符串加载
     */
    SUBCASE("load_by_charbuffe")
    {
        static const char *xml = "<element/>";
        xmlError = doc.Parse(xml);
        CHECK(tinyxml2::XMLError::XML_SUCCESS == xmlError);
    }

    /**
     * 从字符串加载
     */
    SUBCASE("load_by_charbuffe")
    {
        static const char *xml = "";
        xmlError = doc.Parse(xml);
        CHECK(tinyxml2::XMLError::XML_ERROR_EMPTY_DOCUMENT == xmlError);
    }
}

节点操作

TinyXML-2 doesn’t parse or use DTDs (Document Type Definitions) or XSLs (eXtensible Stylesheet Language.) There are other parsers out there that are much more fully featured. But they are generally bigger and more difficult to use. If you are working with browsers or have more complete XML needs, TinyXML-2 is not the parser for you.


TinyXML-2不解析或使用dtd(文档类型定义)或xsl(可扩展样式表语言)。还有其他功能更全面的解析器。但它们通常更大,更难使用。如果您正在使用浏览器或有更完整的XML需求,TinyXML-2不是适合您的解析器。

xml 数据

<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<personList>
    <person id="1001" name="khl001" age="34" manager="true">
        <intro>这是一段介绍. 这是一段介绍.</intro>
    </person>
    <person id="1002" name="khl002" age="56" manager="false">
        <intro>这是一段介绍. 这是一段介绍.</intro>
    </person>
    <person id="1003" name="khl003" age="48">
        <intro>这是一段介绍. 这是一段介绍.</intro>
    </person>
</personList>

查找节点

tinyxml2不支持xpath, 所以只能一级一级的查找

代码位置: https://gitcode.net/u014254963/tinyxml2-study/-/blob/master/test/test_tinyxml2_find_node.cpp

TEST_CASE("tinyxml2_find_node")
{
    std::string simpleXmlPath;

    tinyxml2::XMLDocument doc;
    tinyxml2::XMLError xmlError;

    /**
     * 查找节点
     */
    SUBCASE("find_node")
    {
        simpleXmlPath = getXmlPath("/data/simple.xml");
        xmlError = doc.LoadFile(simpleXmlPath.c_str());
        CHECK(tinyxml2::XMLError::XML_SUCCESS == xmlError);

        const char* id = "1002";

        auto rootEl = doc.RootElement();
        auto personNode = rootEl->FirstChildElement("person");
        while( nullptr != personNode )
        {
            if( 0 == strcmp(id,personNode->Attribute("id")))
            {
                break;
            }

            personNode = personNode->NextSiblingElement();
        }

        bool find = nullptr != personNode;
        CHECK(find);
        bool idCheck = 0 == strcmp(id,personNode->Attribute("id"));
        CHECK(idCheck);
    }
}

编辑节点

代码位置: https://gitcode.net/u014254963/tinyxml2-study/-/blob/master/test/test_tinyxml2_edit_node.cpp

TEST_CASE("tinyxml2_edit_node")
{
    std::string simpleXmlPath;
    std::string xmlEditResultPath;

    tinyxml2::XMLDocument doc;
    tinyxml2::XMLError xmlError;

    /**
     * 添加节点
     */
    SUBCASE("add_node")
    {
        simpleXmlPath = getXmlPath("/data/simple.xml");
        xmlEditResultPath = getXmlPath("/data/edit_add_node_result.xml");

        xmlError = doc.LoadFile(simpleXmlPath.c_str());
        CHECK(tinyxml2::XMLError::XML_SUCCESS == xmlError);

        auto rootEl = doc.RootElement();

        const char* id = "1004";
        auto newPersonNode = doc.NewElement("person");
        newPersonNode->SetAttribute("id", id);
        rootEl->InsertEndChild(newPersonNode);

        doc.SaveFile(xmlEditResultPath.c_str());

        xmlError = doc.LoadFile(xmlEditResultPath.c_str());
        CHECK(tinyxml2::XMLError::XML_SUCCESS == xmlError);

        rootEl = doc.RootElement();

        auto personNode = rootEl->FirstChildElement("person");
        while( nullptr != personNode )
        {
            if( 0 == strcmp(id,personNode->Attribute("id")))
            {
                break;
            }

            personNode = personNode->NextSiblingElement();
        }

        bool hasNewPersonNode = nullptr != personNode;
        CHECK(hasNewPersonNode);
    }

    /**
     * 删除节点
     */
    SUBCASE("remove_node")
    {
        simpleXmlPath = getXmlPath("/data/simple.xml");
        xmlEditResultPath = getXmlPath("/data/edit_remove_node_result.xml");

        xmlError = doc.LoadFile(simpleXmlPath.c_str());
        CHECK(tinyxml2::XMLError::XML_SUCCESS == xmlError);

        
        const char* id = "1002";

        auto rootEl = doc.RootElement();
        auto personNode = rootEl->FirstChildElement("person");
        while( nullptr != personNode )
        {
            if( 0 == strcmp(id,personNode->Attribute("id")))
            {
                break;
            }

            personNode = personNode->NextSiblingElement();
        }

        rootEl->DeleteChild(personNode);

        doc.SaveFile(xmlEditResultPath.c_str());

        xmlError = doc.LoadFile(xmlEditResultPath.c_str());
        CHECK(tinyxml2::XMLError::XML_SUCCESS == xmlError);

        rootEl = doc.RootElement();
        personNode = rootEl->FirstChildElement("person");
        while( nullptr != personNode )
        {
            if( 0 == strcmp(id,personNode->Attribute("id")))
            {
                break;
            }

            personNode = personNode->NextSiblingElement();
        }

        bool person1002NotExist = nullptr == personNode;
        CHECK(person1002NotExist);
    }
}

添加节点

除了 InsertEndChild方法, 还有其他方法:
tinyxml2::XMLNode::InsertFirstChild(XMLNode * addThis)
tinyxml2::XMLNode::InsertAfterChild ( XMLNode * afterThis,XMLNode * addThis )

删除节点

除了DeleteChild 方法, 还可以用 DeleteChildren() 方法删除所有子节点, 也可以使用 doc.DeleteNode删除节点, 比如doc.DeleteNode(root)会删除所有节点

输出

// 输出到文件
doc.SaveFile(xmlEditResultPath.c_str());
// 输出到标准输出
doc.Print()
// 输出到内存
tinyxml2::XMLPrinter printer;
doc.Print(&printer);
spdlog::info("xml content:\n {}",printer.CStr());

其他测试

 类似资料: