Nós já publicamos sobre o Expat XML que é também uma alternativa para fazer parser de XML.
No entanto, o TinyXML2 é mais simples e tão eficiente quanto o Expat .
TinyXML2 analisa um documento XML e constrói a partir dele um Document Object Model (DOM) que pode ser lido, modificado e salvo.
O TinyXML2 é uma melhoria do TinyXML 1, mas implementação do analisador do TinyXML2 é mais apropriado para uso em games. Ele usa menos memória, é mais rápido e usa muito menos alocações de memória.
Eu fiz um fork do projeto original para que o repositório possua menos arquivos e demore menos de você implementar, até porque a biblioteca em si são somente 2 arquivos:o header(tinyxml2.hpp
) e o source(tinyxml2.cpp
).
Na versão original o header é com extensão
.h
eu renomeei paratinyxml2.hpp
, ou seja, extensão.hpp
.
Para implementar utilize o Git para clonar e usar os arquivos tinyxml2.hpp
e tinyxml2.cpp
para seu projeto.
mkdir meuprojeto
cd meuprojeto
git clone https://github.com/terroo/tinyxml2/
Nos exemplos abaixo vamos simular um blog em vez de um game que fica mais fácil de entendermos de acordo com artigos .
Primeiro exemplo de um arquivo XML:
primeiro.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- Isso aqui é um comentário e será ignorado pelo TinyXML2-->
<title>Como fazer parser de XML com TinyXML2 C++</title>
Arquivo com a função
main()
com o código:primeiro.cpp
#include <iostream>
#include "tinyxml2/tinyxml2.hpp"
int main(){
tinyxml2::XMLDocument doc;
doc.LoadFile("primeiro.xml");
tinyxml2::XMLElement * p_root_element = doc.RootElement();
std::cout << p_root_element->GetText() << '\n';
return 0;
}
Compile:
g++ primeiro.cpp tinyxml2/tinyxml2.cpp
e rode:./a.out
Possível e provável saída:
Como fazer parser de XML com TinyXML2 C++
Note que o elemento root(*p_root_element
) é o <title>
.
O elemento root agora é a tag <artigo>
segundo.xml
<?xml version="1.0" encoding="UTF-8"?>
<artigo>
<title>Como fazer parser de XML com TinyXML2 C++</title>
</artigo>
Consequentemente precisamos criar um ponteiro para o elemento root e informar a tag
segundo.cpp
#include <iostream>
#include "tinyxml2/tinyxml2.hpp"
int main(){
tinyxml2::XMLDocument doc;
doc.LoadFile("segundo.xml");
tinyxml2::XMLElement * p_root_element = doc.RootElement();
tinyxml2::XMLElement * p_title = p_root_element->FirstChildElement("title");
std::cout << p_title->GetText() << '\n';
return 0;
}
Possível e provável saída:
Como fazer parser de XML com TinyXML2 C++
Se seu artigo tiver diversos elementos, exemplo:
<?xml version="1.0" encoding="UTF-8"?>
<artigo>
<title>Como fazer parser de XML com TinyXML2 C++</title>
<description>Uma ferramenta simples e funcional para ler os tilemaps dos seus games.</description>
<date>2022-03-04</date>
<time>13:40</time>
<tag>c++</tag>
</artigo>
Seu código seria assim:
#include <iostream>
#include "tinyxml2/tinyxml2.hpp"
int main(){
tinyxml2::XMLDocument doc;
doc.LoadFile("segundo.xml");
tinyxml2::XMLElement * p_root_element = doc.RootElement();
tinyxml2::XMLElement * p_title = p_root_element->FirstChildElement("title");
tinyxml2::XMLElement * p_desc = p_root_element->FirstChildElement("description");
tinyxml2::XMLElement * p_date = p_root_element->FirstChildElement("date");
tinyxml2::XMLElement * p_time = p_root_element->FirstChildElement("time");
tinyxml2::XMLElement * p_tag = p_root_element->FirstChildElement("tag");
std::cout << p_title->GetText() << '\n';
std::cout << p_desc->GetText() << '\n';
std::cout << p_date->GetText() << '\n';
std::cout << p_time->GetText() << '\n';
std::cout << p_tag->GetText() << '\n';
return 0;
}
Se quiser deixar seu código mais LIKE A BOSS!, use um vector
:
#include <iostream>
#include <vector>
#include "tinyxml2/tinyxml2.hpp"
int main(){
tinyxml2::XMLDocument doc;
doc.LoadFile("segundo.xml");
std::vector<const char*> elems = {"title", "description", "date", "time", "tag"};
tinyxml2::XMLElement * p_root_element = doc.RootElement();
for (std::size_t i{}; i < elems.size(); ++i){
tinyxml2::XMLElement * ptr = p_root_element->FirstChildElement(elems[i]);
std::cout << ptr->GetText() << '\n';
}
return EXIT_SUCCESS;
}
Possível e provável saída:
Como fazer parser de XML com TinyXML2 C++
Uma ferramenta simples e funcional para ler os tilemaps dos seus games.
2022-03-04
13:40
c++
Se usar
std::string
no seuvector
, converta oelems[i]
parac_str()
assim:elems[i].c_str()
.
A partir daqui vamos usar essa sintaxe LIKE A BOSS! para os próximos exemplos!
O elemento root agora é o <blog>
:
terceiro.xml
<?xml version="1.0" encoding="UTF-8"?>
<blog>
<artigo>
<title>Como fazer parser de XML com TinyXML2 C++</title>
<description>Uma ferramenta simples e funcional para ler os tilemaps dos seus games.</description>
<date>2022-03-04</date>
<time>13:40</time>
<tag>c++</tag>
</artigo>
<artigo>
<title>Conheça os detalhes dos Estilos de Indentação</title>
<description>O estilo de recuo não é obrigatório na maioria das linguagens de programação.</description>
<date>2022-02-13</date>
<time>08:27</time>
<tag>codigo</tag>
</artigo>
</blog>
E o código:
#include <iostream>
#include <vector>
#include "tinyxml2/tinyxml2.hpp"
int main(){
tinyxml2::XMLDocument doc;
doc.LoadFile("terceiro.xml");
std::vector<const char*> elems = {"title", "description", "date", "time", "tag"};
tinyxml2::XMLElement * p_root_element = doc.RootElement();
tinyxml2::XMLElement * p_artigo = p_root_element->FirstChildElement("artigo");
while(p_artigo){
for (std::size_t i{}; i < elems.size(); ++i){
tinyxml2::XMLElement * ptr = p_artigo->FirstChildElement(elems[i]);
std::cout << elems[i] << ": " << ptr->GetText() << '\n';
std::cout << ( i == elems.size() - 1 ? "\n" : "");
}
p_artigo = p_artigo->NextSiblingElement("artigo");
}
return EXIT_SUCCESS;
}
Note que o ponteiro
*p_artigo
obtém o primeiro elemento do root e o*ptr
obtém dele. Para pularmos para o próximo artigo, usamos:p_artigo = p_artigo->NextSiblingElement("artigo");
dentro e ao final do loopwhile
. A condição ternária foi só para separar os artigos.
Possível e provável saída:
title: Como fazer parser de XML com TinyXML2 C++
description: Uma ferramenta simples e funcional para ler os tilemaps dos seus games.
date: 2022-03-04
time: 13:40
tag: c++
title: Conheça os detalhes dos Estilos de Indentação
description: O estilo de recuo não é obrigatório na maioria das linguagens de programação.
date: 2022-02-13
time: 08:27
tag: codigo
Imagine se houvesse mais um elemento <data>
após o root para fazer uma hierarquia mais expressiva, exemplo:
vim quarto.xml
<?xml version="1.0" encoding="UTF-8"?>
<blog>
<data>
<artigo>
<title>Como fazer parser de XML com TinyXML2 C++</title>
<description>Uma ferramenta simples e funcional para ler os tilemaps dos seus games.</description>
<date>2022-03-04</date>
<time>13:40</time>
<tag>c++</tag>
</artigo>
<artigo>
<title>Conheça os detalhes dos Estilos de Indentação</title>
<description>O estilo de recuo não é obrigatório na maioria das linguagens de programação.</description>
<date>2022-02-13</date>
<time>08:27</time>
<tag>codigo</tag>
</artigo>
</data>
<data>
<artigo>
<title>Primeiro post da segunda data</title>
<description>Somente um exemplo de descrição.</description>
<date>2019-02-11</date>
<time>00:43</time>
<tag>c</tag>
</artigo>
<artigo>
<title>Segundo post da segunda data</title>
<description>Exemplo de descrição 2.</description>
<date>2021-08-04</date>
<time>10:05</time>
<tag>mais</tag>
</artigo>
</data>
</blog>
No código teríamos dois loop while
e *p_artigo
agora obteria o FirstChildElement()
de *p_data
:
vim quarto.cpp
#include <iostream>
#include <vector>
#include "tinyxml2/tinyxml2.hpp"
int main(){
tinyxml2::XMLDocument doc;
doc.LoadFile("quarto.xml");
std::vector<const char*> elems = {"title", "description", "date", "time", "tag"};
tinyxml2::XMLElement * p_root_element = doc.RootElement();
tinyxml2::XMLElement * p_data = p_root_element->FirstChildElement("data");
while(p_data){
tinyxml2::XMLElement * p_artigo = p_data->FirstChildElement("artigo");
while(p_artigo){
for (std::size_t i{}; i < elems.size(); ++i){
tinyxml2::XMLElement * ptr = p_artigo->FirstChildElement(elems[i]);
std::cout << elems[i] << ": " << ptr->GetText() << '\n';
std::cout << ( i == elems.size() - 1 ? "\n" : "");
}
p_artigo = p_artigo->NextSiblingElement("artigo");
}
p_data = p_data->NextSiblingElement("data");
}
return EXIT_SUCCESS;
}
Possível e provável saída:
title: Como fazer parser de XML com TinyXML2 C++
description: Uma ferramenta simples e funcional para ler os tilemaps dos seus games.
date: 2022-03-04
time: 13:40
tag: c++
title: Conheça os detalhes dos Estilos de Indentação
description: O estilo de recuo não é obrigatório na maioria das linguagens de programação.
date: 2022-02-13
time: 08:27
tag: codigo
title: Primeiro post da segunda data
description: Somente um exemplo de descrição.
date: 2019-02-11
time: 00:43
tag: c
title: Segundo post da segunda data
description: Exemplo de descrição 2.
date: 2021-08-04
time: 10:05
tag: mais
Ainda é possível alterar conteúdos, obter nomes de tags, números de linhas e entre outras funcionalidades. Para uma documentação completa veja esse link .