source: XMLIO_V2/dev/dev_rv/old/xml_parser.hpp @ 90

Last change on this file since 90 was 90, checked in by hozdoba, 14 years ago

Ancienne Version de parsing.

File size: 14.4 KB
Line 
1#ifndef __XML_PARSER__
2#define __XML_PARSER__
3
4#include "xmlio_std.hpp"
5
6/// HISTORIQUE ///
7// <RV> 20/04/10 - 23/04/10 : Nouvelle implémentation parsing, création de la classe principale XmlIOServer::XML::XMLParser.
8// <RV> 23/04/10            : Création de la classe abstraite XmlIOServer::XML::XMLElement + ajout de quelques commentaires.
9// <RV> 26/04/10            : Ajout de la gestion simplifiée des héritages descendants + gestion des flux de sortie.
10// <RV> 29/04/10            : Ajout de la gestion simplifiée des attributs par défaut.
11// <RV> 30/04/10            : Création et Vérification de la classe de test XML XmlIOServer::XML::XMLClassTest.
12// <RV> 03/05/10            : Nouvelle implémentation classe de test + ajout de tous les commentaires.
13// <RV> 04/05/10            : Suppression documentation excessive + correction de 2 problÚmes de parsing sur situations particuliÚres non gérées.
14
15/**
16 * \file  XMLParser.hpp
17 * \brief Ce fichier contient le code source permettant de parser un fichier de configuration xml pour le serveur d'E/S.
18 * \author Ozdoba Hervé (contact: herve.ozdoba@glsce.ipsl.fr)
19 * \author Meurdesoif Yann (contact Yann.Meurdesoif@cea.fr)
20 * \version 0.1.0
21 * \date Avril - Mai  2010
22 */
23
24// Utilisation de la STL
25using std::string;
26
27using std::pair;
28using std::vector;
29using std::deque;
30
31using std::ifstream;
32using std::ostream;
33
34// Utilisation de la biliothÚque POCO
35using Poco::XML::DOMParser;
36using Poco::XML::InputSource;
37
38using Poco::XML::Document;
39using Poco::XML::Node;
40using Poco::XML::Element;
41
42using Poco::XML::NamedNodeMap;
43
44//using Poco::XML::AutoPtr;
45
46using Poco::Exception;
47using Poco::HashMap;
48
49/**
50 * \namespace XmlIOServer
51 * \brief Cet espace de nommage regroupe l'intégralité des classes du serveur des E/S.
52 * \see XmlIOServer::XML
53 *
54 * Espace de nommage général qui regroupe toutes les classes dont dépend le serveur de gestion des entrées/sorties
55 * parallÚles avec configuration par fichier de données xml.
56 */
57namespace XmlIOServer
58{
59        /**
60         * \namespace XmlIOServer::XML
61         * \brief Cet espace de nommage contient les classes permettant de parser le fichier de configuration XML.
62         */
63        namespace XML
64        {
65                /**
66                 * \typedef pair<string, string> TAttribute
67                 * \brief Définition d'un type pair associant un nom d'attribut à sa valeur.
68                 * \see TListAttributes
69                 *
70                 * Ce type permet de récupérer une pair contenant :
71                 * \li Le nom de l'attribut;
72                 * \li La valeur associée à l'attribut sous forme de chaîne de caractÚres.
73                 */
74                typedef pair<string, string> TAttribute;
75
76                /**
77                 * \typedef HashMap<string, string> THashAttributes
78                 * \brief Définition d'une HashMap de TAttribute.
79                 * \see TAttribute
80                 */
81                typedef HashMap<string, string> THashAttributes;
82               
83                /**
84                 * \enum TNodeType
85                 * \brief Définition d'un type de noeud xml.
86                 */
87                typedef enum 
88                {
89                        UNKNOWN = 0, CONTEXT = 1,
90                        FIELD_GROUP = 2, FILE_GROUP = 3, AXIS_GROUP = 4, GRID_GROUP = 5,
91                        FIELD = 6, FILE = 7, AXIS = 8, GRID = 9
92                       
93                } TNodeType;
94               
95                /**
96                 * \struct XmlIOServer::XML::_element
97                 * \brief  Association d'un type de noeud avec un HashMap des attributs qui lui sont associés.
98                 */
99               
100                /**
101                 * \typedef struct XmlIOServer::XML::_element TElement
102                 * \brief Redéfinition du type _element pour simplification d'écriture.
103                 * \see _element
104                 */
105                typedef struct _element
106                {
107                        /**
108                         * \fn _element(TNodeType t, THashAttributes& l)
109                         * \brief Simple constructeur du structure.
110                         * \param t Un type d'élément.
111                         * \param l Une HashMap d'attributs associé  à l'élément.
112                         */
113                        _element(TNodeType t, THashAttributes& l) : type(t),list(l)
114                         { /* Ne rien faire de plus */};
115                       
116                        /**
117                         * \var TNodeType type
118                         * \brief Type d'élément.
119                         */
120                        TNodeType type; 
121                       
122                        /**
123                         * \var THashAttributes list
124                         * \brief HashMap d'attributs.
125                         */                     
126                        THashAttributes list; //< HashMap d'attributs.
127                       
128                } TElement;
129               
130       
131                /**
132                 * \typedef deque<TElement> TListElements
133                 * \brief Liste de TElement utilisée comme pile pour la gestion (optionnelle)
134                 *      de l'héritage descendant dans la classe de parsing xml.
135                 * \see XmlIOServer::XML::XMLParser::path
136                 */
137                typedef deque<TElement> TListElements;
138
139                /**
140                 * \typedef Document* PDocument
141                 * \brief Redéfinition du pointeur sur document xml pour simplification d'écriture.
142                 */
143                typedef Document*       PDocument;
144               
145                /**
146                 * \typedef Node* PNode
147                 * \brief Redéfinition du pointeur sur noeud xml pour simplification d'écriture.
148                 * \see XmlIOServer::XML::cNode
149                 */
150                typedef Node*           PNode;
151               
152                /**
153                 * \class XMLElement
154                 * \brief Classe abstraite pour parsing xml.
155                 * \see XmlIOServer::XML::XMLParser
156                 *
157                 * Les classes susceptibles d'être instanciées par parsing Xml doivent hériter des fonctions de celle-ci pour être
158                 * traoter par la classe XMLParser.
159                 */
160                class XMLElement
161                {
162                        public :
163                       
164                                // TODO ? Enlever le param. name serait une bonne chose ?
165                                /**
166                                 * \fn XMLElement* addChild(TNodeType type, string name, THashAttributes& attr)
167                                 * \brief Fonction appelée par XMLParser signifiant l'ajout d'un fils à l'élément actuel.
168                                 * \param type le type du noeud à ajouter.
169                                 * \param name le nom du noeud à ajouter (lié au paramêtre <i>type</i>)
170                                 * \param attr une HashMap des attributs associés à l'élément à ajouter.
171                                 * \return Un pointeur sur l'élément fils nouvellement créé.
172                                 */
173                                virtual XMLElement* addChild(TNodeType type, TListElements& path, THashAttributes& attr) = 0;
174                               
175                                               
176                                /**
177                                 * \fn XMLElement* getPReference(void)
178                                 * \brief Renvoie la référence au noeud parent e l'élément actuel.
179                                 * \return la référence au noeud parent.
180                                 *
181                                 */
182                                virtual XMLElement* getPReference(void) = 0;
183                                                       
184                }; // class XMLElement
185               
186                /**
187                 * \class XMLClassTest
188                 * \brief Une classe de test pour le parsing xml.
189                 * 
190                 * Une simple classe de test qui écrit les arguments reçus lors du parsing vers la console.
191                 */             
192                class XMLClassTest : public XMLElement
193                {
194                        public:
195                       
196                                /**
197                                 * \fn XMLClassTest()
198                                 * \brief Simple constructeur d'initialisation d'un élément racine.
199                                 */
200                                XMLClassTest(XMLElement* ref = NULL)
201                                {
202                                        this->pref = ref;
203                                        //std::cout << "[simulation]" << std::endl;
204                                }
205                       
206                                /**
207                                 * \fn XMLClassTest(XMLClassTest* ref, TNodeType type, string& name, THashAttributes& attr)
208                                 * \brief Constructeur pour tout autre élément que celui de la racine.
209                                 * \param ref Référence à l'élement parent (théorique, celui qui appelle le constructeur via la méthode addChild).
210                                 * \param type Le type du noeud à instancier.
211                                 * \param name Le nom du noeud à instancier.
212                                 * \param attr Une HashMap des attributs liés au noeud à instancier.
213                                 */
214                                XMLClassTest(XMLClassTest* ref, TNodeType type, THashAttributes& attr)
215                                {
216                                        this->pref = ref;
217                                        //for(int i = 0; i<INC; i++) std::cout << "  ";
218                                        /*std::cout << "[" << type;
219                                       
220                                        for (THashAttributes::Iterator it = attr.begin(); it != attr.end(); it++)
221                                                std::cout << " "<< (*it).first<< "=\"" << (*it).second << "\"";
222                                               
223                                        std::cout << "]" << std::endl;*/
224                                }
225                               
226                                friend ostream& operator<< (ostream& out, const XMLClassTest& c)
227                                { out << "[Non implémentée]" << std::endl; return out; }
228                               
229                                virtual XMLClassTest* addChild(TNodeType type, TListElements& path, THashAttributes& attr) 
230                                { INC++; return (new XMLClassTest(this, type, attr)); }
231                               
232                                virtual XMLElement* getPReference(void) { INC--; return (this->pref); }
233                               
234                                /**
235                                 * \fn ~XMLClassTest()
236                                 * \brief Simple destructeur.
237                                 */
238                                ~XMLClassTest() { /* Ne rien faire de plus */ }
239                               
240                        protected:
241                       
242                        private:
243                       
244                                /**
245                                 * \var XMLClassTest* pref
246                                 * \brief Référence au parent de l'élÚment actuel (NULL si on se trouve à la racine).
247                                 */
248                                XMLElement* pref; // TODO Vérifier la gestion de la mémoire.
249                               
250                                /**
251                                 * \var int INC
252                                 * \brief Entier permettant de connaître le niveau d'incrémentation pour l'écriture sur la sortie standard.
253                                 */
254                                static int INC;
255                               
256                }; // class XMLClassTest
257               
258                int XMLClassTest::INC = 0;
259
260                /**
261                 * \class XMLParser
262                 * \brief Classe qui initie le parsing d'un fichier de configuration Xml.
263                 *
264                 * Cette classe permet de parser un document XML afin de configurer le serveur des E/S.\n
265                 * Cette méthode de récupération des paramÚtres est statique puisque le traitement est effectué une fois au
266                 * démarrage du serveur.\n Elle est complémentaire d'une seconde méthode, dynamique cette fois, consistant à paramétrer
267                 * l'application par remoting client-serveur à travers MPI.
268                 */
269                class XMLParser
270                {
271                        public :
272
273                                XMLParser(const string& filename, const string& rootName = string("simulation"))
274                                { 
275                                        XMLParser();
276                                        ifstream istr( filename.data() , ifstream::in );
277                                        if ((istr.good()))
278                                        { // S'il est possible de lire le flux en entrée ...
279                                                InputSource src(istr);
280                                                DOMParser parser;
281
282                                                // On parse la source XML et on vérifie que le premier noeud (racine) est du type "Element"
283                                                // ... et à pour valeur la chaîne rootName.
284                                                PDocument pDoc = parser.parse(&src);
285                                                if (!(pDoc->documentElement()->nodeName().compare(rootName)))
286                                                {
287                                                        this->cNode = pDoc->documentElement();
288                                                        this->goToChildElement();
289                                                }
290                                                else
291                                                        std::cout       << "L'élément racine doit avoir pour valeur <"<< rootName <<"> (\""
292                                                                                <<  (pDoc->documentElement()->nodeName()) <<"\" lue)"<< std::endl;
293       
294                                        }
295                                        else
296                                                std::cout << "Impossible de lire le flux du fichier en entrée !" << std::endl;
297                                }
298
299                               
300                                void parse(XMLElement* const root, ostream& log = std::cout)
301                                {
302                                        XMLElement* current = root;
303                                        THashAttributes attr;
304                                        bool start = true;
305                                       
306                                        do{
307                                                if(!start)path.pop_back();
308                                                while((start) ? start : this->goToNextElement()) // PARCOURS SUR ELEMENT SUIVANT
309                                                {
310                                                        // APPEL ADD PARENT
311                                                        if(!start)path.pop_back();
312                                                       
313                                                        this->getAttributes(attr);
314                                                        path.push_back(TElement(this->getElementType(), attr));
315                                                        current = current->addChild(this->getElementType(),this->getTreePath(), attr);
316                                                        attr.clear();
317                                                       
318                                                        while (this->goToChildElement()) // PARCOURS SUR ELEMENT ENFANT
319                                                        {
320                                                                // APPEL ADD LOCAL
321                                                                this->getAttributes(attr); // ou getGlobalAttributes pour gestion de l'héritage descendant.
322                                                                path.push_back(TElement(this->getElementType(), attr));
323                                                                current = current->addChild(this->getElementType(),this->getTreePath(), attr);
324                                                                attr.clear();
325                                                        }
326
327                                                        current = current->getPReference();
328
329                                                        if (start) start = false;                       
330                                                }
331                                               
332                                                if(current == root ) break; 
333                                                else current = current->getPReference();
334                                                                       
335                                        } while(this->goToParentElement()); // PARCOURS SUR ELEMENT PARENT
336                                       
337                                        return;
338                                }
339               
340                                ~XMLParser()
341                                { /* Ne rien faire pour le moment*/ }
342                               
343                                static void ClassTest(const char* path)
344                                {
345                                        try
346                                        {                                       
347                                                // Instanciation du parseur.
348                                                XMLParser parser(path);                                                                                 
349                                                // Instanciation de l'objet racine.
350                                                XMLClassTest root ; 
351                                       
352                                                // Début du parsing XML ...
353                                                parser.parse(&root);
354                                        }
355                                        catch (Exception& exc)
356                                        {
357                                                // TODO : Remplacer sorties vers cerr et cout par exception
358                                                std::cerr << (exc.displayText()) << std::endl;
359                                        }
360                                                                               
361                                        return;
362                                }
363                               
364                                TListElements& getTreePath() { return (this->path); }
365                                void setTreePath(const TListElements& p) { this->path = p; }
366
367                        protected :
368                               
369                                TNodeType getElementType(void) const 
370                                {
371                                        if(this->isElementName("context"))return (CONTEXT);
372                                       
373                                        // les groupes, quels qu'ils soient.
374                                        if(this->isElementName("field_definition") or this->isElementName("field_group"))return (FIELD_GROUP);
375                                        if(this->isElementName("file_definition")  or this->isElementName("file_group")) return (FILE_GROUP);
376                                        if(this->isElementName("axis_definition")  or this->isElementName("axis_group")) return (AXIS_GROUP);
377                                        if(this->isElementName("grid_definition")  or this->isElementName("grid_group")) return (GRID_GROUP);
378                                       
379                                        // les éléments finaux (hormis "file").
380                                        if(this->isElementName("field"))return (FIELD);
381                                        if(this->isElementName("file")) return (FILE);
382                                        if(this->isElementName("axis")) return (AXIS);
383                                        if(this->isElementName("grid")) return (GRID);
384                                       
385                                        return (UNKNOWN);
386                                }
387                               
388                                //////////////////////// PARSING //////////////////////////////
389
390                                // TODO voir pour récupérer une référence.
391                                string getElementName(void) const {return (this->cNode->nodeName());}
392                               
393                                bool isElementName(const char* val) const {return !(this->getElementName().compare(string(val)));}
394                               
395                                bool goToNextElement(Node* nextElement = 0) 
396                                {
397                                        nextElement = (!nextElement)? this->cNode->nextSibling() : nextElement;
398                                       
399                                        // On parcourt la liste des "siblings" jusqu'à trouver un élément quelconque.
400                                        for(; ; nextElement = nextElement->nextSibling())
401                                                if (nextElement == NULL) break;
402                                                else if (nextElement->nodeType() == 1)
403                                                {// Si l'un des noeuds est un élément...
404                                                        this->setCurrentNode(nextElement);
405                                                        return (true);
406                                                } 
407                                        return (false);
408                                }
409                               
410                                bool goToChildElement(void)
411                                {
412                                        // On parcourt la liste des enfants jusqu'à trouver un élément quelconque.
413                                        if (this->cNode->firstChild())
414                                                if (this->goToNextElement(this->cNode->firstChild()))
415                                                        return (true);
416                                                       
417                                        return (false);
418                                }
419                               
420                                bool goToParentElement(void)
421                                { 
422                                        // Pas de retour au parent si on est à la racine.
423                                        if (!(this->getElementName().compare(string("simulation")))) return (false);
424                                        this->setCurrentNode(this->cNode->parentNode());
425                                        return (true);
426                                }
427                               
428                                bool getAttributes(THashAttributes& attributes)
429                                {
430                                        if(!this->cNode->hasAttributes()) return (false);
431                                        NamedNodeMap* map = this->cNode->attributes();
432                                       
433                                        for(unsigned int i = 0; i< map->length(); i++)
434                                                attributes[map->item(i)->nodeName()] = map->item(i)->nodeValue();
435
436                                        return (true);
437                                }
438                               
439                        private :
440                       
441                                XMLParser() : path() //pDoc(), cNode() << Ancien
442                                { /* Ne rien faire de plus */ }
443                       
444                                bool setCurrentNode(PNode node){ if (!node) return false; this->cNode = node; return (true);}                           
445                                PNode getCurrentNode(void){return (this->cNode);}
446
447                                /**
448                                 * \var AElement cNode
449                                 * \brief Pointeur sur l'objet représentant l'élément courant.
450                                 */
451                                PNode  cNode;
452                               
453                                TListElements path;
454                                               
455                };// class XMLParser
456               
457        };// namespace XML
458       
459};// namespace XmlIOServer
460
461#endif //__XML_PARSER__
462
Note: See TracBrowser for help on using the repository browser.