Autore: Fabio Di Matteo
Ultima revisione: 19/09/2008
Libxml2 e' una libreria che si occupa dell'elaborazione dei file Xml .
Con essa si possono scrivere e leggere quindi file Xml.
Risorse:
http://student.santarosa.edu/~dturover/?node=libxml2
http://xmlsoft.org/tutorial/xmltutorial.pdf
Un file xml e' un file di testo formato da diversi nodi che assomigliano ai tag html. Un nodo xml e' qualcosa del genere:
<nodo attributo1="valore_attr1" attributo2="12345"> <nodo figlio>Hello World</nodo figlio> </nodo>
Le cose che si possono manipolare sono il nodo stesso, gli attributi del nodo e il contenuto del nodo.
Immaginiamo per esempio che il seguente file serva ad una qualche applicazione per prendere informazioni riguardo un articolo.
<?xml version="1.0"?> <articolo> <info> <autore>Fabio Di Matteo</autore> <data>01 Gennaio 1970</data> <titolo>Titolo articolo</titolo> </info> <body> <testo>Questo e' il testo dell'articolo.</testo> </body> </articolo>
Come vediamo esiste un tag (nodo) <articolo>
che e' la radice principale ovvero il tag piu' esterno (la root del file xml).
All'inerno della root abbiamo poi altri nodi principali come <info>
e <body>
. Dentro quest'ultimi infine gli elementi che racchiudono i dati. Sotto <info>
ci sono <autore>, <data>, <titolo>
, invece sotto <body>
c'e' solo <testo>
.
xmlChar* ReadXmlNodeContent(char* filename, xmlChar* root ,xmlChar* node, xmlChar* key ); void NewXmlNode(char* filename, xmlChar* root ,xmlChar* node, xmlChar* key, xmlChar *keyvalue ); void SetXmlNodeContent(char* filename, xmlChar* root ,xmlChar* node, xmlChar* key, xmlChar *keyvalue ); void DelXmlNode(char *filename, xmlChar* root ,xmlChar* node, xmlChar *key);
Scriveremo delle funzioni per scrivere e leggere i tag del file.
Ecco come potrebbero utilizzarsi le funzioni:
... /*Aggiunge un nuovo nodo dentro body di nome testo2 con il contenuto "iuppiieeeee"*/ NewXmlNode("file.xml", "articolo" ,"body", "testo2", "iuppiieeeee" ) ; /*Modifica il nodo data contenuto nel nodo info con il valore "31/10/1915" */ SetXmlNodeContent("file.xml", "articolo" ,"info", "data", "31/10/1915" ) ; /*Cancelliamo il nodo titolo contenuto nel nodo info*/ DelXmlNode(argv[1], "articolo", "info", "titolo" ); /*Stampa a video il contenuto del nodo autore che a sua volta e' figlio del nodo info*/ xmlChar *mykey = ReadXmlNodeContent("file.xml", "articolo" , "info", "autore" ); printf("Autore-->%s\n", mykey); ...
Per la lettura dei tag la funzione avra' il seguente prototipo
xmlChar* ReadXmlNodeContent(char* filename, xmlChar* root ,xmlChar* node, xmlChar* key );
Dove:
char* filename
e' il percorso del file xml;xmlChar* root
e' il nodo root (nel nostro caso <articolo>);xmlChar* node
e' il nodo della sottocategoria (nel nostro caso potrebbe essere <info> oppure <body>) ;xmlChar* key
e' invece ,finalmente ,la chiave che contiene i dati(nel nostro caso potrebbe essere <autore> <data> <titolo> per il nodo <info> oppure <testo> per il nodo <body>);
La funzione restituisce il valore della chiave xmlChar* key
sottoforma
di xmlChar*
che puo' essere trattato come qualsiasi puntatore a char.
Per la lettura dei tag la funzione avra' il seguente prototipo
void NewXmlNode(char* filename, xmlChar* root ,xmlChar* node, xmlChar* key, xmlChar *keyvalue );
Dove:
char* filename
e' il percorso del file xml;xmlChar* root
e' il nodo root (nel nostro caso <articolo>);xmlChar* node
e' il nodo della sottocategoria (nel nostro caso potrebbe essere <info> oppure <body>) ;xmlChar* key
e' ,la chiave che contiene i dati(nel nostro caso potrebbe essere <autore> <data> <titolo> per il nodo <info> oppure <testo> per il nodo <body>); xmlChar* keyvalue
e' il contenuto del nodo .
Per la modifica del contenuto di un nodo la funzione avra' il seguente prototipo
void SetXmlNodeContent(char* filename, xmlChar* root ,xmlChar* node, xmlChar* key, xmlChar *keyvalue );
Dove:
char* filename
e' il percorso del file xml;xmlChar* root
e' il nodo root (nel nostro caso <articolo>);xmlChar* node
e' il nodo della sottocategoria (nodo figlio) (nel nostro caso potrebbe essere <info> oppure <body>) ;xmlChar* key
e' invece la chiave che contiene i dati(nel nostro caso potrebbe essere <autore> <data> <titolo> per il nodo <info> oppure <testo> per il nodo <body>);
* xmlChar* keyvalue
e' il contenuto del nodo
Per eliminare un nodo serve una funzione come questa il seguente prototipo
void DelXmlNode(char *filename, xmlChar* root ,xmlChar* node, xmlChar *key);
Dove:
char* filename
e' il percorso del file xml;xmlChar* root
e' il nodo root (nel nostro caso <articolo>);xmlChar* node
e' il nodo della sottocategoria (nodo figlio) (nel nostro caso potrebbe essere <info> oppure <body>) ;xmlChar* key
e' invece la chiave che contiene i dati(nel nostro caso potrebbe essere <autore> <data> <titolo> per il nodo <info> oppure <testo> per il nodo <body>); #include <stdio.h> #include <string.h> #include <stdlib.h> #include <libxml/xmlmemory.h> #include <libxml/parser.h> /*prototipo funzioni ausiliarie (vedi in fondo)*/ xmlChar* ReadParseNode (xmlDocPtr doc, xmlNodePtr cur,xmlChar *key) ; void AddParseNode (xmlDocPtr doc, xmlNodePtr cur, char *key, char* keyvalue) ; void SetParseNode (xmlDocPtr doc, xmlNodePtr cur, xmlChar *key, xmlChar* keyvalue) ; void DelParseNode (xmlDocPtr doc, xmlNodePtr cur, xmlChar *key); /*Prototipi funzioni principali*/ xmlChar* ReadXmlNodeContent(char* filename, xmlChar* root ,xmlChar* node, xmlChar* key ); void NewXmlNode(char* filename, xmlChar* root ,xmlChar* node, xmlChar* key, xmlChar *keyvalue ); void DelXmlNode(char *filename, xmlChar* root ,xmlChar* node, xmlChar *key); void SetXmlNodeContent(char* filename, xmlChar* root ,xmlChar* node, xmlChar* key, xmlChar *keyvalue ); xmlChar* ReadXmlNodeContent(char* filename, xmlChar* root ,xmlChar* node, xmlChar* key ){ /* Variabili che ci servono*/ xmlDocPtr doc; xmlNodePtr cur; //nodo da cui si comincia a cercare xmlChar *value; //valore di ritorno della funzione /* Verifichiamo se il file xml e' conforme*/ doc = xmlParseFile(filename); if (doc == NULL ) { fprintf(stderr,"Non e' stato possibile interpretare il file xml. \n"); return ; } /* Ricaviamo il nodo radice del file xml (root node)*/ cur = xmlDocGetRootElement(doc); if (cur == NULL) { fprintf(stderr,"Documento vuoto!\n"); xmlFreeDoc(doc); return; } /* Verifichiamo che esista un nodo root con il nostro nome*/ if (xmlStrcmp(cur->name, root)) { fprintf(stderr,"Errore nel formato del file xml\n"); xmlFreeDoc(doc); return; } /* Adesso partendo da il nodo "node" scandisce i solo nodi contenuti in esso * finche non trova la chiave di nome "key" vedi proptotipo funzione. */ cur = cur->xmlChildrenNode; while (cur != NULL) { if ((!xmlStrcmp(cur->name,(const xmlChar *) node ))){ /* funzione d'appoggio, per non appesantire il codice * dove doc e' il puntatore al file xml, cur e' la posizione * del nodo corrente, key e' il nome della chiave e keyvalue */ value = ReadParseNode (doc, cur,key ); return value; } cur = cur->next; } /*Scarichiamo dalla memoria cio' che non serve*/ xmlFreeDoc(doc); /*ritorniamo il valore della funzione*/ return value; } void NewXmlNode(char* filename, xmlChar* root ,xmlChar* node, xmlChar* key, xmlChar *keyvalue ) { /* Variabili che ci servono*/ xmlDocPtr doc; xmlNodePtr cur; //nodo da cui si comincia a cercare /* Verifichiamo se il file xml e' conforme*/ doc = xmlParseFile(filename); if (doc == NULL ) { fprintf(stderr,"Non e' stato possibile interpretare il file xml. \n"); return ; } /* Ricaviamo il nodo radice del file xml (root node)*/ cur = xmlDocGetRootElement(doc); if (cur == NULL) { fprintf(stderr,"Documento vuoto!\n"); xmlFreeDoc(doc); return; } /* Verifichiamo che esista un nodo root con il nostro nome*/ if (xmlStrcmp(cur->name, root)) { fprintf(stderr,"Errore nel formato del file xml\n"); xmlFreeDoc(doc); return; } /* Adesso partendo da il nodo "node" scandisce i solo nodi contenuti in esso * finche non trova la chiave di nome "key" vedi proptotipo funzione. */ cur = cur->xmlChildrenNode; while (cur != NULL) { if ((!xmlStrcmp(cur->name,(const xmlChar *) node ))){ /* funzione d'appoggio, per non appesantire il codice * dove doc e' il puntatore al file xml, cur e' la posizione * del nodo corrente, key e' il nome della chiave e keyvalue * il valore della chiave*/ AddParseNode (doc, cur,key, keyvalue ); } cur = cur->next; } /*Salviamo il file*/ xmlSaveFormatFile (filename, doc, 1); /*Scarichiamo dalla memoria cio' che non serve*/ xmlFreeDoc(doc); return ; } void DelXmlNode(char *filename ,xmlChar* root ,xmlChar* node, xmlChar *key){ /* Variabili che ci servono*/ xmlDocPtr doc; xmlNodePtr cur; //nodo da cui si comincia a cercare /* Verifichiamo se il file xml e' conforme*/ doc = xmlParseFile(filename); if (doc == NULL ) { fprintf(stderr,"Non e' stato possibile interpretare il file xml. \n"); return ; } /* Ricaviamo il nodo radice del file xml (root node)*/ cur = xmlDocGetRootElement(doc); if (cur == NULL) { fprintf(stderr,"Documento vuoto!\n"); xmlFreeDoc(doc); return; } /* Verifichiamo che esista un nodo root con il nostro nome*/ if (xmlStrcmp(cur->name, root)) { fprintf(stderr,"Errore nel formato del file xml\n"); xmlFreeDoc(doc); return; } /* Adesso partendo da il nodo "node" scandisce i solo nodi contenuti in esso * finche non trova la chiave di nome "key" vedi proptotipo funzione. */ cur = cur->xmlChildrenNode; FILE* fxml; while (cur != NULL) { if ((!xmlStrcmp(cur->name,(const xmlChar *) node ))){ /* funzione d'appoggio, per non appesantire il codice * dove doc e' il puntatore al file xml, cur e' la posizione * del nodo corrente, key e' il nome della chiave e keyvalue */ DelParseNode (doc, cur, key); } cur = cur->next; } /*Salviamo il file*/ xmlSaveFormatFile (filename, doc, 1); /*Scarichiamo dalla memoria cio' che non serve*/ xmlFreeDoc(doc); } /* Queste sono funzioni ausiliarie alle funzioni principali , non sono da usarsi da sole. * Potevano comunque essere accorpate dentro le funzioni principali, ma per non appesantirle abbiamo * deciso di tenerle fuori proprio come nel tutorial ufficiale*/ xmlChar* ReadParseNode (xmlDocPtr doc, xmlNodePtr cur,xmlChar *key) { /*Variabile di ritorno della funzione */ xmlChar *value; /*Nodo da cui si comincia a cercare*/ cur = cur->xmlChildrenNode; /* Individua la chiave contenuta nel nodo cur e ne restituisce il valore * grazie alla variabile "cur" */ while (cur != NULL) { if ((!xmlStrcmp(cur->name, (const xmlChar *) key))) { value = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); } cur = cur->next; } return value; } void SetXmlNodeContent(char* filename, xmlChar* root ,xmlChar* node, xmlChar* key, xmlChar *keyvalue ){ /* Variabili che ci servono*/ xmlDocPtr doc; xmlNodePtr cur; //nodo da cui si comincia a cercare /* Verifichiamo se il file xml e' conforme*/ doc = xmlParseFile(filename); if (doc == NULL ) { fprintf(stderr,"Non e' stato possibile interpretare il file xml. \n"); return ; } /* Ricaviamo il nodo radice del file xml (root node)*/ cur = xmlDocGetRootElement(doc); if (cur == NULL) { fprintf(stderr,"Documento vuoto!\n"); xmlFreeDoc(doc); return; } /* Verifichiamo che esista un nodo root con il nostro nome*/ if (xmlStrcmp(cur->name, root)) { fprintf(stderr,"Errore nel formato del file xml\n"); xmlFreeDoc(doc); return; } /* Adesso partendo da il nodo "node" scandisce i solo nodi contenuti in esso * finche non trova la chiave di nome "key" vedi proptotipo funzione. */ cur = cur->xmlChildrenNode; while (cur != NULL) { if ((!xmlStrcmp(cur->name,(const xmlChar *) node ))){ /* funzione d'appoggio, per non appesantire il codice * dove doc e' il puntatore al file xml, cur e' la posizione * del nodo corrente, key e' il nome della chiave e keyvalue * il valore della chiave*/ SetParseNode (doc, cur,key, keyvalue ); } cur = cur->next; } /*Salviamo il file*/ xmlSaveFormatFile (filename, doc, 1); /*Scarichiamo dalla memoria cio' che non serve*/ xmlFreeDoc(doc); return ; } void SetParseNode (xmlDocPtr doc, xmlNodePtr cur, xmlChar *key, xmlChar* keyvalue) { /* Modifica la chiave "key" con valore "keyvalue" nella posizione * "cur" */ /*Nodo da cui si comincia a cercare*/ cur = cur->xmlChildrenNode; /* Individua la chiave contenuta nel nodo cur e ne restituisce il valore * grazie alla variabile "cur" */ while (cur != NULL) { if ((!xmlStrcmp(cur->name, key))) { xmlNodeSetContent(cur,keyvalue ); } cur = cur->next; } return; } void DelParseNode (xmlDocPtr doc, xmlNodePtr cur, xmlChar *key) { /* Modifica la chiave "key" con valore "keyvalue" nella posizione * "cur" */ /*Nodo da cui si comincia a cercare*/ cur = cur->xmlChildrenNode; /* Individua la chiave contenuta nel nodo cur e ne restituisce il valore * grazie alla variabile "cur" */ while (cur != NULL) { if ((!xmlStrcmp(cur->next->name, key))) { /*qualcoca per cancellare il nodo*/ cur->next=NULL; } cur = cur->next; } return; } void AddParseNode (xmlDocPtr doc, xmlNodePtr cur, char *key, char* keyvalue) { /* Aggiunge la chiave "key" con valore "keyvalue" nella posizione * "cur" */ xmlNewTextChild (cur, NULL, key, keyvalue); return; } int main(int argc, char *argv[]){ /*Aggiunge un nuovo nodo dentro body di nome testo2 con il contenuto "iuppiieeeee"*/ NewXmlNode(argv[1], "articolo" ,"body", "testo2", "iuppiieeeee" ) ; /*Cancelliamo il nodo titolo contenuto nel nodo info*/ DelXmlNode(argv[1], "articolo", "info", "titolo" ); /*Modifica il nodo data contenuto nel nodo info con il valore "31/10/1915" */ SetXmlNodeContent(argv[1], "articolo" ,"info", "data", "31/10/1915" ) ; /*Stampa a video il contenuto del nodo autore che a sua volta e' figlio del nodo info*/ xmlChar *mykey = ReadXmlNodeContent(argv[1], "articolo" , "info", "autore" ); printf("Autore-->%s\n", mykey); return 0; }
Linkaggio a libxml2 dinamico
CPP = gcc OPTS = `xml2-config --cflags --libs` all: $(CPP) main.c -o main $(OPTS) clean: rm main
Il nostro wiki installa solamente cookie tecnici necessari al funzionamento della piattaforma "Dokuwiki". Niente analitics, statistiche, tracciamenti o altro.