web-dev-qa-db-fra.com

Comment analyser un fichier XML avec RapidXml

Je dois analyser un fichier XML en C++. Je faisais des recherches et ai trouvé la bibliothèque RapidXml pour cela. 

J'ai des doutes sur doc.parse<0>(xml).

xml peut-il être un fichier .xml ou doit-il être un string ou char *?

Si je ne peux utiliser que string ou char *, alors je suppose que je dois lire tout le fichier et le stocker dans un tableau de caractères et en passer le pointeur à la fonction?

Existe-t-il un moyen d'utiliser directement un fichier parce que je devrais également modifier le fichier XML dans le code.

Si cela n’est pas possible dans RapidXml, veuillez suggérer d’autres bibliothèques XML en C++.

Merci!!!

Ashd

17
ashd

RapidXml est livré avec une classe pour le faire pour vous, rapidxml::file dans le fichier rapidxml_utils.hpp. Quelque chose comme:

#include "rapidxml_utils.hpp"

int main() {
    rapidxml::file<> xmlFile("somefile.xml"); // Default template is char
    rapidxml::xml_document<> doc;
    doc.parse<0>(xmlFile.data());
...
}

Notez que l'objet xmlFile contient désormais toutes les données du fichier XML, ce qui signifie qu'une fois qu'il est hors de portée et détruit, la variable doc n'est plus utilisable en toute sécurité. Si vous appelez analyse à l'intérieur d'une fonction, vous devez conserver l'objet xmlFile en mémoire (variable globale, nouvelle, etc.) pour que le document reste valide.

27
Superfly Jon

Nouveau en C++ moi-même ... mais je voulais partager une solution.

YMMV!

Criez à SiCrane sur ce thread : - et remplacez simplement 'string' par un vecteur --- (merci anno)

S'il vous plaît commenter et aidez-moi à apprendre aussi! Je suis très nouveau pour cela

Quoi qu’il en soit, cela semble bien fonctionner:

#include <iostream>
#include <fstream>
#include <vector>

#include "../../rapidxml/rapidxml.hpp"

using namespace std;

int main(){
   ifstream myfile("sampleconfig.xml");
   rapidxml::xml_document<> doc;

   /* "Read file into vector<char>"  See linked thread above*/
   vector<char> buffer((istreambuf_iterator<char>(myfile)), istreambuf_iterator<char>( ));

   buffer.Push_back('\0');

   cout<<&buffer[0]<<endl; /*test the buffer */

   doc.parse<0>(&buffer[0]); 

   cout << "Name of my first node is: " << doc.first_node()->name() << "\n";  /*test the xml_document */


}
7
FlipMcF

Nous lisons habituellement le code XML du disque dans un std::string, puis en faisons une copie sûre dans un std::vector<char>, comme illustré ci-dessous:

string input_xml;
string line;
ifstream in("demo.xml");

// read file into input_xml
while(getline(in,line))
    input_xml += line;

// make a safe-to-modify copy of input_xml
// (you should never modify the contents of an std::string directly)
vector<char> xml_copy(input_xml.begin(), input_xml.end());
xml_copy.Push_back('\0');

// only use xml_copy from here on!
xml_document<> doc;
// we are choosing to parse the XML declaration
// parse_no_data_nodes prevents RapidXML from using the somewhat surprising
// behavior of having both values and data nodes, and having data nodes take
// precedence over values when printing
// >>> note that this will skip parsing of CDATA nodes <<<
doc.parse<parse_declaration_node | parse_no_data_nodes>(&xml_copy[0]);

Pour une vérification complète du code source:

Lire une ligne d'un fichier xml à l'aide de C++

2
karlphillip

Le manuel nous dit:

fonction xml_document :: parse 

[...] Analyse la chaîne XML à terminaison zéro En fonction des indicateurs donnés.

RapidXML vous permet de charger les données de personnage d’un fichier. Soit lire le fichier dans un tampon, comme anno suggéré, soit utiliser une technique de mappage de la mémoire. (Mais cherchez le drapeau parse_non_destructive en premier.)

0
Martin Ba