00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "xmlsource.h"
00021 #include "../xmlencodeattr.h"
00022
00023
00024 #include <opie2/odebug.h>
00025 using namespace Opie::Core;
00026
00027
00028 #include <qdict.h>
00029 #include <qtextstream.h>
00030
00031
00032 #include <stdlib.h>
00033
00034 DBXml::DBXml(DBStore *d)
00035 {
00036 dstore = d;
00037 }
00038
00039 QString DBXml::type()
00040 {
00041 return "xml";
00042 }
00043
00044 bool DBXml::openSource(QIODevice *inDev)
00045 {
00046 bool ok;
00047
00048 DBXmlHandler h(dstore);
00049
00050 QTextStream tsIn(inDev);
00051 QXmlInputSource source(tsIn);
00052 QXmlSimpleReader reader;
00053 reader.setContentHandler(&h);
00054 reader.setErrorHandler(&h);
00055 ok = reader.parse(source);
00056
00057 return ok;
00058 }
00059
00060 bool DBXml::saveSource(QIODevice *outDev)
00061 {
00062 int i;
00063 DataElem *elem;
00064 KeyList *k;
00065
00066 QTextStream outstream(outDev);
00067
00068 outstream << "<database name=\"" << dstore->getName() << "\">" << endl;
00069 outstream << "<header>" << endl;
00070
00071 k = dstore->getKeys();
00072 KeyListIterator it(*k);
00073 while(it.current()) {
00074 if (!it.current()->delFlag()) {
00075 outstream << "<key name=\"KEYID" << it.currentKey() << "\" ";
00076 outstream << "type=\""
00077 << TVVariant::typeToName(it.current()->type())
00078 << "\">";
00079 outstream << encodeAttr(it.current()->name()) << "</key>" << endl;
00080 }
00081 ++it;
00082 }
00083
00084 outstream << "</header>" << endl;
00085
00086 dstore->first();
00087
00088 do {
00089 elem = dstore->getCurrentData();
00090 if (!elem)
00091 break;
00092 outstream << "<record>" << endl;
00093 it.toFirst();
00094 while (it.current()) {
00095 i = it.currentKey();
00096 if (elem->hasValidValue(i)) {
00097 outstream << "<KEYID" << i << ">";
00098 if (dstore->getKeyType(i) == TVVariant::Date) {
00099
00100 QDate date = elem->getField(i).toDate();
00101 outstream << date.day() << "/"
00102 << date.month() << "/"
00103 << date.year();
00104 } else {
00105 outstream << encodeAttr(elem->toQString(i));
00106 }
00107 outstream << "</KEYID" << i << ">" << endl;
00108 }
00109 ++it;
00110 }
00111 outstream << "</record>" << endl;
00112 } while(dstore->next());
00113
00114 outstream << "</database>" << endl;
00115 return TRUE;
00116 }
00117
00118 DBXml::~DBXml() {}
00119
00134 DBXmlHandler::DBXmlHandler(DBStore *ds)
00135 {
00136 data_store = ds;
00137 current_keyrep = 0;
00138 }
00139
00143 DBXmlHandler::~DBXmlHandler()
00144 {
00145 }
00146
00147 QString DBXmlHandler::errorProtocol()
00148 {
00149 owarn << "Error reading file" << oendl;
00150 return errorProt;
00151 }
00152
00153 bool DBXmlHandler::startDocument()
00154 {
00155 errorProt = "";
00156 state = StateInit;
00157 return TRUE;
00158 }
00159
00160 bool DBXmlHandler::startElement(const QString&, const QString&,
00161 const QString& qName, const QXmlAttributes& atts)
00162 {
00163 if (state == StateInit && qName == "database") {
00164
00165 state = StateDocument;
00166 data_store->setName(atts.value("name"));
00167 return TRUE;
00168 }
00169 if (state == StateDocument && qName == "header") {
00170 state = StateHeader;
00171 if (current_keyrep) delete current_keyrep;
00172 current_keyrep = new KeyList();
00173 return TRUE;
00174 }
00175 if (state == StateHeader && qName == "key") {
00176
00177 state = StateKey;
00178 last_key_type = TVVariant::String;
00179 key = atts.value("name");
00180 if (key.isEmpty()) {
00181 owarn << "empty key name" << oendl;
00182 return FALSE;
00183 }
00184 if(!atts.value("type").isEmpty())
00185 last_key_type = TVVariant::nameToType(atts.value("type"));
00186 return TRUE;
00187 }
00188 if (state == StateDocument && qName == "record") {
00189 state = StateRecord;
00190 current_data = new DataElem(data_store);
00191
00192 return TRUE;
00193 }
00194 if (state == StateRecord) {
00195 state = StateField;
00196
00197 if (!keyIndexList[qName]) {
00198
00199 owarn << "Invalid key in record" << oendl;
00200 return FALSE;
00201 }
00202 keyIndex = *keyIndexList[qName];
00203 return TRUE;
00204 }
00205 owarn << "Unable to determine tag type" << oendl;
00206 return FALSE;
00207 }
00208
00209 bool DBXmlHandler::endElement(const QString&, const QString&,
00210 const QString& qName)
00211 {
00212 switch(state) {
00213 case StateField:
00214
00215 state = StateRecord;
00216 break;
00217 case StateKey:
00218
00219 state = StateHeader;
00220 break;
00221 case StateHeader:
00222 data_store->setKeys(current_keyrep);
00223 state = StateDocument;
00224 break;
00225 case StateRecord:
00226 data_store->addItem(current_data);
00227 state = StateDocument;
00228 break;
00229 case StateDocument:
00230
00231 break;
00232 default:
00233
00234 owarn << "Invalid end tag" << oendl;
00235 return FALSE;
00236 break;
00237 }
00238 return TRUE;
00239 }
00240
00241 bool DBXmlHandler::characters(const QString& ch)
00242 {
00243
00244
00245 QString ch_simplified = ch.simplifyWhiteSpace();
00246
00247 if (ch_simplified.isEmpty())
00248 return TRUE;
00249
00250 if (state == StateKey) {
00251 int *tmp_val = new int;
00252
00253 *tmp_val = current_keyrep->addKey(ch_simplified, last_key_type);
00254 keyIndexList.insert(key, tmp_val);
00255 return TRUE;
00256 }
00257 if (state == StateField) {
00258
00259 current_data->setField(keyIndex, ch_simplified);
00260 return TRUE;
00261 }
00262
00263 owarn << "Junk characters found... ignored" << oendl;
00264 return TRUE;
00265 }
00266
00267 QString DBXmlHandler::errorString()
00268 {
00269 return "the document is not in the expected file format";
00270 }
00271
00272 bool DBXmlHandler::warning(const QXmlParseException& exception)
00273 {
00274 errorProt += QString("warning parsing error: %1 in line %2, column %3\n" )
00275 .arg(exception.message())
00276 .arg(exception.lineNumber())
00277 .arg(exception.columnNumber());
00278
00279 owarn << errorProt << oendl;
00280 return QXmlDefaultHandler::fatalError(exception);
00281 }
00282
00283 bool DBXmlHandler::error(const QXmlParseException& exception)
00284 {
00285 errorProt += QString("error parsing error: %1 in line %2, column %3\n" )
00286 .arg(exception.message())
00287 .arg(exception.lineNumber())
00288 .arg(exception.columnNumber());
00289
00290 owarn << errorProt << oendl;
00291 return QXmlDefaultHandler::fatalError(exception);
00292 }
00293
00294 bool DBXmlHandler::fatalError(const QXmlParseException& exception)
00295 {
00296 errorProt += QString("fatal parsing error: %1 in line %2, column %3\n" )
00297 .arg(exception.message())
00298 .arg(exception.lineNumber())
00299 .arg(exception.columnNumber());
00300
00301 owarn << errorProt << oendl;
00302 return QXmlDefaultHandler::fatalError(exception);
00303 }