hddm-xml.cpp

Go to the documentation of this file.
00001 /*
00002  *  hddm-xml : tool that reads in a HDDM document (Hall D Data Model)
00003  *    and translates it into plain-text xml.
00004  *
00005  *  Version 1.2 - Richard Jones, December 2005.
00006  *  - Updated code to use STL strings and vectors instead of old c-style
00007  *    pre-allocated arrays and strXXX functions.
00008  *  - Moved functions into classes grouped by function for better clarity.
00009  *  - Introduced the XStream class library instead of the direct interface
00010  *    to the rpc/xdr c-library function.  This also gives access to a nice
00011  *    integrated set of compression/decompression streambuf classes.
00012  *
00013  *  Version 1.1 - Richard Jones, September 2003.
00014  *  - Updated code to work with the new DOM-2 implementation Xerces-c
00015  *    from apache.org.  Significant changes have taken place in the API
00016  *    since DOM-1.
00017  *  - Added support for new types "long" (int64), "string" (char arrays of
00018  *    arbitrary length), and "anyURI" (special case of string).
00019  *  - Switched from native encoding to the use of the XDR library to make
00020  *    hddm files machine-independent.
00021  *
00022  *  Original version - Richard Jones, June 4 2001.
00023  *
00024  *
00025  *  Programmer's Notes:
00026  *  -------------------
00027  * 1. The output from hddm-xml is a well-formed xml document.
00028  *
00029  * 2. The hddm stream contains a xml header that functions as a prototype
00030  *    of the xml output.
00031  *
00032  * 3. This tool can read any hddm stream.  No recompilation is required.
00033  *
00034  * 4. The code has been tested with the xerces-c DOM implementation from
00035  *    Apache, and is intended to be used with the xerces-c library.
00036  *
00037  * 5. Output is sent by default to stdout and can be changed with the
00038  *    -o option.
00039  */
00040 
00041 #include <xercesc/util/PlatformUtils.hpp>
00042 #include <xercesc/dom/DOMNamedNodeMap.hpp>
00043 
00044 #include "XParsers.hpp"
00045 #include "XString.hpp"
00046 
00047 #include <assert.h>
00048 #include <stdlib.h>
00049 #include <stdio.h>
00050 #include <rpc/rpc.h>
00051 #include <unistd.h>
00052 #include <xstream/xdr.h>
00053 
00054 #include <iostream>
00055 #include <fstream>
00056 #include <sstream>
00057 
00058 #include "particleType.h"
00059 
00060 
00061 #define X(str) XString(str).unicode_str()
00062 #define S(str) str.c_str()
00063 
00064 using namespace xercesc;
00065 
00066 class XMLmaker
00067 {
00068  public:
00069    std::ofstream xout; 
00070 
00071    XMLmaker() {};
00072    ~XMLmaker() {};
00073 
00074    void writeXML(const XString& s);
00075    void constructXML(xstream::xdr::istream& ifx, DOMElement* el, int depth);
00076 };
00077 
00078 void usage()
00079 {
00080    std::cerr
00081         << "\nUsage:\n"
00082         << "    hddm-xml [-o <filename>] [HDDM file]\n\n"
00083         << "Options:\n"
00084         <<  "    -o <filename>   write to <filename>.xml"
00085         << std::endl;
00086 }
00087 
00088 
00089 int main(int argC, char* argV[])
00090 {
00091    XString xFilename;
00092 
00093    try
00094    {
00095       XMLPlatformUtils::Initialize();
00096    }
00097    catch (const XMLException* toCatch)
00098    {
00099       XString msg(toCatch->getMessage());
00100       std::cerr
00101            << "hddm-xml: Error during initialization! :\n"
00102            << S(msg) << std::endl;
00103       return 1;
00104    }
00105 
00106    int reqcount=0;
00107    int argInd;
00108    for (argInd = 1; argInd < argC; argInd++)
00109    {
00110       if (argV[argInd][0] != '-')
00111       {
00112          break;
00113       }
00114       else if (strcmp(argV[argInd],"-o") == 0)
00115       {
00116          xFilename = argV[++argInd];
00117       }
00118       else if (sscanf(argV[argInd],"%d",&reqcount))
00119       {
00120     reqcount = 1-reqcount;
00121       }
00122       else
00123       {
00124          usage();
00125          return 1;
00126       }
00127    }
00128 
00129    XString hddmFile;
00130    std::istream* ifs;
00131    if (argInd == argC)
00132    {
00133       ifs = &std::cin;
00134    }
00135    else if (argInd == argC - 1)
00136    {
00137       hddmFile = XString(argV[argInd]);
00138       ifs = new std::ifstream(hddmFile.c_str());
00139    }
00140    else
00141    {
00142       usage();
00143       return 1;
00144    }
00145    if (!ifs->good())
00146    {
00147       std::cerr
00148            << "hddm-xml: Error opening input stream " << hddmFile << std::endl;
00149       exit(1);
00150    }
00151    std::ostringstream tmpFileStr;
00152    tmpFileStr << "tmp" << getpid();
00153    std::ofstream ofs(tmpFileStr.str().c_str());
00154    if (! ofs.is_open())
00155    {
00156       std::cerr
00157            << "hddm-xml: Error opening temp file " << tmpFileStr << std::endl;
00158       exit(2);
00159    }
00160 
00161    ofs << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
00162    XString xmlHeader;
00163    XString line;
00164    if (getline(*ifs,line))
00165    {
00166       if (line.substr(0,5) == "<?xml")
00167       {
00168          std::cerr
00169               << "hddm-xml: Error reading input stream " << hddmFile
00170               << std::endl;
00171          std::cerr
00172               << "Input file appears to be an xml document!" << std::endl;
00173          exit(1);
00174       }
00175       else if (line.substr(0,5) == "<HDDM")
00176       {
00177          xmlHeader = line + "\n";
00178          ofs << line;
00179       }
00180       else
00181       {
00182          std::cerr
00183               << "hddm-xml: Input stream does not contain valid hddm header"
00184               << std::endl;
00185          exit(1);
00186       }
00187    }
00188    else
00189    {
00190       std::cerr
00191            << "hddm-xml: Error reading from input stream " << hddmFile 
00192            << std::endl;
00193       exit(1);
00194    }
00195    while (getline(*ifs,line))
00196    {
00197       ofs << line;
00198       if (line == "</HDDM>")
00199       {
00200          break;
00201       }
00202    }
00203    ofs.close();
00204 
00205 #if defined OLD_STYLE_XERCES_PARSER
00206    DOMDocument* document = parseInputDocument(tmpFileStr.str().c_str(),false);
00207 #else
00208    DOMDocument* document = buildDOMDocument(tmpFileStr.str().c_str(),false);
00209 #endif
00210    if (document == 0)
00211    {
00212       std::cerr
00213            << "hddm-xml : Error parsing HDDM document, "
00214            << "cannot continue" << std::endl;
00215       return 1;
00216    }
00217    unlink(tmpFileStr.str().c_str());
00218 
00219    DOMElement* rootEl = document->getDocumentElement();
00220    XString rootS(rootEl->getTagName());
00221    if (rootS != "HDDM")
00222    {
00223       std::cerr
00224            << "hddm-xml error: root element of input document is "
00225            << "\"" << S(rootS) << "\", expected \"HDDM\""
00226            << std::endl;
00227       return 1;
00228    }
00229 
00230    XMLmaker builder;
00231    if (xFilename.size())
00232    {
00233       XString fname(xFilename + ".xml");
00234       builder.xout.open(fname.c_str());
00235    }
00236   
00237    builder.writeXML("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
00238    builder.writeXML(xmlHeader);
00239 
00240    xstream::xdr::istream ifx(*ifs);
00241    while (--reqcount && ifs->good())
00242    {
00243       DOMNodeList* contList = rootEl->getChildNodes();
00244       int contLength = contList->getLength();
00245       int size;
00246       ifx >> size;
00247       if (size < 0)
00248       {
00249          break;
00250       }
00251       for (int c = 0; c < contLength; c++)
00252       {
00253          DOMNode* cont = contList->item(c);
00254          short type = cont->getNodeType();
00255          if (type == DOMNode::ELEMENT_NODE)
00256          {
00257             DOMElement* contEl = (DOMElement*) cont;
00258             ifx >> size;
00259             if (size > 0)
00260             {
00261                builder.constructXML(ifx,contEl,1);
00262             }
00263          }
00264       }
00265    }
00266 
00267    builder.writeXML("</HDDM>\n");
00268 
00269    if (ifs != &std::cin)
00270    {
00271       ((std::ifstream*)ifs)->close();
00272    }
00273    XMLPlatformUtils::Terminate();
00274    return 0;
00275 }
00276 
00277 /* write a string to xml output stream, either stdout or a file */
00278 
00279 void XMLmaker::writeXML(const XString& s)
00280 {
00281       if (xout.is_open())
00282       {
00283          xout << s;
00284       }
00285       else
00286       {
00287          std::cout << s;
00288       }
00289 }
00290 
00291 /* Generate the output xml document according the DOM;
00292  * at entry the buffer pointer bp points the the word after the word count
00293  */
00294 
00295 void XMLmaker::constructXML(xstream::xdr::istream& ifx,
00296                             DOMElement* el, int depth)
00297 {
00298    XString repS(el->getAttribute(X("maxOccurs")));
00299    int rep = (repS == "unbounded")? 9999 :
00300              (repS == "")? 1 :
00301              atoi(S(repS));
00302    if (rep > 1)
00303    {
00304       ifx >> rep;
00305    }
00306 
00307    for (int r = 0; r < rep; r++)
00308    {
00309       XString tagS(el->getTagName());
00310       for (int d = 0; d < depth; d++)
00311       {
00312          writeXML("  ");
00313       }
00314       writeXML("<");
00315       writeXML(S(tagS));
00316       DOMNamedNodeMap* attrList = el->getAttributes();
00317       int listLength = attrList->getLength();
00318       for (int a = 0; a < listLength; a++)
00319       {
00320          XString nameS(attrList->item(a)->getNodeName());
00321          XString typeS(attrList->item(a)->getNodeValue());
00322          std::ostringstream attrStr;
00323          if (typeS == "int")
00324          {
00325             int32_t value;
00326        ifx >> value;
00327             attrStr << " " << nameS << "=\"" << value << "\"";
00328          }
00329     else if (typeS == "long")
00330          {
00331             int64_t value;
00332             ifx >> value;
00333             attrStr << " " << nameS << "=\"" << value << "\"";
00334          }
00335          else if (typeS == "float")
00336          {
00337             float value;
00338             ifx >> value;
00339             attrStr << " " << nameS << "=\"" << value << "\"";
00340          }
00341          else if (typeS == "double")
00342          {
00343             double value;
00344             ifx >> value;
00345             attrStr << " " << nameS << "=\"" << value << "\"";
00346          }
00347          else if (typeS == "boolean")
00348          {
00349             bool_t value;
00350             ifx >> value;
00351             attrStr << " " << nameS << "=\"" << value << "\"";
00352          }
00353          else if (typeS == "Particle_t")
00354          {
00355             int32_t value;
00356             ifx >> value;
00357             attrStr << " " << nameS << "=\"" << ParticleType((Particle_t)value) << "\"";
00358          }
00359          else if (typeS == "string" || typeS == "anyURI")
00360          {
00361             std::string value;
00362             ifx >> value;
00363             attrStr << " " << nameS << "=\"" << value << "\"";
00364          }
00365          else if (nameS == "minOccurs" || nameS == "maxOccurs")
00366          {
00367             ;
00368          }
00369          else
00370          {
00371             attrStr << " " << nameS << "=\"" << typeS << "\"";
00372          }
00373          writeXML(attrStr.str());
00374       }
00375 
00376       DOMNodeList* contList = el->getChildNodes();
00377       int contLength = contList->getLength();
00378       if (contLength > 1)
00379       {
00380          writeXML(">\n");
00381       }
00382       else
00383       {
00384          writeXML(" />\n");
00385       }
00386 
00387       for (int c = 0; c < contLength; c++)
00388       {
00389          DOMNode* cont = contList->item(c);
00390          short type = cont->getNodeType();
00391          if (type == DOMNode::ELEMENT_NODE)
00392          {
00393             DOMElement* contEl = (DOMElement*) cont;
00394             int size;
00395             ifx >> size;
00396             if (size > 0) {
00397                constructXML(ifx,contEl,depth +1);
00398             }
00399          }
00400       }
00401 
00402       if (contLength > 1)
00403       {
00404          for (int d = 0; d < depth; d++)
00405          {
00406             writeXML("  ");
00407          }
00408          XString endTag("</"+tagS+">\n");
00409          writeXML(endTag);
00410       }
00411    }
00412 }

Generated on Sun Mar 15 03:37:28 2009 for Hall-D Software by  doxygen 1.5.2