XMLLoadSave.ccGo to the documentation of this file.00001 #include "XMLLoadSave.h"
00002 #include <iostream>
00003 #include <string>
00004 #include <libxml/xmlmemory.h>
00005 #include <libxml/parser.h>
00006 #include <libxml/parserInternals.h>
00007
00008 using namespace std;
00009
00010 unsigned int XMLLoadSave::AutoInit::libxmlrefc=0;
00011
00012 XMLLoadSave::AutoInit::AutoInit() {
00013 if(libxmlrefc==0) {
00014
00015 xmlInitParser();
00016 xmlKeepBlanksDefault(1);
00017 xmlLineNumbersDefault(1);
00018 xmlIndentTreeOutput = 1;
00019 }
00020 libxmlrefc++;
00021 }
00022
00023 XMLLoadSave::AutoInit::~AutoInit() {
00024 libxmlrefc--;
00025 if(libxmlrefc==0) {
00026 xmlCleanupParser();
00027
00028 }
00029 }
00030
00031 XMLLoadSave::XMLLoadSave()
00032 : xmldocument(NULL), compressionLevel(-1), autoFormat(true), libxmlInit()
00033 {}
00034
00035 XMLLoadSave::XMLLoadSave(const XMLLoadSave& xls)
00036 : LoadSave(xls), xmldocument(xls.xmldocument==NULL?NULL:xmlCopyDoc(xls.xmldocument,true)), compressionLevel(xls.compressionLevel), autoFormat(xls.autoFormat), libxmlInit()
00037 {}
00038
00039 XMLLoadSave& XMLLoadSave::operator=(const XMLLoadSave& xls) {
00040 LoadSave::operator=(xls);
00041 if(xls.xmldocument==NULL)
00042 clearParseTree();
00043 else
00044 setParseTree(xmlCopyDoc(xls.xmldocument,true));
00045 compressionLevel = xls.compressionLevel;
00046 autoFormat=xls.autoFormat;
00047 return *this;
00048 }
00049
00050 XMLLoadSave::~XMLLoadSave() {
00051 clearParseTree();
00052 }
00053
00054 void XMLLoadSave::reportError(const std::string& context, const bad_format& err) const {
00055 cerr << context << endl;
00056 cerr << " " << err.what() << endl;
00057 if(err.getNode()!=NULL) {
00058 xmlChar* path=xmlGetNodePath(err.getNode());
00059 cerr << " Error was flagged during processing of node at line " << xmlGetLineNo(err.getNode()) << ": " << path << " '" << xmlNodeGetContent(err.getNode()) << '\'' << endl;
00060 xmlFree(path);
00061 }
00062 }
00063
00064 unsigned int XMLLoadSave::getBinSize() const {
00065 try {
00066 if(xmldocument==NULL)
00067 setParseTree(xmlNewDoc((const xmlChar*)"1.0"));
00068 if(compressionLevel>=0)
00069 xmlSetDocCompressMode(xmldocument,compressionLevel);
00070 xmlNode * cur = FindRootXMLElement(xmldocument);
00071 SaveXML(cur);
00072 xmlChar* buf=NULL;
00073 int size=0;
00074 xmlDocDumpFormatMemory(xmldocument, &buf, &size, autoFormat);
00075 xmlFree(buf);
00076 return size;
00077 } catch(const bad_format& err) {
00078 reportError("During calculation of size:",err);
00079 return 0;
00080 }
00081 }
00082 unsigned int XMLLoadSave::LoadBuffer(const char buf[], unsigned int len) {
00083 if(xmldocument!=NULL)
00084 xmlFreeDoc(xmldocument);
00085
00086
00087 xmlParserCtxt* ctxt=xmlCreateMemoryParserCtxt(buf,len);
00088 if(ctxt==NULL) {
00089 cerr << "Error: XMLLoadSave could not create memory parser context" << endl;
00090 return 0;
00091 }
00092 xmldocument = xmlParseDocument(ctxt)==0?ctxt->myDoc:NULL;
00093 if (xmldocument == NULL ) {
00094 cerr << "Error: XMLLoadSave buffer not parsed successfully. (xml syntax error)\n"
00095 << " Attempting to recover..." << endl;
00096 xmlFreeParserCtxt(ctxt);
00097 ctxt=xmlCreateMemoryParserCtxt(buf,len);
00098 if(ctxt==NULL) {
00099 cerr << "Error: XMLLoadSave could not create memory parser context" << endl;
00100 return 0;
00101 }
00102 ctxt->recovery=1;
00103 xmldocument = xmlParseDocument(ctxt)==0?ctxt->myDoc:NULL;
00104 if(xmldocument==NULL) {
00105 cerr << "Error: XMLLoadSave recovery failed." << endl;
00106 xmlFreeParserCtxt(ctxt);
00107 return 0;
00108 }
00109 }
00110 unsigned int size=ctxt->nbChars;
00111 xmlFreeParserCtxt(ctxt);
00112
00113 try {
00114 xmlNodePtr cur = FindRootXMLElement(xmldocument);
00115 LoadXML(cur);
00116 return size;
00117 } catch(const bad_format& err) {
00118 reportError("During load of memory buffer:",err);
00119 xmlFreeDoc(xmldocument);
00120 xmldocument=NULL;
00121 return 0;
00122 }
00123 }
00124 unsigned int XMLLoadSave::SaveBuffer(char buf[], unsigned int len) const {
00125 try {
00126 if(xmldocument==NULL)
00127 setParseTree(xmlNewDoc((const xmlChar*)"1.0"));
00128 if(compressionLevel>=0)
00129 xmlSetDocCompressMode(xmldocument,compressionLevel);
00130 xmlNode * cur = FindRootXMLElement(xmldocument);
00131 SaveXML(cur);
00132 xmlChar* xbuf=NULL;
00133 int size=0;
00134 xmlDocDumpFormatMemory(xmldocument, &xbuf, &size, autoFormat);
00135 if((unsigned int)size<=len)
00136 memcpy(buf,xbuf,size);
00137 else {
00138 cerr << "Error: XMLLoadSave::SaveBuffer xmlDocDumpFormatMemory returned larger region than the target buffer" << endl;
00139 size=0;
00140 }
00141 return size;
00142 } catch(const bad_format& err) {
00143 reportError("During save to memory buffer:",err);
00144 return 0;
00145 }
00146 }
00147
00148 unsigned int XMLLoadSave::LoadFile(const char* filename) {
00149 if(xmldocument!=NULL)
00150 xmlFreeDoc(xmldocument);
00151
00152
00153 xmlParserCtxt* ctxt=xmlCreateFileParserCtxt(filename);
00154 if(ctxt==NULL) {
00155 cerr << "Error: XMLLoadSave could not create parser context for '"<< filename << "'" << endl;
00156 return 0;
00157 }
00158 xmldocument = xmlParseDocument(ctxt)==0?ctxt->myDoc:NULL;
00159 if (xmldocument == NULL ) {
00160 cerr << "Error: XMLLoadSave document '" << filename << "' not parsed successfully. (file not found or xml syntax error)\n"
00161 << " Attempting to recover..." << endl;
00162 xmlFreeParserCtxt(ctxt);
00163 ctxt=xmlCreateFileParserCtxt(filename);
00164 if(ctxt==NULL) {
00165 cerr << "Error: XMLLoadSave could not create parser context for '"<< filename << "'" << endl;
00166 return 0;
00167 }
00168 ctxt->recovery=1;
00169 xmldocument = xmlParseDocument(ctxt)==0?ctxt->myDoc:NULL;
00170 if(xmldocument==NULL) {
00171 cerr << "Error: XMLLoadSave document '" << filename << "' recovery failed." << endl;
00172 xmlFreeParserCtxt(ctxt);
00173 return 0;
00174 }
00175 }
00176 unsigned int size=ctxt->nbChars;
00177 xmlFreeParserCtxt(ctxt);
00178
00179 try {
00180 xmlNodePtr cur = FindRootXMLElement(xmldocument);
00181 LoadXML(cur);
00182 return size;
00183 } catch(const bad_format& err) {
00184 string context("During load of '");
00185 context+=filename;
00186 context+="':";
00187 reportError(context,err);
00188 xmlFreeDoc(xmldocument);
00189 xmldocument=NULL;
00190 return 0;
00191 }
00192 }
00193 unsigned int XMLLoadSave::SaveFile(const char* filename) const {
00194 try {
00195 if(xmldocument==NULL)
00196 setParseTree(xmlNewDoc((const xmlChar*)"1.0"));
00197 if(compressionLevel>=0)
00198 xmlSetDocCompressMode(xmldocument,compressionLevel);
00199 xmlNode * cur = FindRootXMLElement(xmldocument);
00200 SaveXML(cur);
00201 int size=xmlSaveFormatFile (filename, xmldocument, autoFormat);
00202 if(size==-1)
00203 cerr << "Error: XMLLoadSave::SaveFile: xmlSaveFormatFile(\"" << filename << "\",...) returned -1" << endl;
00204 return size==-1?0:size;
00205 } catch(const bad_format& err) {
00206 string context("During save to '");
00207 context+=filename;
00208 context+="':";
00209 reportError(context,err);
00210 return 0;
00211 }
00212 }
00213
00214 unsigned int XMLLoadSave::LoadFileStream(FILE* f) {
00215 if(xmldocument!=NULL)
00216 xmlFreeDoc(xmldocument);
00217
00218
00219
00220 xmlParserCtxt* ctxt=xmlCreateIOParserCtxt(NULL,NULL,fileReadCallback,fileCloseCallback,f,XML_CHAR_ENCODING_UTF8);
00221 if(ctxt==NULL) {
00222 cerr << "Error: XMLLoadSave could not create file stream parser context" << endl;
00223 return 0;
00224 }
00225 ctxt->recovery=1;
00226 xmldocument = xmlParseDocument(ctxt)==0?ctxt->myDoc:NULL;
00227 unsigned int size=ctxt->nbChars;
00228 bool wellFormed=ctxt->wellFormed;
00229 xmlFreeParserCtxt(ctxt);
00230 if (xmldocument == NULL ) {
00231 cerr << "Error: XMLLoadSave file stream not parsed successfully. (xml syntax error)\n" << endl;
00232 return 0;
00233 }
00234 if(!wellFormed)
00235 cerr << "Warning: XMLLoadSave file stream was not well formed (but was recovered)." << endl;
00236
00237 try {
00238 xmlNodePtr cur = FindRootXMLElement(xmldocument);
00239 LoadXML(cur);
00240 return size;
00241 } catch(const bad_format& err) {
00242 reportError("During load of file stream:",err);
00243 xmlFreeDoc(xmldocument);
00244 xmldocument=NULL;
00245 return 0;
00246 }
00247 }
00248 unsigned int XMLLoadSave::SaveFileStream(FILE* f) const {
00249 try {
00250 if(xmldocument==NULL)
00251 setParseTree(xmlNewDoc((const xmlChar*)"1.0"));
00252 if(compressionLevel>=0)
00253 xmlSetDocCompressMode(xmldocument,compressionLevel);
00254 xmlNode * cur = FindRootXMLElement(xmldocument);
00255 SaveXML(cur);
00256 int size=xmlDocFormatDump(f, xmldocument, autoFormat);
00257 if(size==-1)
00258 cerr << "Error: XMLLoadSave::SaveFileStream: xmlDocFormatDump(...) returned -1" << endl;
00259 return size==-1?0:size;
00260 } catch(const bad_format& err) {
00261 reportError("During save to file stream:",err);
00262 return 0;
00263 }
00264 }
00265
00266 void XMLLoadSave::clearParseTree() {
00267 xmlFreeDoc(xmldocument);
00268 xmldocument=NULL;
00269 }
00270 void XMLLoadSave::setParseTree(xmlDoc* doc) const {
00271 if(doc==xmldocument)
00272 return;
00273 xmlFreeDoc(xmldocument);
00274 xmldocument=doc;
00275 }
00276 void XMLLoadSave::readParseTree() {
00277 if(xmldocument==NULL)
00278 return;
00279 try {
00280 xmlNodePtr cur = FindRootXMLElement(xmldocument);
00281 LoadXML(cur);
00282 } catch(const bad_format& err) {
00283 reportError("During readParseTree:",err);
00284 xmlFreeDoc(xmldocument);
00285 xmldocument=NULL;
00286 }
00287 }
00288 void XMLLoadSave::writeParseTree() {
00289 try {
00290 if(xmldocument==NULL)
00291 setParseTree(xmlNewDoc((const xmlChar*)"1.0"));
00292 if(compressionLevel>=0)
00293 xmlSetDocCompressMode(xmldocument,compressionLevel);
00294 xmlNode * cur = FindRootXMLElement(xmldocument);
00295 SaveXML(cur);
00296 } catch(const bad_format& err) {
00297 reportError("During writeParseTree:",err);
00298 }
00299 }
00300
00301 void XMLLoadSave::setCompression(int level) {
00302 compressionLevel=level;
00303 if(xmldocument!=NULL)
00304 xmlSetDocCompressMode(xmldocument,compressionLevel);
00305 }
00306
00307 xmlNode* XMLLoadSave::FindRootXMLElement(xmlDoc* doc) const {
00308 if(doc==NULL)
00309 return NULL;
00310 xmlNode* cur=xmlDocGetRootElement(doc);
00311 if(cur==NULL) {
00312
00313 cur = xmlNewNode(NULL,(const xmlChar*)"");
00314 xmlDocSetRootElement(doc,cur);
00315 }
00316 return cur;
00317 }
00318
00319 int XMLLoadSave::fileReadCallback(void* f,char* buf, int len) {
00320 return ferror((FILE*)f)?-1:(int)fread(buf,sizeof(char),len,(FILE*)f);
00321 }
00322 int XMLLoadSave::fileCloseCallback(void* f) {
00323 return fclose((FILE*)f)==0?0:-1;
00324 }
00325
00326 xmlNode* XMLLoadSave::skipToElement(xmlNode* cur) {
00327 while(cur!=NULL && cur->type!=XML_ELEMENT_NODE)
00328 cur=cur->next;
00329 return cur;
00330 }
00331
00332 xmlNode* XMLLoadSave::skipToElement(xmlNode* cur, std::string& comment) {
00333 comment.clear();
00334 while(cur!=NULL && cur->type!=XML_ELEMENT_NODE) {
00335 if(cur->type==XML_COMMENT_NODE) {
00336 xmlChar* cont=xmlNodeGetContent(cur);
00337 comment+=(char*)cont;
00338 xmlFree(cont);
00339 }
00340 cur=cur->next;
00341 }
00342 return cur;
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
|