- Piccolo
- Semplice
- Facile da includere nel nostro progetto
Nel mondo Open Source, putroppo, almeno una di queste tre caratteristiche è spesso assente. Vi segnalo però TinyXML, una libreria C++ veramente minuta che mantiene quel che promette.
Step 1) Scarichiamo TinyXML e includiamola nel nostro progetto C++
Il download è uno zip contenente due header e quattro file di codice. Non vi sono binari. Eh, ma allora è da ricompilare! Non proprio. Cioè, liberi di farlo, ma potete semplicemente includere i file nel vostro progetto: non richiederanno flag o altre impostazioni aggiuntive per la compilazione. Se proprio non vi va di avere qualche Kb di sorgente di terzi potete sempre creare una libreria statica (.a o .lib) e includere poi quella. Personalmente preferisco il primo metodo.
Step 2) Utilizziamo TinyXML
Tutto quel che occorre per accedere alle classi della libreria è contenuto in tinyxml.h, da cui:
#include “tinyxml.h”
La documentazione online offre numerosi esempi d’uso, ma si concentra più sulla creazione di nuovi documenti che sulla lettura di documenti esistenti. Scelta dell’autore, ma credo sia esigenza più frequente la seconda che non la prima. Inoltre, la ricchezza degli esempi può al tempo stesso risultare spaesante. In questo tutorial vediamo quindi come aprire un documento in lettura ed esplorarne la struttura. Il documento di esempio ha questa forma:
<items> <item id=”1”> <name>Item01</name> </item> <item id=”2”> <name>Item02</name> </item> </items>
La nostra root è il nodo
items
, che contiene una serie di elementi item
. Ogni elemento item
ha un attributo id
e una proprietà name
.NB: TinyXML, per mantenere la sua semplicità, deve compiere qualche rinuncia. Una di queste è il supporto ai DTD, quindi non abbiamo strumenti per verificare la validità formale del nostro XML.
Vediamo ora come fare per aprire il nostro file (items.xml) e andare a beccare l’item con id 2 per stamparne a video il nome.
TiXmlDocument doc("items.xml"); if(doc.LoadFile()) { TiXmlElement* root = doc.RootElement(); TiXmlNode* item_node = root->IterateChildren(null); while( item_node ) { TiXmlElement* item_element = item_node->ToElement(); int item_id = 0; item_element->QueryIntAttribute("id", &item_id); if(item_id == 2) { // stampo a video il valore name di questo nodo TiXmlElement* name_property = item_element->FirstChild(“name”)->ToElement(); std::cout << name_property->GetText() << endl; // ed esco dal while break; } item_node = root->IterateChildren( item_node ); } }
TiXmlDocument
è la classe principale della libreria. Sintetizza il nostro documento xml fisico, il cui path è richiesto nel costruttore. Il metodo LoadFile
è autoesplicativo e ha un booleano come valore di ritorno per verificare che l’operazione sia andata a buon fine.Una volta che il nostro documento xml è caricato in memoria nell’oggetto doc, possiamo iniziare a giocare con i metodi della classe. In particolare dobbiamo accedere alla root (
RootElement()
), ottenere il primo dei nodi figli (IterateChildren(null)
) e iniziare ad iterare tra tutti i figli di root finchè non troviamo quello che ci interessa. La IterateChildren
accetta in input il puntatore al nodo corrente e restituisce il nodo successivo, o null
in assenza di ulteriori nodi. Nella nostra prima chiamata le passiamo null
, ad indicare che vogliamo accedere al primo elemento. Le chiamate successive (ultima istruzione del while
) contengono invece il puntatore all’elemento corrente.La prima istruzione del
while
è un cast da TiXmlNode*
a TiXmlElement*
, una specializzazione di TiXmlNode
che ne estende le funzionalità. La documentazione dei due metodi è il posto migliore in cui scoprire le differenze e magari sbirciare l’albero di ereditarietà.TiXmlElement
ha diversi metodi per leggere un attributo, in particolare per interpretarne il valore secondo un tipo predefinito. Nel nostro caso gli id sono tutti interi, quindi usiamo senza timori QueryIntAttribute
, che necessita di un puntatore ad intero per restituire il risultato della lettura.Una volta raggiunto il nodo con l’id che ci interessa usiamo il metodo
FirstChild(const char* value)
per accedere al primo nodo figlio con il nome specificato: name
, nel nostro caso. Otteniamo quindi il relativo puntatore e accediamo al testo tramite GetText()
, stampando il valore di name a video con una buona vecchia cout
.Buon coding!
Riferimenti:
TinyXML home
Nessun commento:
Posta un commento