/* * XLSReader.cpp * * Copyright (C) 2009 Matthias Schiffer * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along * with this program. If not, see . */ #include "XLSReader.h" #include "XLSSheet.h" #include #include #include namespace Mad { namespace Client { xmlNodePtr XLSReader::findNode(xmlNodePtr parent, const Core::String &name) { if(!parent) return 0; for(xmlNodePtr entry = parent->children; entry != 0; entry = entry->next) { if(entry->type == XML_ELEMENT_NODE && !xmlStrcmp(entry->name, (xmlChar*)name.toUTF8().c_str())) { return entry; } } return 0; } XLSReader::XLSReader(const std::string &filename) throw (Core::Exception) { static const std::string XLHTML_EXEC = "xlhtml -xml"; static const boost::regex r("'"); if(!boost::filesystem::exists(filename)) throw Core::Exception(Core::Exception::NOT_FOUND); std::string escapedFilename = boost::regex_replace(filename, r, "\\\\'", boost::match_default); std::FILE *stream = popen((XLHTML_EXEC + " '" + escapedFilename + "' 2>/dev/null").c_str(), "r"); std::string data; while(!std::feof(stream)) { char buffer[1024]; size_t bytes = std::fread(buffer, 1, sizeof(buffer), stream); if(!bytes) break; data += std::string(buffer, bytes); } int ret = pclose(stream); if(!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) { throw Core::Exception(Core::Exception::INVALID_INPUT); } doc.reset(xmlParseMemory(data.c_str(), data.length()), xmlFreeDoc); if(!doc) { throw Core::Exception(Core::Exception::NOT_AVAILABLE); } xmlNodePtr sheetsNode = findNode(xmlDocGetRootElement(doc.get()), "sheets"); if(!sheetsNode) { throw Core::Exception(Core::Exception::NOT_AVAILABLE); } for(xmlNodePtr entry = sheetsNode->children; entry != 0; entry = entry->next) { if(entry->type == XML_ELEMENT_NODE && !xmlStrcmp(entry->name, (xmlChar*)"sheet")) sheets.push_back(boost::shared_ptr(new XLSSheet(doc, entry))); } } } }