Soyez le premier à donner votre avis sur cette source.
Vue 17 580 fois - Téléchargée 1 693 fois
///////////////////////////////////////////////////////////////////////////// // CECI EST UN APPERCU DU CODE ZIPPE.... ///////////////////////////////////////////////////////////////////////////// struct t_xml_node { // constructor t_xml_node( std::string const & key = "_EMPTY_", std::string const & value = "" ); // destructor virtual ~t_xml_node(); // copy constructor t_xml_node( t_xml_node const & node ); // assignment t_xml_node & operator=( t_xml_node const & node ); // key accessers std::string const & key() const; std::string & key(); // value accessers std::string const & value() const; std::string & value(); // number of attributes std::size_t nb_attributes() const; // add an attributes void insert_attribute( std::string const & attribute, std::string const & value ); // remove an attributes void remove_attribute( std::size_t const & index ); // remove an attribute through string indexer void remove_attribute( std::string const & attribute ); // get an attribute std::string const & attribute_at( std::size_t const & index ) const; std::string & attribute_at( std::size_t const & index ); // get an attribute associated value std::string const & attribute_value_at( std::size_t const & index ) const; std::string & attribute_value_at( std::size_t const & index ); // get an attribute associated through string indexer (key_suffix = "aaaa:n", "aaaa"+":0" by default suffix) std::string const & attribute_value_at( std::string const & attribute ) const; std::string & attribute_value_at( std::string const & attribute ); // number of children std::size_t nb_children() const; // add a child void insert_child( t_xml_node const & child ); // remove a child void remove_child( std::size_t const & index ); // remove a child through string indexer (key_suffix = "aaaa:n", "aaaa"+":0" by default suffix) void remove_child( std::string const & key_suffix ); // get a child t_xml_node const & child_at( std::size_t const & index ) const; t_xml_node & child_at( std::size_t const & index ); // get a child through indexer (key_suffix = "aaaa:n", "aaaa"+":0" by default suffix) t_xml_node const & child_at( std::string const & key_suffix ) const; t_xml_node & child_at( std::string const & key_suffix ); // build : transform a tree/node into a XML stream/file void build_to_file( std::string const & path_filename ) const; std::string build_to_str() const; // parse : transform a XML stream/file into a tree/node void parse_from_file( std::string const & path_filename ); void parse_from_str( std::string const & str ); }; ///////////////////////////////////////////////////////////////////////////// // CECI EST UN APPERCU DU CODE ZIPPE.... ///////////////////////////////////////////////////////////////////////////// struct t_xml_manip { // constructor t_xml_manip( t_xml_node & root ); // key management std::vector< std::string > ls( std::string const & path ) const; // list keys void mk( std::string const & path ) const; // make new key or new attribute void rm( std::string const & path ) const; // remove key or attribute void mv( std::string const & src_path, std::string const & dst_path ) const; // move key void cp( std::string const & src_path, std::string const & dst_path ) const; // copy key // key-value and attribute-value read/write std::string const & operator()( std::string const & path ) const; // read key-value or attribute-value std::string & operator()( std::string const & path ); // read/write key-value or attribute-value std::string const & read( std::string const & path ) const; // read key-value or attribute-value void write( std::string const & value, std::string const & path ) const; // write key-value or attribute-value } ///////////////////////////////////////////////////////////////////////////// // CECI EST UN APPERCU DU CODE ZIPPE.... ///////////////////////////////////////////////////////////////////////////// { // example 1.1.1 : // // player_list (number_of_players : 2) // +---> player (id : 0001) // | +---> name : xterm-in-hate // | +---> level : 39 // | +---> class : berseker // | +---> experience : 8012 // | +---> position // | | +---> world : earth // | | +---> xcord : 111 // | | +---> ycord : 452 // | | +---> zcord : 37 // | | +---> xyangle : 162 // | | +---> xzangle : -9 // | +---> health : 120 // | +---> mana : 270 // +---> player (id : 0002) // . +---> name : guest // . +---> level : 1 // . +---> class : paladin // . +---> experience : 0 // . +---> position // . | +---> world : earth // . | +---> xcord : 118 // . | +---> ycord : 493 // . | +---> zcord : 38 // . | +---> xyangle : 25 // . | +---> xzangle : 0 // . +---> health : 50 // . +---> mana : 22 cout << "EXAMPLE#1.1.1" << endl; // root node : player list t_xml_node root( "player_list", "" ); root.insert_attribute("number_of_players","2"); // child 1 node : player t_xml_node c1( "player", "" ); c1.insert_attribute( "id", "0001" ); // child 1-1 node : name t_xml_node c11( "name", "xterm-in-hate" ); c1.insert_child(c11); // child 1-2 node : level t_xml_node c12( "level", "39" ); c1.insert_child(c12); // child 1-3 node : class t_xml_node c13( "class", "berseker" ); c1.insert_child(c13); // child 1-4 node : experience t_xml_node c14( "experience", "8012" ); c1.insert_child(c14); // child 1-5 node : position t_xml_node c15( "position", "" ); // child 1-5-1 node : world t_xml_node c151( "world", "earth" ); c15.insert_child(c151); // child 1-5-2 node : xcord t_xml_node c152( "xcord", "111" ); c15.insert_child(c152); // child 1-5-3 node : ycord t_xml_node c153( "ycord", "452" ); c15.insert_child(c153); // child 1-5-4 node : zcord t_xml_node c154( "zcord", "37" ); c15.insert_child(c154); // child 1-5-5 node : xyangle t_xml_node c155( "xyangle", "162" ); c15.insert_child(c155); // child 1-5-6 node : xzangle t_xml_node c156( "xzangle", "-9" ); c15.insert_child(c156); // child 1-5 node : position (end) c1.insert_child(c15); // child 1-6 node : health t_xml_node c16( "health", "120" ); c1.insert_child(c16); // child 1-7 node : mana t_xml_node c17( "mana", "270" ); c1.insert_child(c17); // child 1 node : player (end) root.insert_child(c1); // child 2 node : player t_xml_node c2( "player", "" ); c2.insert_attribute( "id", "0002" ); // child 2-1 node : name t_xml_node c21( "name", "guest" ); c2.insert_child(c21); // child 2-2 node : level t_xml_node c22( "level", "1" ); c2.insert_child(c22); // child 2-3 node : class t_xml_node c23( "class", "paladin" ); c2.insert_child(c23); // child 2-4 node : experience t_xml_node c24( "experience", "0" ); c2.insert_child(c24); // child 2-5 node : position t_xml_node c25( "position", "" ); // child 2-5-1 node : world t_xml_node c251( "world", "earth" ); c25.insert_child(c251); // child 2-5-2 node : xcord t_xml_node c252( "xcord", "118" ); c25.insert_child(c252); // child 2-5-3 node : ycord t_xml_node c253( "ycord", "493" ); c25.insert_child(c253); // child 2-5-4 node : zcord t_xml_node c254( "zcord", "38" ); c25.insert_child(c254); // child 2-5-5 node : xyangle t_xml_node c255( "xyangle", "25" ); c25.insert_child(c255); // child 2-5-6 node : xzangle t_xml_node c256( "xzangle", "0" ); c25.insert_child(c256); // child 2-5 node : position (end) c2.insert_child(c25); // child 2-6 node : health t_xml_node c26( "health", "50" ); c2.insert_child(c26); // child 2-7 node : mana t_xml_node c27( "mana", "22" ); c2.insert_child(c27); // child 2 node : player (end) root.insert_child(c2); // build XML file/stream cout << root.build() << endl; } { // example 2.1.1 : // // player_list (number_of_players : 2) // +---> player (id : 0001) // | +---> name : xterm-in-hate // | +---> level : 39 // | +---> class : berseker // | +---> experience : 8012 // | +---> position // | | +---> world : earth // | | +---> xcord : 111 // | | +---> ycord : 452 // | | +---> zcord : 37 // | | +---> xyangle : 162 // | | +---> xzangle : -9 // | +---> health : 120 // | +---> mana : 270 // +---> player (id : 0002) // . +---> name : guest // . +---> level : 1 // . +---> class : paladin // . +---> experience : 0 // . +---> position // . | +---> world : earth // . | +---> xcord : 118 // . | +---> ycord : 493 // . | +---> zcord : 38 // . | +---> xyangle : 25 // . | +---> xzangle : 0 // . +---> health : 50 // . +---> mana : 22 cout << "EXAMPLE#2.1.1" << endl; // root node : player list t_xml_node root( "player_list", "" ); t_xml_manip m( root ); // root node : player list m.mk("/player_list/.number_of_players"); m("/player_list/.number_of_players") = "2"; // player 1 m.mk("/player_list/player"); m.mk("/player_list/player:0/.id"); m("/player_list/player:0/.id") = "0001"; // player 1 name m.mk("/player_list/player:0/name"); m("/player_list/player:0/name") = "xterm-in-hate"; // player 1 level m.mk("/player_list/player:0/level"); m("/player_list/player:0/level") = "39"; // player 1 class m.mk("/player_list/player:0/class"); m("/player_list/player:0/class") = "berseker"; // player 1 experience m.mk("/player_list/player:0/experience"); m("/player_list/player:0/experience") = "8012"; // player 1 position m.mk("/player_list/player:0/position"); m.mk("/player_list/player:0/position/world"); m("/player_list/player:0/position/world") = "earth"; m.mk("/player_list/player:0/position/xcord"); m("/player_list/player:0/position/xcord") = "111"; m.mk("/player_list/player:0/position/ycord"); m("/player_list/player:0/position/ycord") = "452"; m.mk("/player_list/player:0/position/zcord"); m("/player_list/player:0/position/zcord") = "37"; m.mk("/player_list/player:0/position/xyangle"); m("/player_list/player:0/position/xyangle") = "162"; m.mk("/player_list/player:0/position/xzangle"); m("/player_list/player:0/position/xzangle") = "-9"; // player 1 health m.mk("/player_list/player:0/health"); m("/player_list/player:0/health") = "120"; // player 1 mana m.mk("/player_list/player:0/mana"); m("/player_list/player:0/mana") = "270"; // player 2 m.mk("/player_list/player"); m.mk("/player_list/player:1/.id"); m("/player_list/player:1/.id") = "0002"; // player 2 name m.mk("/player_list/player:1/name"); m("/player_list/player:1/name") = "guest"; // player 2 level m.mk("/player_list/player:1/level"); m("/player_list/player:1/level") = "1"; // player 2 class m.mk("/player_list/player:1/class"); m("/player_list/player:1/class") = "paladin"; // player 2 experience m.mk("/player_list/player:1/experience"); m("/player_list/player:1/experience") = "0"; // player 2 position m.mk("/player_list/player:1/position"); m.mk("/player_list/player:1/position/world"); m("/player_list/player:1/position/world") = "earth"; m.mk("/player_list/player:1/position/xcord"); m("/player_list/player:1/position/xcord") = "118"; m.mk("/player_list/player:1/position/ycord"); m("/player_list/player:1/position/ycord") = "493"; m.mk("/player_list/player:1/position/zcord"); m("/player_list/player:1/position/zcord") = "38"; m.mk("/player_list/player:1/position/xyangle"); m("/player_list/player:1/position/xyangle") = "25"; m.mk("/player_list/player:1/position/xzangle"); m("/player_list/player:1/position/xzangle") = "0"; // player 2 health m.mk("/player_list/player:1/health"); m("/player_list/player:1/health") = "50"; // player 2 mana m.mk("/player_list/player:1/mana"); m("/player_list/player:1/mana") = "22"; // build XML file/stream cout << root.build() << endl; } ///////////////////////////////////////////////////////////////////////////// // CECI EST UN APPERCU DU CODE ZIPPE.... /////////////////////////////////////////////////////////////////////////////
21 août 2008 à 22:40
quand à la suppression des enfants, j'ai ajouté la fonction à partir d'un std::for_each, je prendrai la nouvelle version de minxl lorsqu'elle sera disponible et je m'adapterai
vu que ça fonctionne bien je suis passé à autre chose niveau programme
cordialement,
Shenron
21 août 2008 à 17:55
MinXL utilise le gestionnaire d'exception afin de faciliter le traitement d'un fichier XML anormal / corrompu. A mon sens, tu ne devrais donc avoir qu'un seul et unique bloc try-catch, encadrant l'appel à la fonction de "configuration" de ton application.
A partir de ce point, on suppose le fichier XML parfaitement intègre et valide. Pour simplifier l'interprétation du fichier XML par l'application, on prendra soin de choisir une structuration XML systématique. Ainsi, aucun traitement d'exception n'est a implémenter au moment de l'analyse du fichier XML.
Par exemple, le noeud <drives> comprendra un certains nombre de fils <drive> et seulement <drive>, comprenant tous un attribut "data" (renseigné ou vide). Le noed <drive> comprendra un certain nombre de fils <select>, comprenant tous un attribut "label" (renseigné ou vide). Etc.
Par conséquent, en prenant soin d'utiliser les fonctions membres child_at( size_t ), nb_children(), attribute_at( size_t ) et nb_attributes(), aucune exception ne sera levée par MinXL. Cela tend à simplifier le code la fonction "configuration" de cette application.
Pour gérer les exceptions au fil de l'analyse du fichier, dans le but de résister à une corruption partielle du fichier XML, je ne vois pas d'autre solution que de gérer les exceptions à chaque appel à MinXL avec un bloc try-catch dédié. L'autre technique serait d'utiliser le principe du C avec un retour de fonction à 0 et une fonction globale du genre get_error() afin d'obtenir une information détaillée sur la nature de l'erreur...
Effectivement, il manque une fonction pour supprimer tous les enfants d'un noeud, par exemple remove_childS(). Pour l'instant, c'est à l'utilisateur de MinXL d'implémenter une éventuelle boucle. En outre, il n'y a pas d'autre solution que de faire un boucle pour supprimer les fils un par un. Néanmoins, il est possible d'utiliser la fonction remove_child() sur le père du noeud dont on veut supprimer les fils. Attention, cela supprime également le noeud en question.
Je vais réfléchir à intégrer la fonction remove_childs() et remove_attributes() dans une prochaine révision de MinXL.
Je suis preneur de proposition pour une gestion plus souple des exceptions.
Cordialement,
Xterminhate.
21 août 2008 à 10:17
par contre, personnellement je trouve que gérer tous les échecs avec des exceptions alourdit énormément le code qui devient vite illisible
si on ne veux pas sortir de la lecture de l'arbre xml juste parcequ'un élément non critique n'a pas été trouvé on est obligé d'imbriquer des try catch à la pelle
à titre d'exemple, gérer la lecture de cet arbre xml :
<?xml version="1.0" encoding="ISO-8859-1"?>
<mediaterface>
<drives>
<drive label="[DRV]Programmation" data="d:/Programmation">
<select label="[DIR]Code::Blocks">
<select label="[DIR]MinGW">
<select label="[Dir]Includes">
</drive>
</drives>
</mediaterface>
"drive" est un lecteur et les "select" servent à mémoriser le dernier emplacement parcouru
pour récupérer tout ça en code j'ai fait ceci :
// load configuration file
m_XmlFile.parse_from_file("test.xml");
try
{
// parse the xml tree
MinXL::t_xml_node drives = m_XmlFile.child_at("drives");
for(size_t nDriveNb=0; nDriveNb < drives.nb_children(); ++nDriveNb)
{
MinXL::t_xml_node drive = drives.child_at(nDriveNb);
if(drive.key() != "drive")
continue;
try
{
// create the drive
CPathElementPtr drv = new CPathElement(CPathElement::eFolder, drive.attribute_value_at("label"), drive.attribute_value_at("data"), m_Root);
// add the new drive to the root
m_Root->Add(drv);
drv->UpdateChildren();
std::stringvector arSelection;
try
{
for(size_t nSelectNb=0; nSelectNb < drive.nb_children(); ++nSelectNb)
{
MinXL::t_xml_node select = drive.child_at(nSelectNb);
if(select.key() != "select")
continue;
arSelection.push_back(select.attribute_value_at("label"));
}
}
catch(std::exception e)
{
}
drv->SetSelection(arSelection);
}
catch(std::exception e)
{
continue;
}
}
}
catch(std::exception e)
{
}
si un élément n'est pas trouvé, je ne veux pas tout arrêter
je ne pense pas que je puisse m'en sortir autrement ?
Autre chose aussi, il manque une méthode pour supprimer tous les enfants d'un noeud
coller un foreach pour supprimer tous les enfants n'est pas très propre et pour des gros fichier ça risque de plomber les perfs
19 août 2008 à 18:48
tinyxml est aussi plus lourd côté code généré, mais on trouve plus facilement des tutos et surtout une doc doxygen
minxl mériterait une page dédiée avec tout ce qu'il faut pour l'utiliser sans se prendre la tête à plonger dans le code
en tout cas, merci pour votre aide, je vais adapter mon programme et voir quelle bibliothèque me convient le mieux ;)
19 août 2008 à 11:22
Je crée un nouveau projet C++. J'ajoute les fichiers xml.hpp et .cpp. J'écris le code source suivant :
#include
using namespace std;
#include "xml.hpp"
int main()
{
MinXL::t_xml_node root;
root.parse_from_file( "test.xml" );
MinXL::t_xml_node drives = root.child_at("drives");
size_t drive_count = drives.nb_children();
cout << drive_count << " drives!" << endl;
for( size_t index = 0; index != drive_count; ++index )
cout << "Drive #" << index << " = " << drives.child_at(index).attribute_value_at("data") << endl;
return 0;
}
J'obtiens l'affichage suivant :
3 drives!
Drive #0 = //nas/sources
Drive #1 = //nas/demos
Drive #2 = d:/jeux
Process returned 0 (0x0) execution time : 0.015 s
Press any key to continue.
CQFD.
Pour utiliser TinyXML, il faut vraiment aimer les pointeurs dans tous les sens... ^^
Cordialement,
Xterminhate.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.