
TinyXML 2.6.2 con correzioni per CVE-2021-42260 e CVE-2023-34194
/** @mainpage
TinyXML è un parser XML C++ semplice, piccolo e facilmente integrabile in altri programmi.
In breve, TinyXML analizza un documento XML e ne costruisce un Document Object Model (DOM) che può essere letto, modificato e salvato.
XML sta per "eXtensible Markup Language". Ti permette di creare i tuoi markup di documento. Mentre l'HTML fa un ottimo lavoro nel marcare i documenti per i browser, XML ti permette di definire qualsiasi tipo di markup di documento, ad esempio un documento che descrive una lista di "cose da fare" per un'applicazione organizer. XML è un formato molto strutturato e comodo. Tutti quei formati di file arbitrari creati per memorizzare dati di applicazioni possono essere sostituiti da XML. Un solo parser per tutto.
Il posto migliore per la specifica completa, corretta e, francamente, difficile da leggere è http://www.w3.org/TR/2004/REC-xml-20040204/. Un'introduzione a XML (che mi piace molto) si trova a http://skew.org/xml/tutorial.
Ci sono diversi modi per accedere e interagire con i dati XML. TinyXML usa un Document Object Model (DOM), il che significa che i dati XML vengono analizzati in oggetti C++ che possono essere esplorati e manipolati, e poi scritti su disco o su un altro stream di output. Puoi anche costruire un documento XML da zero con oggetti C++ e scriverlo su disco o su un altro stream di output.
TinyXML è progettato per essere facile e veloce da imparare. Si tratta di due header e quattro file cpp. Basta aggiungerli al tuo progetto e sei pronto per partire. C'è un file di esempio - xmltest.cpp - per iniziare.
TinyXML è rilasciato sotto la licenza ZLib, quindi puoi usarlo in codice open source o commerciale. I dettagli della licenza sono all'inizio di ogni file sorgente.
TinyXML cerca di essere un parser flessibile, ma con un output XML davvero corretto e conforme. TinyXML dovrebbe compilare su qualsiasi sistema ragionevolmente conforme al C++. Non fa affidamento su eccezioni o RTTI. Può essere compilato con o senza supporto STL. TinyXML supporta completamente la codifica UTF-8 e le prime 64k entità di caratteri.
TinyXML non analizza né usa DTD (Document Type Definitions) o XSL (eXtensible Stylesheet Language). Ci sono altri parser in giro (controlla www.sourceforge.org, cerca XML) che hanno molte più funzionalità. Ma sono anche molto più grandi, richiedono più tempo per la configurazione nel tuo progetto, hanno una curva di apprendimento più ripida e spesso hanno una licenza più restrittiva. Se lavori con i browser o hai esigenze XML più complete, TinyXML non è il parser che fa per te.
La seguente sintassi DTD non verrà analizzata al momento in TinyXML:
@verbatim ]> @endverbatim
perché TinyXML lo vede come un nodo !DOCTYPE con un nodo !ELEMENT incorporato illegalmente. Questo potrebbe essere risolto in futuro.
Per gli impazienti, ecco un tutorial per iniziare. Un ottimo modo per partire, ma vale la pena leggere questo manuale (molto breve) per intero.
TinyXML è un codice maturo e collaudato. È molto stabile. Se trovi bug, per favore segnalali sul sito web di sourceforge (www.sourceforge.net/projects/tinyxml). Li sistemeremo il prima possibile.
Ci sono alcune aree di miglioramento; controlla sourceforge se sei interessato a lavorare su TinyXML.
Progetti TinyXML che potresti trovare utili! (Descrizioni fornite dai progetti.)
TinyXML può essere compilato per usare o non usare STL. Quando usa STL, TinyXML usa la classe std::string e supporta completamente std::istream, std::ostream, operator<< e operator>>. Molti metodi API hanno sia le forme 'const char*' che 'const std::string&'.
Quando il supporto STL è escluso dalla compilazione, nessun file STL viene incluso. Tutte le classi stringa sono implementate da TinyXML stesso. Tutti i metodi API usano la forma 'const char*' per l'input.
Usa la #define in fase di compilazione:
TIXML_USE_STL
per compilare una versione o l'altra. Questo può essere passato dal compilatore o impostato come prima riga di "tinyxml.h".
Nota: se compili il codice di test in Linux, impostando la variabile d'ambiente TINYXML_USE_STL=YES/NO controllerai la compilazione STL. Nel file di progetto Windows vengono forniti target STL e non STL. Nel tuo progetto, probabilmente è più semplice aggiungere la riga "#define TIXML_USE_STL" come prima riga di tinyxml.h.
TinyXML supporta UTF-8, permettendo di manipolare file XML in qualsiasi lingua. TinyXML supporta anche la "modalità legacy" - la codifica usata prima del supporto UTF-8 e probabilmente meglio descritta come "ascii esteso".
Normalmente, TinyXML cercherà di rilevare la codifica corretta e di usarla. Tuttavia, impostando il valore di TIXML_DEFAULT_ENCODING nel file header, TinyXML può essere forzato a usare sempre una codifica.
TinyXML assumerà la Modalità Legacy finché non si verifica una delle seguenti condizioni:
Cosa succede se la codifica è impostata o rilevata in modo errato? TinyXML cercherà di leggere e lasciar passare il testo visto come codificato in modo improprio. Potresti ottenere risultati strani o caratteri alterati. Potresti voler forzare TinyXML nella modalità corretta.
Puoi forzare TinyXML in Modalità Legacy usando LoadFile( TIXML_ENCODING_LEGACY ) o LoadFile( filename, TIXML_ENCODING_LEGACY ). Puoi forzarlo a usare sempre la modalità legacy impostando TIXML_DEFAULT_ENCODING = TIXML_ENCODING_LEGACY. Allo stesso modo, puoi forzarlo a TIXML_ENCODING_UTF8 con la stessa tecnica.
Per gli utenti inglesi, che usano XML in inglese, UTF-8 è uguale al low-ASCII. Non hai bisogno di conoscere UTF-8 o di cambiare il tuo codice in alcun modo. Puoi pensare a UTF-8 come a un "superset" di ASCII.
UTF-8 non è un formato a doppio byte - ma è una codifica standard di Unicode! Al momento TinyXML non usa né supporta direttamente wchar, TCHAR o _UNICODE di Microsoft. È comune vedere il termine "Unicode" riferito impropriamente a UTF-16, una codifica a byte larghi di unicode. Questa è una fonte di confusione.
Per le lingue "high-ascii" - praticamente tutto ciò che non è inglese - TinyXML può gestire tutte le lingue, allo stesso tempo, purché l'XML sia codificato in UTF-8. Questo può essere un po' complicato: i programmi e i sistemi operativi più vecchi tendono a usare la code page "predefinita" o "tradizionale". Molte app (e quasi tutte quelle moderne) possono produrre UTF-8, ma quelle più vecchie o ostinate (o semplicemente rotte) producono ancora testo nella code page predefinita.
Per esempio, i sistemi giapponesi usano tradizionalmente la codifica SHIFT-JIS. Il testo codificato come SHIFT-JIS non può essere letto da TinyXML. Un buon editor di testo può importare SHIFT-JIS e poi salvare come UTF-8.
Il link Skew.org fa un ottimo lavoro nel trattare il problema della codifica.
Il file di test "utf8test.xml" è un XML che contiene inglese, spagnolo, russo e cinese semplificato. (Si spera che siano tradotti correttamente). Il file "utf8test.gif" è una cattura dello schermo del file XML, renderizzato in IE. Nota che se non hai i font corretti (cinese semplificato o russo) sul tuo sistema, non vedrai un output che corrisponda al file GIF anche se riesci ad analizzarlo correttamente. Nota anche che (almeno sulla mia macchina Windows) l'output della console è in una code page occidentale, quindi Print() o printf() non possono visualizzare correttamente il file. Questo non è un bug di TinyXML - è solo un problema del sistema operativo. Nessun dato viene perso o distrutto da TinyXML. La console semplicemente non renderizza UTF-8.
@verbatim & & < < > > " " ' ' @endverbatim
Queste vengono riconosciute quando il documento XML viene letto e tradotte nei loro equivalenti UTF-8. Per esempio, testo con l'XML di:
@verbatim Far & Away @endverbatim
avrà Value() pari a "Far & Away" quando interrogato dall'oggetto TiXmlText, e verrà riscritto nello stream/file XML come una e commerciale. Le versioni più vecchie di TinyXML "preservavano" le entità di carattere, ma le versioni più recenti le traducono in caratteri.
Inoltre, qualsiasi carattere può essere specificato tramite il suo code point Unicode: la sintassi " " o " " si riferiscono entrambe al carattere di spazio unificatore (non-breaking space).
Print( FILE* ). Output su uno stream std-C, che include tutti i file C e anche stdout.
operator<<. Output su uno stream C++.
TiXmlPrinter. Output su una std::string o su un buffer di memoria.
Output in stile C: - basato su FILE* - i metodi Print() e SaveFile()
Genera un output formattato, con abbondanza di spazio bianco, pensato per essere il più leggibile possibile dall'uomo. Sono molto veloci e tolleranti verso documenti XML malformati. Per esempio, un documento XML che contiene 2 elementi radice e 2 dichiarazioni verrà comunque stampato.
Input in stile C: - basato su FILE* - i metodi Parse() e LoadFile()
Una lettura veloce e tollerante. Usala ogni volta che non hai bisogno degli stream C++.
Output in stile C++: - basato su std::ostream - operator<<
Genera un output condensato, pensato per la trasmissione in rete piuttosto che per la leggibilità. A seconda dell'implementazione della classe ostream del tuo sistema, questi potrebbero essere un po' più lenti. (O forse no.) Non è tollerante verso XML malformato: un documento dovrebbe contenere il corretto elemento radice. Ulteriori elementi a livello di radice non verranno trasmessi.
Input in stile C++: - basato su std::istream - operator>>
Legge XML da uno stream, rendendolo utile per la trasmissione in rete. La parte complicata è sapere quando il documento XML è completo, poiché quasi certamente ci saranno altri dati nello stream. TinyXML assumerà che i dati XML siano completi dopo aver letto l'elemento radice. In altre parole, i documenti costruiti male con più di un elemento radice non verranno letti correttamente. Nota anche che operator>> è un po' più lento di Parse, sia per l'implementazione della STL sia per le limitazioni di TinyXML.
È un problema che non è stato risolto in modo soddisfacente per me. TinyXML supporta i primi 2 approcci. Chiama TiXmlBase::SetCondenseWhiteSpace( bool ) per impostare il comportamento desiderato. L'impostazione predefinita è condensare lo spazio bianco.
Se cambi l'impostazione predefinita, dovresti chiamare TiXmlBase::SetCondenseWhiteSpace( bool ) prima di fare qualsiasi chiamata per analizzare dati XML, e non consiglio di cambiarla dopo che è stata impostata.
Quando si esplora un documento XML in modo robusto, è importante controllare i ritorni null dalle chiamate ai metodi. Un'implementazione sicura contro gli errori può generare molto codice come:
@verbatim TiXmlElement* root = document.FirstChildElement( "Document" ); if ( root ) { TiXmlElement* element = root->FirstChildElement( "Element" ); if ( element ) { TiXmlElement* child = element->FirstChildElement( "Child" ); if ( child ) { TiXmlElement* child2 = child->NextSiblingElement( "Child" ); if ( child2 ) { // Finally do something useful. @endverbatim
Gli handle sono stati introdotti per ripulire tutto questo. Usando la classe TiXmlHandle, il codice precedente si riduce a:
@verbatim TiXmlHandle docHandle( &document ); TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); if ( child2 ) { // do something useful @endverbatim
Il che è molto più facile da gestire. Vedi TiXmlHandle per maggiori informazioni.
TinyXML può tracciare l'origine di riga e colonna di tutti i nodi e attributi in un file di testo. I metodi TiXmlBase::Row() e TiXmlBase::Column() restituiscono l'origine del nodo nel testo sorgente. Le tabulazioni corrette possono essere configurate in TiXmlDocument::SetTabSize().
Per compilare ed eseguire xmltest:
Vengono forniti un Makefile Linux e un file .dsw per Windows Visual C++. Basta compilare ed eseguire. Scriverà il file demotest.xml sul tuo disco e genererà output sullo schermo. Testa anche l'attraversamento del DOM stampando il numero di nodi trovati usando diverse tecniche.
Il makefile Linux è molto generico e funziona su molti sistemi - attualmente è testato su mingw e MacOSX. Non hai bisogno di eseguire 'make depend'. Le dipendenze sono state codificate direttamente.
PROFILE, DEBUG e TINYXML_USE_STL. I dettagli (per quel che valgono) sono nel makefile.
Nella directory tinyxml, digita "make clean" e poi "make". Verrà creato il file eseguibile 'xmltest'.
Aggiungi tinyxml.cpp, tinyxml.h, tinyxmlerror.cpp, tinyxmlparser.cpp, tinystr.cpp e tinystr.h al tuo progetto o make file. Tutto qui! Dovrebbe compilare su qualsiasi sistema C++ ragionevolmente conforme. Non hai bisogno di abilitare eccezioni o RTTI per TinyXML.
Un esempio è probabilmente il modo migliore. Prendi: @verbatim <?xml version="1.0" standalone=no> Go to the Toy store! Do bills @endverbatim
Non è granché come lista di cose da fare, ma va bene. Per leggere questo file (diciamo "demo.xml") creeresti un documento e lo analizzeresti: @verbatim TiXmlDocument doc( "demo.xml" ); doc.LoadFile(); @endverbatim
Ed è pronto per l'uso. Ora guardiamo alcune righe e come si relazionano al DOM.
@verbatim
@endverbatim La prima riga è una dichiarazione e viene trasformata nella classe TiXmlDeclaration. Sarà il primo figlio del nodo documento. Questo è l'unico tag direttiva/speciale analizzato da TinyXML. In generale i tag direttiva vengono memorizzati in TiXmlUnknown così i comandi non andranno persi quando viene salvato di nuovo su disco. @verbatim @endverbatim Un commento. Diventerà un oggetto TiXmlComment. @verbatim @endverbatim Il tag "ToDo" definisce un oggetto TiXmlElement. Questo non ha attributi, ma contiene 2 altri elementi. @verbatim @endverbatim Crea un altro TiXmlElement che è figlio dell'elemento "ToDo". Questo elemento ha 1 attributo, con nome "priority" e valore "1". @verbatim Go to the @endverbatim Un TiXmlText. Questo è un nodo foglia e non può contenere altri nodi. È un figlio del TiXmlElement "Item". @verbatim @endverbatim Un altro TiXmlElement, questo figlio dell'elemento "Item". Ecc. Guardando l'intero albero di oggetti, ti ritrovi con: @verbatim TiXmlDocument "demo.xml" TiXmlDeclaration "version='1.0'" "standalone=no" TiXmlComment " Our to do list data" TiXmlElement "ToDo" TiXmlElement "Item" Attribtutes: priority = 1 TiXmlText "Go to the " TiXmlElement "bold" TiXmlText "Toy store!" TiXmlElement "Item" Attributes: priority=2 TiXmlText "Do bills" @endverbatim