00001
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)
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
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
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
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
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
00228 xpathCtx = xmlXPathNewContext(doc);
00229 if (xpathCtx == NULL)
00230 {
00231 xmlFreeDoc(doc);
00232 xmlCleanupParser();
00233 return NULL;
00234 }
00235
00236
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
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
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
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
00304 xpathCtx = xmlXPathNewContext(doc);
00305 if (xpathCtx == NULL)
00306 {
00307 xmlFreeDoc(doc);
00308 xmlCleanupParser();
00309
00310 return NULL;
00311 }
00312
00313
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
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;
00401 }
00402 }
00403 else
00404 {
00405 throw FesaException(__FILE__, __LINE__, FesaErrorXMLParserConvertingInput.c_str());
00406 }
00407
00408 return out;
00409 }
00410
00411 }