XMLParser.cpp

Go to the documentation of this file.
00001 // Copyright CERN 2012 - Developed in collaboration with GSI
00002 
00003 #include <fesa-core/Utilities/XMLParser.h>
00004 
00005 #include <fstream>
00006 #include <cstring>
00007 
00008 
00009 namespace fesa
00010 {
00011 
00012 ElementXML::~ElementXML()
00013 {
00014     for (uint32_t i = 0; i < attributeList_.size(); i++)
00015     {
00016         delete attributeList_[i];
00017     }
00018 
00019     attributeList_.clear();
00020 
00021     for (uint32_t i = 0; i < childList_.size(); i++)
00022     {
00023         delete childList_[i];
00024     }
00025 
00026     childList_.clear();
00027 
00028 }
00029 
00030 XMLParser::XMLParser(const std::string& fileName, bool validateFile) :
00031     writer_((xmlTextWriterPtr)NULL), fileName_(fileName)
00032 {
00033     if (validateFile)
00034     {
00035         std::ifstream file(fileName.c_str());
00036         if (!file)//check, if file is valid
00037         {
00038             throw FesaFileException(__FILE__, __LINE__, FesaErrorOpenXMLFile.c_str(), fileName.c_str());
00039         }
00040     }
00041 }
00042 
00043 XMLParser::~XMLParser()
00044 {
00045     xmlCleanupParser();
00046     if (writer_ != NULL)
00047     {
00048         xmlFreeTextWriter(writer_);
00049         writer_ = (xmlTextWriterPtr)NULL;
00050     }
00051 }
00052 
00053 void XMLParser::createFile()
00054 {
00055     writer_ = xmlNewTextWriterFilename(fileName_.c_str(), 0);
00056     if (!writer_)
00057     {
00058         throw FesaException(__FILE__, __LINE__, FesaErrorCreatingXMLFile.c_str(), fileName_.c_str());
00059     }
00060 }
00061 
00062 void XMLParser::startDocument()
00063 {
00064     int32_t rc = xmlTextWriterStartDocument(writer_, NULL, MY_ENCODING, NULL);
00065     if (rc < 0)
00066     {
00067         throw FesaException(__FILE__, __LINE__, FesaErrorWritingToXMLFile.c_str(), fileName_.c_str());
00068     }
00069 }
00070 
00071 void XMLParser::endDocument()
00072 {
00073     int32_t rc = xmlTextWriterEndDocument(writer_);
00074     if (rc < 0)
00075     {
00076         throw FesaException(__FILE__, __LINE__, FesaErrorWritingToXMLFile.c_str(), fileName_.c_str());
00077     }
00078 
00079     xmlFreeTextWriter(writer_);
00080     writer_ = (xmlTextWriterPtr)NULL;
00081 }
00082 
00083 void XMLParser::startElement(const std::string element)
00084 {
00085     int32_t rc = xmlTextWriterStartElement(writer_, BAD_CAST element.c_str());
00086     if (rc < 0)
00087     {
00088         throw FesaException(__FILE__, __LINE__, FesaErrorWritingToXMLFile.c_str(), fileName_.c_str());
00089     }
00090 }
00091 
00092 void XMLParser::writeElement(const std::string element, const std::string elementValue)
00093 
00094 {
00095     int32_t rc = xmlTextWriterWriteElement(writer_, BAD_CAST element.c_str(), BAD_CAST elementValue.c_str());
00096     if (rc < 0)
00097     {
00098         throw FesaException(__FILE__, __LINE__, FesaErrorWritingToXMLFile.c_str(), fileName_.c_str());
00099     }
00100 }
00101 
00102 void XMLParser::endElement()
00103 
00104 {
00105     int32_t rc = xmlTextWriterEndElement(writer_);
00106     if (rc < 0)
00107     {
00108         throw FesaException(__FILE__, __LINE__, FesaErrorWritingToXMLFile.c_str(), fileName_.c_str());
00109     }
00110 }
00111 
00112 void XMLParser::writeString(const std::string text)
00113 
00114 {
00115     xmlChar* tmp;
00116     tmp = ConvertInput(text.c_str(), "ISO-8859-1");
00117     int32_t rc = xmlTextWriterWriteString(writer_, BAD_CAST tmp);
00118     if (tmp != NULL)
00119     {
00120         delete tmp;
00121     }
00122     if (rc < 0)
00123     {
00124         throw FesaException(__FILE__, __LINE__, FesaErrorWritingToXMLFile.c_str(), fileName_.c_str());
00125     }
00126 }
00127 
00128 void XMLParser::writeNewline()
00129 
00130 {
00131     std::string text = "\n";
00132     xmlChar* tmp;
00133     tmp = ConvertInput(text.c_str(), "ISO-8859-1");
00134     int32_t rc = xmlTextWriterWriteString(writer_, BAD_CAST tmp);
00135     if (tmp != NULL)
00136     {
00137         free(tmp);
00138     }
00139     if (rc < 0)
00140     {
00141         throw FesaException(__FILE__, __LINE__, FesaErrorWritingToXMLFile.c_str(), fileName_.c_str());
00142     }
00143 }
00144 
00145 void XMLParser::writeAttribute(const std::string attributeName, const std::string attributeValue)
00146 
00147 {
00148     int32_t rc = xmlTextWriterWriteAttribute(writer_, BAD_CAST attributeName.c_str(), BAD_CAST attributeValue.c_str());
00149     if (rc < 0)
00150     {
00151         throw FesaException(__FILE__, __LINE__, FesaErrorWritingToXMLFile.c_str(), fileName_.c_str());
00152     }
00153 }
00154 
00155 void XMLParser::fillElement(xmlNodePtr node, ElementXML* pElement)
00156 {
00157     xmlChar *value = NULL;
00158 
00159     value = xmlNodeListGetString(node->doc, node->children, 1);
00160 
00161     /* If node is containing text the carrier return is removed */
00162     if (value)
00163     {
00164         std::string trimString((const char*) value);
00165         trimCarrierReturn(trimString);
00166         pElement->value_ = trimString.data();
00167         xmlFree(value);
00168         value = NULL;
00169     }
00170     pElement->name_ = (const char*) node->name;
00171 
00172     /* Loop over all the attributes of the XML element */
00173     if (node->properties != NULL)
00174     {
00175         xmlAttrPtr curAttr;
00176         for (curAttr = node->properties; curAttr != NULL; curAttr = curAttr->next)
00177         {
00178 
00179             AttributeXML* pAttributeXML = new AttributeXML();
00180             pAttributeXML->name_ = (const char*) curAttr->name;
00181             value = xmlGetProp(node, (xmlChar*) pAttributeXML->name_.data());
00182             pAttributeXML->value_ = (const char*) value;
00183             xmlFree(value);
00184             value = NULL;
00185             pElement->attributeList_.push_back(pAttributeXML);
00186         }
00187     }
00188 
00189     /* Loop over all the child nodes of the XML element */
00190     if (node->xmlChildrenNode != NULL)
00191     {
00192         xmlNodePtr curNode;
00193         for (curNode = node->xmlChildrenNode; curNode != NULL; curNode = curNode->next)
00194         {
00195             if ((curNode->type == XML_ELEMENT_NODE))
00196             {
00197 
00198                 ElementXML* pChild = new ElementXML();
00199 
00200                 fillElement(curNode, pChild);
00201                 pElement->childList_.push_back(pChild);
00202             }
00203         }
00204     }
00205 }
00206 
00207 std::vector<ElementXML*>* XMLParser::extractElementsFromXPath(const std::string& xpathExpr)
00208 {
00209 
00210     std::vector<ElementXML*>* pElementXMLList = 0;
00211 
00212     xmlInitParser();
00213 
00214     xmlDocPtr doc;
00215     xmlXPathContextPtr xpathCtx;
00216     xmlXPathObjectPtr xpathObj;
00217 
00218     /* Load XML document */
00219     doc = xmlParseFile(fileName_.data());
00220     if (doc == NULL)
00221     {
00222         xmlCleanupParser();
00223         throw FesaException(__FILE__, __LINE__, FesaErrorOpenXMLFile.c_str(), fileName_.c_str());
00224         return NULL;
00225 
00226     }
00227     /* Create xpath evaluation context */
00228     xpathCtx = xmlXPathNewContext(doc);
00229     if (xpathCtx == NULL)
00230     {
00231         xmlFreeDoc(doc);
00232         xmlCleanupParser();
00233         return NULL;
00234     }
00235 
00236     /* Evaluate xpath expression */
00237     std::string xpath = "//";
00238     xpath.append(xpathExpr);
00239     xpathObj = xmlXPathEvalExpression((const xmlChar*) xpath.data(), xpathCtx);
00240     if (xpathObj == NULL)
00241     {
00242         xmlXPathFreeContext(xpathCtx);
00243         xmlFreeDoc(doc);
00244         xmlCleanupParser();
00245 
00246         return NULL;
00247     }
00248 
00249     /* Loop over node set returned by xPath */
00250     if (!xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
00251     {
00252         for (int32_t i = 0; i < xpathObj->nodesetval->nodeNr; ++i)
00253         {
00254             ElementXML* pEl = new ElementXML();
00255             if (!pElementXMLList)
00256             {
00257                 pElementXMLList = new std::vector<ElementXML*>;
00258             }
00259             pElementXMLList->push_back(pEl);
00260             fillElement(xpathObj->nodesetval->nodeTab[i], pEl);
00261         }
00262     }
00263 
00264     /* Cleanup */
00265     xmlXPathFreeObject(xpathObj);
00266     xmlXPathFreeContext(xpathCtx);
00267     xmlFreeDoc(doc);
00268     xmlCleanupParser();
00269 
00270     return pElementXMLList;
00271 }
00272 
00273 std::vector<ElementXML*>* XMLParser::extractElements(const std::string& elementName)
00274 {
00275     std::string xPath = "*[contains(name(),'" + elementName + "')]";
00276 
00277     return extractElementsFromXPath(xPath);
00278 
00279 }
00280 
00281 AttributeXML* XMLParser::extractAttribute(const std::string& elementName, const std::string& attributeName)
00282 {
00283     AttributeXML* pAttr = 0;
00284     xmlInitParser();
00285 
00286     xmlChar *value = NULL;
00287 
00288     xmlDocPtr doc;
00289     xmlXPathContextPtr xpathCtx;
00290     xmlXPathObjectPtr xpathObj;
00291 
00292     std::string xpathExpr("//" + elementName);
00293 
00294     /* Load XML document */
00295     doc = xmlParseFile(fileName_.data());
00296     if (doc == NULL)
00297     {
00298         xmlCleanupParser();
00299         throw FesaException(__FILE__, __LINE__, FesaErrorOpenXMLFile.c_str(), fileName_.c_str());
00300         return NULL;
00301     }
00302 
00303     /* Create xpath evaluation context */
00304     xpathCtx = xmlXPathNewContext(doc);
00305     if (xpathCtx == NULL)
00306     {
00307         xmlFreeDoc(doc);
00308         xmlCleanupParser();
00309 
00310         return NULL;
00311     }
00312 
00313     /* Evaluate xpath expression */
00314     std::string xpath = "//";
00315     xpath.append(xpathExpr);
00316     xpathObj = xmlXPathEvalExpression((const xmlChar*) xpath.data(), xpathCtx);
00317     if (xpathObj == NULL)
00318     {
00319         xmlXPathFreeContext(xpathCtx);
00320         xmlFreeDoc(doc);
00321         xmlCleanupParser();
00322 
00323         return NULL;
00324     }
00325 
00326     /* Loop over node set returned by xPath */
00327     if (!xmlXPathNodeSetIsEmpty(xpathObj->nodesetval))
00328     {
00329         value = xmlGetProp(xpathObj->nodesetval->nodeTab[0], (const xmlChar*) attributeName.data());
00330         if (value)
00331         {
00332             pAttr = new AttributeXML();
00333             pAttr->value_ = (const char*) value;
00334             xmlFree(value);
00335             pAttr->name_ = attributeName;
00336         }
00337     }
00338     xmlXPathFreeObject(xpathObj);
00339     xmlXPathFreeContext(xpathCtx);
00340     xmlFreeDoc(doc);
00341     xmlCleanupParser();
00342 
00343     return pAttr;
00344 }
00345 
00346 void XMLParser::trimCarrierReturn(std::string& s)
00347 {
00348     size_t startPos = 0;
00349     while ((startPos = s.find("\n", startPos)) != std::string::npos)
00350     {
00351         s.erase(startPos, 2);
00352     }
00353 }
00354 
00355 xmlChar* XMLParser::ConvertInput(const char *in, const char *encoding)
00356 {
00357     xmlChar *out;
00358     int32_t ret;
00359     int32_t size;
00360     int32_t out_size;
00361     int32_t temp;
00362     xmlCharEncodingHandlerPtr handler;
00363 
00364     if (in == 0)
00365         return 0;
00366 
00367     handler = xmlFindCharEncodingHandler(encoding);
00368 
00369     if (!handler)
00370     {
00371         throw FesaException(__FILE__, __LINE__, FesaErrorXMLParserEncodingNotFound.c_str(), encoding);
00372         return 0;
00373     }
00374 
00375     size = (int32_t)std::strlen(in) + 1;
00376     out_size = size * 2 - 1;
00377     out = (unsigned char *) xmlMalloc((size_t) out_size);
00378 
00379     if (out != 0)
00380     {
00381         temp = size - 1;
00382         ret = handler->input(out, &out_size, (const xmlChar *) in, &temp);
00383         if ((ret < 0) || (temp - size + 1))
00384         {
00385             if (ret < 0)
00386             {
00387                 throw FesaException(__FILE__, __LINE__, FesaErrorXMLParserConvertingInput.c_str());
00388             }
00389             else
00390             {
00391                 throw FesaException(__FILE__, __LINE__, FesaErrorXMLParserConvertingInput.c_str());
00392             }
00393 
00394             xmlFree(out);
00395             out = 0;
00396         }
00397         else
00398         {
00399             out = (unsigned char *) xmlRealloc(out, out_size + 1);
00400             out[out_size] = 0; /*null terminating out */
00401         }
00402     }
00403     else
00404     {
00405         throw FesaException(__FILE__, __LINE__, FesaErrorXMLParserConvertingInput.c_str());
00406     }
00407 
00408     return out;
00409 }
00410 
00411 } // fesa

Generated on 18 Jan 2013 for Fesa by  doxygen 1.6.1