File: xmlexport.cpp

package info (click to toggle)
portabase 2.0%2Bgit20110117-1
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 6,692 kB
  • sloc: cpp: 32,047; sh: 2,675; ansic: 2,320; makefile: 343; xml: 20; python: 16; asm: 10
file content (244 lines) | stat: -rw-r--r-- 7,991 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/*
 * xmlexport.cpp
 *
 * (c) 2003,2009-2010 by Jeremy Bowman <jmbowman@alum.mit.edu>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */

/** @file xmlexport.cpp
 * Source file for XMLExport
 */

#include <QFile>
#include <QTextDocument>
#include <QTextStream>
#include "database.h"
#include "datatypes.h"
#include "formatting.h"
#include "xmlexport.h"

/**
 * Constructor.
 *
 * @param source The database to export from
 * @param filename The XML file to export to
 * @param currentCols Ordered list of column names in the current view
 */
XMLExport::XMLExport(Database *source, const QString &filename,
  const QStringList &currentCols) : db(source), indentUnit(" ")
{
    cols = currentCols;
    fieldElements.append("s");
    fieldElements.append("i");
    fieldElements.append("f");
    fieldElements.append("b");
    fieldElements.append("n");
    fieldElements.append("d");
    fieldElements.append("t");
    fieldElements.append("c");
    fieldElements.append("q");
    fieldElements.append("p");
    file = new QFile(filename);
    file->open(QFile::WriteOnly);
    output = new QTextStream(file);
    output->setCodec("UTF-8");
    *output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
    *output << "<portabase>\n";
    indent = indentUnit;
    utils.setExportPaths(filename);
}

/**
 * Destructor.
 */
XMLExport::~XMLExport()
{
    *output << "</portabase>\n";
    file->close();
    delete output;
    delete file;
}

/**
 * Add a &lt;global&gt; element representing the "_global" Metakit view.
 *
 * @param global The Metakit view to export
 */
void XMLExport::addGlobalView(c4_View &global)
{
    *output << (indent + "<global>\n");
    indent += indentUnit;
    int count = global.NumProperties();
    for (int i = 0; i < count; i++) {
        const c4_Property prop = global.NthProperty(i);
        QString name = getPropName(prop);
        if (name == "gcrypt") {
            continue;
        }
        *output << (indent + "<" + name + ">");
        *output << getValue(global, "_" + name, prop.Type(), 0);
        *output << ("</" + name + ">\n");
    }
    indent = indent.remove(0, indentUnit.length());
    *output << (indent + "</global>\n");
}

/**
 * Add an element representing the provided Metakit view.
 *
 * @param name The name to use for the generated element
 * @param view The Metakit view to export
 */
void XMLExport::addView(const QString &name, c4_View view)
{
    *output << (indent + "<" + name + ">\n");
    indent += indentUnit;
    // strip off trailing 's'
    QString rowElement = name.left(name.length() - 1);
    int colCount = view.NumProperties();
    QStringList elementNames;
    QStringList propNames;
    char *types = new char[colCount];
    int i;
    for (i = 0; i < colCount; i++) {
        const c4_Property prop = view.NthProperty(i);
        QString element = getPropName(prop);
        elementNames.append(element);
        propNames.append("_" + element);
        types[i] = prop.Type();
    }
    int rowCount = view.GetSize();
    for (i = 0; i < rowCount; i++) {
        *output << (indent + "<" + rowElement + ">\n");
        indent += indentUnit;
        for (int j = 0; j < colCount; j++) {
            *output << (indent + "<" + elementNames[j] + ">");
            *output << getValue(view, propNames[j], types[j], i);
            *output << ("</" + elementNames[j] + ">\n");
        }
        indent = indent.remove(0, indentUnit.length());
        *output << (indent + "</" + rowElement + ">\n");
    }
    indent = indent.remove(0, indentUnit.length());
    *output << (indent + "</" + name + ">\n");
}

/**
 * Add an element representing the actual user data table.
 *
 * @param fullView The Metakit view to export
 * @param filteredView The Metakit view resulting from applying the current
 *                     filter
 * @param colIds Ordered array of field ID numbers (array deleted here)
 * @param colTypes Ordered array of field type IDs (array deleted here)
 * @param idStrings Ordered list of Metakit data field identifiers
 * @param colNames Ordered list of field names in the database
 */
void XMLExport::addDataView(c4_View &fullView, c4_View &filteredView,
                            int *colIds, int *colTypes,
                            const QStringList &idStrings,
                            const QStringList &colNames)
{
    *output << (indent + "<data>\n");
    indent += indentUnit;
    int rowCount = fullView.GetSize();
    int colCount = idStrings.count();
    int viewColCount = cols.count();
    char *typeChars = new char[colCount];
    int i;
    for (i = 0; i < colCount; i++) {
        int type = colTypes[i];
        if (type == INTEGER || type == BOOLEAN || type == DATE
                || type == TIME || type == SEQUENCE) {
            typeChars[i] = 'I';
        }
        else {
            typeChars[i] = 'S';
        }
    }
    c4_IntProp Id("_id");
    for (i = 0; i < rowCount; i++) {
        *output << (indent + "<r");
        int rowId = Id (fullView[i]);
        if (filteredView.Find(Id [rowId]) == -1) {
            *output << " h=\"y\"";
        }
        *output << ">\n";
        indent += indentUnit;
        for (int j = 0; j < colCount; j++) {
            int type = colTypes[j];
            QString element("e");
            if (type < FIRST_ENUM) {
                element = fieldElements[type];
            }
            QString value = getValue(fullView, idStrings[j], typeChars[j], i);
            *output << (indent + "<" + element + " c=\"");
            *output << QString::number(colIds[j]);
            if (element == "d") {
                QString stringRep = Formatting::dateToString(value.toInt());
                *output << ("\" s=\"" + stringRep);
            }
            else if (element == "t") {
                QString stringRep = Formatting::timeToString(value.toInt());
                *output << ("\" s=\"" + stringRep);
            }
            else if (element == "p") {
                value = utils.exportImage(db, rowId, colNames[j], value);
            }
            if (j >= viewColCount) {
                *output << "\" h=\"y";
            }
            *output << ("\">" + value + "</" + element + ">\n");
        }
        indent = indent.remove(0, indentUnit.length());
        *output << (indent + "</r>\n");
    }
    indent = indent.remove(0, indentUnit.length());
    *output << (indent + "</data>\n");
    delete[] colIds;
    delete[] colTypes;
    delete[] typeChars;
}

/**
 * Get the name to use for the export element corresponding to the given
 * Metakit property.  Generally, this only involves stripping the leading
 * underscore from the property name.
 *
 * @param prop The Metakit property being exported
 * @return The name to use for the corresponding exported element
 */
QString XMLExport::getPropName(const c4_Property prop)
{
    QString name = QString::fromUtf8(prop.Name());
    // strip leading '_'
    return name.right(name.length() - 1);
}

/**
 * Get a value from a Metakit view cell for export.  Escapes special XML
 * characters in the value where appropriate.
 *
 * @param view The view being exported
 * @param name The name of the Metakit property being exported from
 * @param type The Metakit property type character for this property
 * @param row The position index in the view of the row being exported
 * @return The specified data value, ready for insertion into an XML file
 */
QString XMLExport::getValue(c4_View &view, const QString &name, char type, int row)
{
    if (type == 'I') {
        c4_IntProp prop(name.toUtf8());
        int value = prop (view[row]);
        return QString::number(value);
    }
    else {
        c4_StringProp prop(name.toUtf8());
        QString value = QString::fromUtf8(prop (view[row]));
        return Qt::escape(value);
    }
}