TSAXParser.cxx

Go to the documentation of this file.
00001 // @(#)root/xmlparser:$Id: TSAXParser.cxx 35527 2010-09-21 12:27:01Z brun $
00002 // Author: Jose Lo   12/1/2005
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TSAXParser                                                           //
00015 //                                                                      //
00016 // TSAXParser is a subclass of TXMLParser, it is a wraper class to      //
00017 // libxml library.                                                      //
00018 //                                                                      //
00019 // SAX (Simple API for XML) is an event based interface, which doesn't  //
00020 // maintain the DOM tree in memory, in other words, it's much more      //
00021 // efficient for large document.                                        //
00022 //                                                                      //
00023 // TSAXParserCallback contains a number of callback routines to the     //
00024 // parser in a xmlSAXHandler structure. The parser will then parse the  //
00025 // document and call the appropriate callback when certain conditions   //
00026 // occur.                                                               //
00027 //                                                                      //
00028 //////////////////////////////////////////////////////////////////////////
00029 
00030 
00031 /*************************************************************************
00032   This source is based on libxml++, a C++ wrapper for the libxml XML
00033   parser library.Copyright (C) 2000 by Ari Johnson
00034 
00035   libxml++ are copyright (C) 2000 by Ari Johnson, and are covered by the
00036   GNU Lesser General Public License, which should be included with
00037   libxml++ as the file COPYING.
00038  *************************************************************************/
00039 
00040 #include "TSAXParser.h"
00041 #include "TXMLAttr.h"
00042 #include "Varargs.h"
00043 #include "TObjString.h"
00044 #include "TList.h"
00045 #include "TClass.h"
00046 
00047 #include <libxml/parser.h>
00048 #include <libxml/parserInternals.h>
00049 
00050 
00051 class TSAXParserCallback {
00052 public:
00053    static void StartDocument(void *fParser);
00054    static void EndDocument(void *fParser);
00055    static void StartElement(void *fParser, const xmlChar *name, const xmlChar **p);
00056    static void EndElement(void *fParser, const xmlChar *name);
00057    static void Characters(void *fParser, const xmlChar *ch, Int_t len);
00058    static void Comment(void *fParser, const xmlChar *value);
00059    static void CdataBlock(void *fParser, const xmlChar *value, Int_t len);
00060    static void Warning(void *fParser, const char *fmt, ...);
00061    static void Error(void *fParser, const char *fmt, ...);
00062    static void FatalError(void *fParser, const char *fmt, ...);
00063 };
00064 
00065 
00066 ClassImp(TSAXParser)
00067 
00068 //______________________________________________________________________________
00069 TSAXParser::TSAXParser()
00070 {
00071    // Create SAX parser.
00072 
00073    fSAXHandler = new xmlSAXHandler;
00074    memset(fSAXHandler, 0, sizeof(xmlSAXHandler));
00075 
00076    fSAXHandler->startDocument =
00077                    (startDocumentSAXFunc)TSAXParserCallback::StartDocument;
00078    fSAXHandler->endDocument   =
00079                    (endDocumentSAXFunc)TSAXParserCallback::EndDocument;
00080    fSAXHandler->startElement  =
00081                    (startElementSAXFunc)TSAXParserCallback::StartElement;
00082    fSAXHandler->endElement    =
00083                    (endElementSAXFunc)TSAXParserCallback::EndElement;
00084    fSAXHandler->characters    =
00085                    (charactersSAXFunc)TSAXParserCallback::Characters;
00086    fSAXHandler->comment       =
00087                    (commentSAXFunc)TSAXParserCallback::Comment;
00088    fSAXHandler->cdataBlock    =
00089                    (cdataBlockSAXFunc)TSAXParserCallback::CdataBlock;
00090    fSAXHandler->warning       =
00091                    (warningSAXFunc)TSAXParserCallback::Warning;
00092    fSAXHandler->error         =
00093                    (errorSAXFunc)TSAXParserCallback::Error;
00094    fSAXHandler->fatalError    =
00095                    (fatalErrorSAXFunc)TSAXParserCallback::FatalError;
00096 }
00097 
00098 //______________________________________________________________________________
00099 TSAXParser::~TSAXParser()
00100 {
00101    // TSAXParser desctructor
00102 
00103    ReleaseUnderlying();
00104 
00105    delete fSAXHandler;
00106 }
00107 
00108 //______________________________________________________________________________
00109 void TSAXParser::OnStartDocument()
00110 {
00111    // Emit a signal for OnStartDocument.
00112 
00113    Emit("OnStartDocument()");
00114 }
00115 
00116 //______________________________________________________________________________
00117 void TSAXParser::OnEndDocument()
00118 {
00119    // Emit a signal for OnEndDocument.
00120 
00121    Emit("OnEndDocument()");
00122 }
00123 
00124 //______________________________________________________________________________
00125 void TSAXParser::OnStartElement(const char *name, const TList *attributes)
00126 {
00127    // Emit a signal for OnStarElement, where name is the Element's name and
00128    // attribute is a TList of (TObjString*, TObjString *) TPair's.
00129    // The TPair's key is the attribute's name and value is the attribute's
00130    // value.
00131 
00132    Long_t args[2];
00133    args[0] = (Long_t)name;
00134    args[1] = (Long_t)attributes;
00135 
00136    Emit("OnStartElement(const char *, const TList *)", args);
00137 }
00138 
00139 //______________________________________________________________________________
00140 void TSAXParser::OnEndElement(const char *name)
00141 {
00142    //Emit a signal for OnEndElement, where name is the Element's name.
00143 
00144    Emit("OnEndElement(const char *)", name);
00145 }
00146 
00147 //______________________________________________________________________________
00148 void TSAXParser::OnCharacters(const char *characters)
00149 {
00150    // Emit a signal for OnCharacters, where characters are the characters
00151    // outside of tags.
00152 
00153    Emit("OnCharacters(const char *)", characters);
00154 }
00155 
00156 //______________________________________________________________________________
00157 void TSAXParser::OnComment(const char *text)
00158 {
00159    // Emit a signal for OnComment, where text is the comment.
00160 
00161    Emit("OnComment(const char *)", text);
00162 }
00163 
00164 //______________________________________________________________________________
00165 void TSAXParser::OnWarning(const char *text)
00166 {
00167    // Emit a signal for OnWarning, where text is the warning.
00168 
00169    Emit("OnWarning(const char *)", text);
00170 }
00171 
00172 //______________________________________________________________________________
00173 Int_t TSAXParser::OnError(const char *text)
00174 {
00175    // Emit a signal for OnError, where text is the error and it returns the
00176    // Parse Error Code, see TXMLParser.
00177 
00178    Emit("OnError(const char *)", text);
00179    return -3;
00180 }
00181 
00182 //______________________________________________________________________________
00183 Int_t TSAXParser::OnFatalError(const char *text)
00184 {
00185    // Emit a signal for OnFactalError, where text is the error and it
00186    // returns the Parse Error Code, see TXMLParser.
00187 
00188    Emit("OnFatalError(const char *)", text);
00189    return -4;
00190 }
00191 
00192 //______________________________________________________________________________
00193 void TSAXParser::OnCdataBlock(const char *text, Int_t len)
00194 {
00195    // Emit a signal for OnCdataBlock.
00196 
00197    Long_t args[2];
00198    args[0] = (Long_t)text;
00199    args[1] = len;
00200 
00201    Emit("OnCdataBlock(const char *, Int_t)", args);
00202 }
00203 
00204 //______________________________________________________________________________
00205 Int_t TSAXParser::Parse()
00206 {
00207    // This function parses the xml file, by initializing the parser and checks
00208    // whether the parse context is created or not, it will check as well
00209    // whether the document is well formated.
00210    // It returns the parse error code, see TXMLParser.
00211 
00212    if (!fContext) {
00213       return -2;
00214    }
00215 
00216    xmlSAXHandlerPtr oldSAX = fContext->sax;
00217    fContext->sax = fSAXHandler;
00218    fContext->userData = this;
00219 
00220    InitializeContext();
00221 
00222    xmlParseDocument(fContext);
00223 
00224    fContext->sax = oldSAX;
00225 
00226    if (!fContext->wellFormed && fParseCode == 0) {
00227       fParseCode = -5;
00228    }
00229 
00230    ReleaseUnderlying();
00231 
00232    return fParseCode;
00233 }
00234 
00235 //______________________________________________________________________________
00236 Int_t TSAXParser::ParseFile(const char *filename)
00237 {
00238    // It creates the parse context of the xml file, where the xml file name is
00239    // filename. If context is created sucessfully, it will call Parse()
00240    // It returns parse error code, see TXMLParser.
00241 
00242    // Attempt to parse a second file while a parse is in progress.
00243    if (fContext) {
00244       return -1;
00245    }
00246 
00247    fContext = xmlCreateFileParserCtxt(filename);
00248    return Parse();
00249 }
00250 
00251 //______________________________________________________________________________
00252 Int_t TSAXParser::ParseBuffer(const char *contents, Int_t len)
00253 {
00254    // It parse the contents, instead of a file.
00255    // It will return error if is attempted to parse a second file while
00256    // a parse is in progres.
00257    // It returns parse code error, see TXMLParser.
00258 
00259    // Attempt to parse a second file while a parse is in progress.
00260    if (fContext) {
00261       return -1;
00262    }
00263 
00264    fContext = xmlCreateMemoryParserCtxt(contents, len);
00265    return Parse();
00266 }
00267 
00268 
00269 //--- TSAXParserCallback -------------------------------------------------------
00270 
00271 //______________________________________________________________________________
00272 void TSAXParserCallback::StartDocument(void *fParser)
00273 {
00274    // StartDocument Callback function.
00275 
00276    TSAXParser *parser = (TSAXParser*)fParser;
00277    parser->OnStartDocument();
00278 }
00279 
00280 //______________________________________________________________________________
00281 void TSAXParserCallback::EndDocument(void *fParser)
00282 {
00283    // EndDocument callback function.
00284 
00285    TSAXParser *parser = (TSAXParser*)fParser;
00286    parser->OnEndDocument();
00287 }
00288 
00289 //______________________________________________________________________________
00290 void TSAXParserCallback::StartElement(void *fParser, const xmlChar *name,
00291                                       const xmlChar **p)
00292 {
00293    // StartElement callback function, where name is the name of the element
00294    // and p contains the attributes for the start tag.
00295 
00296    TSAXParser *parser = (TSAXParser*)fParser;
00297    TList *attributes = new TList;
00298 
00299    if (p) {
00300       for (const xmlChar **cur = p; cur && *cur; cur += 2) {
00301          attributes->Add(new TXMLAttr((const char*)*cur,
00302                                       (const char*)*(cur + 1)));
00303       }
00304    }
00305 
00306    parser->OnStartElement((const char*) name, attributes);
00307 
00308    attributes->Delete();
00309    delete attributes;
00310 }
00311 
00312 //______________________________________________________________________________
00313 void TSAXParserCallback::EndElement(void *fParser, const xmlChar *name)
00314 {
00315    // EndElement callback function, where name is the name of the element.
00316 
00317    TSAXParser *parser = (TSAXParser*)fParser;
00318    parser->OnEndElement((const char*) name);
00319 }
00320 
00321 //______________________________________________________________________________
00322 void TSAXParserCallback::Characters(void *fParser, const xmlChar *ch,
00323                                     Int_t len)
00324 {
00325    // Character callback function. It is called when there are characters that
00326    // are outside of tags get parsed and the context will be stored in ch,
00327    // len is the length of ch.
00328 
00329    TSAXParser *parser = (TSAXParser*)fParser;
00330 
00331    char *str = new char[len+1];
00332    strlcpy(str, (const char*) ch, len+1);
00333    str[len] = '\0';
00334 
00335    parser->OnCharacters(str);
00336 
00337    delete [] str;
00338 }
00339 
00340 //______________________________________________________________________________
00341 void TSAXParserCallback::Comment(void *fParser, const xmlChar *value)
00342 {
00343    // Comment callback function.
00344    // Comment of the xml file will be parsed to value.
00345 
00346    TSAXParser *parser = (TSAXParser*)fParser;
00347    parser->OnComment((const char*) value);
00348 }
00349 
00350 //______________________________________________________________________________
00351 void TSAXParserCallback::Warning(void * fParser, const char *va_(fmt), ...)
00352 {
00353    // Warning callback function. Warnings while parsing a xml file will
00354    // be stored at fmt.
00355 
00356    TSAXParser *parser = (TSAXParser*)fParser;
00357 
00358    va_list arg;
00359    char buff[1024];
00360 
00361    va_start(arg, va_(fmt));
00362    vsnprintf(buff, sizeof(buff)/sizeof(buff[0]), va_(fmt), arg);
00363    va_end(arg);
00364 
00365    parser->OnWarning(buff);
00366 }
00367 
00368 //______________________________________________________________________________
00369 void TSAXParserCallback::Error(void *fParser, const char *va_(fmt), ...)
00370 {
00371    // Error callback function. Errors while parsing a xml file will be stored
00372    // at fmt.
00373 
00374    Int_t errorcode;
00375    TSAXParser *parser = (TSAXParser*)fParser;
00376    va_list arg;
00377    char buff[1024];
00378 
00379    va_start(arg, va_(fmt));
00380    vsnprintf(buff, sizeof(buff)/sizeof(buff[0]), va_(fmt), arg);
00381    va_end(arg);
00382 
00383    errorcode = parser->OnError(buff);
00384    if (errorcode < 0) { //When error occurs, write fErrorCode
00385       parser->SetParseCode(errorcode);
00386    }
00387 
00388    if (errorcode < 0 && parser->GetStopOnError()) {
00389       //When GetStopOnError is enabled, stop the parse when an error occurs
00390       parser->StopParser();
00391    }
00392 }
00393 
00394 //______________________________________________________________________________
00395 void TSAXParserCallback::FatalError(void *fParser, const char *va_(fmt), ...)
00396 {
00397    // FactalError callback function. Factal errors while parsing a xml file
00398    // will be stored at fmt.
00399 
00400    Int_t errorcode;
00401    TSAXParser *parser = (TSAXParser*)fParser;
00402    va_list arg;
00403    char buff[1024];
00404 
00405    va_start(arg, va_(fmt));
00406    vsnprintf(buff, sizeof(buff)/sizeof(buff[0]), va_(fmt), arg);
00407    va_end(arg);
00408 
00409    errorcode = parser->OnFatalError(buff);
00410    if (errorcode < 0) {
00411       parser->SetParseCode(errorcode);
00412       parser->StopParser();
00413    }
00414 }
00415 
00416 //______________________________________________________________________________
00417 void TSAXParserCallback::CdataBlock(void *fParser, const xmlChar *value,
00418                                     Int_t len)
00419 {
00420    // CdataBlock Callback function.
00421 
00422    TSAXParser *parser = (TSAXParser*)fParser;
00423    parser->OnCdataBlock((const char*)value, len);
00424 }
00425 
00426 //______________________________________________________________________________
00427 void TSAXParser::ConnectToHandler(const char *handlerName, void *handler)
00428 {
00429    // A default TSAXParser to a user-defined Handler connection function.
00430    // This function makes connection between various function from TSAXParser
00431    // with the user-define SAX Handler, whose functions has to be exactly the
00432    // same as in TSAXParser.
00433    //
00434    // handlerName is the user-defined SAX Handler class name
00435    // handler is the pointer to the user-defined SAX Handler
00436    //
00437    // See SAXHandler.C tutorial.
00438 
00439    const TString kFunctionsName [] = {
00440       "OnStartDocument()",
00441       "OnEndDocument()",
00442       "OnStartElement(const char *, const TList *)",
00443       "OnEndElement(const char *)",
00444       "OnCharacters(const char *)",
00445       "OnComment(const char *)",
00446       "OnWarning(const char *)",
00447       "OnError(const char *)",
00448       "OnFatalError(const char *)",
00449       "OnCdataBlock(const char *, Int_t)"
00450    };
00451 
00452    TClass *cl = TClass::GetClass(handlerName);
00453 
00454    for (Int_t i = 0; i < 10; i++) {
00455       if (CheckConnectArgs(this, this->IsA(), kFunctionsName[i],
00456                            cl, kFunctionsName[i]) != -1)
00457          Connect(kFunctionsName[i], handlerName, handler, kFunctionsName[i]);
00458    }
00459 }

Generated on Tue Jul 5 14:30:42 2011 for ROOT_528-00b_version by  doxygen 1.5.1