Subversion Repositories HomeAutomation

Rev

Rev 1314 | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
1309 runge 1
/*
2
 * Node.cpp
3
 *
4
 *  Created on: Apr 26, 2009
5
 *      Author: Mattias Runge
6
 */
7
 
8
#include "Node.h"
9
 
10
namespace atom {
11
namespace xml {
12
 
13
Node::Node()
14
{
15
    this->myIsEmpty = true;
16
    LOG.setName("XML::Node");
17
}
18
 
19
Node::Node(string filename)
20
{
21
    this->myIsEmpty = true;
22
    LOG.setName("XML::Node");
1310 runge 23
    this->load(filename);
1309 runge 24
}
25
 
26
Node::Node(string filename, string xmlData)
27
{
28
    this->myIsEmpty = true;
29
    LOG.setName("XML::Node");
30
    this->parse(filename, xmlData);
31
}
32
 
1310 runge 33
void Node::load(string filename)
34
{
1314 runge 35
    this->parse(filename, file::get_contents(filename));
1310 runge 36
}
37
 
1309 runge 38
void Node::parse(string filename, string xmlData)
39
{
40
    char c;
41
    unsigned int position = 0;
42
 
43
    while (position < xmlData.length())
44
    {
45
        c = xmlData.at(position);
46
 
47
        switch (c)
48
        {
49
        case '<':
50
            position = this->parseTag(filename, xmlData, position);
51
            break;
52
        }
53
 
54
        position++;
55
    }
56
}
57
 
58
string Node::tagName()
59
{
60
    return this->myTagName;
61
}
62
 
63
Node::attributeList & Node::attributes()
64
{
65
    return this->myAttributes;
66
}
67
 
68
string Node::operator [](string attributeName)
69
{
70
    attributeList::iterator iter = this->myAttributes.find(attributeName);
71
 
1310 runge 72
    if (iter == this->myAttributes.end())
73
    {
1309 runge 74
        return "";
1310 runge 75
    }
1309 runge 76
 
77
    return iter->second;
78
}
79
 
80
Node Node::selectFirst()
81
{
82
    // TODO Throw exception if returned list is empty
83
    return this->select()[0];
84
}
85
 
86
Node Node::selectFirst(string tagName)
87
{
88
    // TODO Throw exception if returned list is empty
89
    return this->select(tagName)[0];
90
}
91
 
92
Node Node::selectFirst(string tagName, attributeList attributes)
93
{
94
    // TODO Throw exception if returned list is empty
95
    return this->select(tagName, attributes)[0];
96
}
97
 
98
Node Node::selectFirst(string tagName, attributePair pair1)
99
{
100
    attributeList attributes;
101
    attributes.insert(pair1);
102
    return this->selectFirst(tagName, attributes);
103
}
104
 
105
Node Node::selectFirst(string tagName, attributePair pair1, attributePair pair2)
106
{
107
    attributeList attributes;
108
    attributes.insert(pair1);
109
    attributes.insert(pair2);
110
    return this->selectFirst(tagName, attributes);
111
}
112
 
113
Node Node::selectFirst(string tagName, attributePair pair1, attributePair pair2, attributePair pair3)
114
{
115
    attributeList attributes;
116
    attributes.insert(pair1);
117
    attributes.insert(pair2);
118
    attributes.insert(pair3);
119
    return this->selectFirst(tagName, attributes);
120
}
121
 
122
Node Node::selectFirst(string tagName, attributePair pair1, attributePair pair2, attributePair pair3, attributePair pair4)
123
{
124
    attributeList attributes;
125
    attributes.insert(pair1);
126
    attributes.insert(pair2);
127
    attributes.insert(pair3);
128
    attributes.insert(pair4);
129
    return this->selectFirst(tagName, attributes);
130
}
131
 
132
Node Node::selectFirst(string tagName, attributePair pair1, attributePair pair2, attributePair pair3, attributePair pair4, attributePair pair5)
133
{
134
    attributeList attributes;
135
    attributes.insert(pair1);
136
    attributes.insert(pair2);
137
    attributes.insert(pair3);
138
    attributes.insert(pair4);
139
    attributes.insert(pair5);
140
    return this->selectFirst(tagName, attributes);
141
}
142
 
143
Node::nodeList Node::select()
144
{
145
    return this->myChildren;
146
}
147
 
148
Node::nodeList Node::select(string tagName)
149
{
150
    attributeList attributes;
151
    return this->select(tagName, attributes);
152
}
153
 
154
Node::nodeList Node::select(string tagName, attributeList attributes)
155
{
156
    nodeList list;
157
    bool attributesMatch = true;
158
 
159
    for (unsigned int n = 0; n < this->myChildren.size(); n++)
160
    {
161
        if (this->myChildren[n].tagName() == tagName)
162
        {
163
            attributesMatch = true;
164
 
165
            for (attributeList::iterator iter = attributes.begin(); iter != attributes.end(); iter++)
166
            {
1314 runge 167
                //LOG.debug("#attributes = " + convert::int2string(this->myChildren[n].attributes().size()));
1309 runge 168
                //LOG.debug("iter->first = " + iter->first);
169
                //LOG.debug("iter->second = " + iter->second);
170
                //LOG.debug("this->myChildren[n][iter->first] = " + this->myChildren[n][iter->first]);
171
                if (this->myChildren[n][iter->first] != iter->second)
172
                {
173
                    attributesMatch = false;
174
                    break;
175
                }
176
            }
177
 
178
            if (attributesMatch)
179
            {
180
                list.push_back(myChildren[n]);
181
            }
182
        }
183
    }
184
 
185
    return list;
186
}
187
 
188
 
189
Node::nodeList Node::select(string tagName, attributePair pair1)
190
{
191
    attributeList attributes;
192
    attributes.insert(pair1);
193
    return this->select(tagName, attributes);
194
}
195
 
196
Node::nodeList Node::select(string tagName, attributePair pair1, attributePair pair2)
197
{
198
    attributeList attributes;
199
    attributes.insert(pair1);
200
    attributes.insert(pair2);
201
    return this->select(tagName, attributes);
202
}
203
 
204
Node::nodeList Node::select(string tagName, attributePair pair1, attributePair pair2, attributePair pair3)
205
{
206
    attributeList attributes;
207
    attributes.insert(pair1);
208
    attributes.insert(pair2);
209
    attributes.insert(pair3);
210
    return this->select(tagName, attributes);
211
}
212
 
213
Node::nodeList Node::select(string tagName, attributePair pair1, attributePair pair2, attributePair pair3, attributePair pair4)
214
{
215
    attributeList attributes;
216
    attributes.insert(pair1);
217
    attributes.insert(pair2);
218
    attributes.insert(pair3);
219
    attributes.insert(pair4);
220
    return this->select(tagName, attributes);
221
}
222
 
223
Node::nodeList Node::select(string tagName, attributePair pair1, attributePair pair2, attributePair pair3, attributePair pair4, attributePair pair5)
224
{
225
    attributeList attributes;
226
    attributes.insert(pair1);
227
    attributes.insert(pair2);
228
    attributes.insert(pair3);
229
    attributes.insert(pair4);
230
    attributes.insert(pair5);
231
    return this->select(tagName, attributes);
232
}
233
 
234
int Node::parseTag(string filename, string xmlData, unsigned int position)
235
{
236
    if (xmlData.at(position) != '<')
237
    {
1314 runge 238
        throw new Exception("Did not find < as expected. Character " + convert::int2string(position));
1309 runge 239
    }
240
 
241
    position++;
242
 
243
    int endPosition = xmlData.find('>', position);
244
 
245
    if (xmlData.at(position) == '?' || xmlData.at(position) == '!' || xmlData.at(position) == '/')
246
    {
247
        return endPosition;
248
    }
249
 
250
    this->myIsEmpty = false;
251
 
252
    string tagString;
253
 
254
    try
255
    {
256
        tagString = xmlData.substr(position, endPosition - position);
257
    }
258
    catch (std::out_of_range & e)
259
    {
260
        LOG.debug("parseTag exception: " + string(e.what()));
1314 runge 261
        LOG.debug("A xmlData=" + xmlData + " :: position=" + convert::int2string(position) + " :: endPosition=" + convert::int2string(endPosition));
1309 runge 262
        throw e;
263
    }
264
 
1311 runge 265
    trim(tagString);
266
    trim_if(tagString, is_any_of("\n"));
267
    trim(tagString);
1309 runge 268
    tagString += " ";
269
 
270
    bool foundEnd = false;
271
    bool foundTag = false;
272
    string buffer;
273
    unsigned int pos = 0;
274
    char c;
275
    int s, e;
276
 
277
    while (pos < tagString.length())
278
    {
279
        c = tagString.at(pos);
280
 
281
        switch (c)
282
        {
283
        case ' ':
284
            if (!foundTag)
285
            {
286
                this->myTagName = buffer;
287
                buffer = "";
288
                //cout << "Found tag: " << myTagName << endl;
289
                foundTag = true;
290
            }
291
            break;
292
 
293
        case '/':
294
            foundEnd = true;
295
            break;
296
 
297
        case '=':
298
            s = tagString.find('"', pos) + 1;
299
            e = tagString.find('"', s);
300
 
301
            try
302
            {
303
                this->myAttributes[buffer] = tagString.substr(s, e - s);
304
                //LOG.debug("Added attribute \"" + buffer + "\" = \"" + this->myAttributes[buffer] + "\"");
305
            }
306
            catch (std::out_of_range & ex)
307
            {
308
                LOG.debug("parseTag exception: " + string(ex.what()));
1314 runge 309
                LOG.debug("A xmlData=" + xmlData + " :: position=" + convert::int2string(position) + " :: endPosition=" + convert::int2string(endPosition));
1309 runge 310
                throw ex;
311
            }
312
 
313
            //cout << "Found attribute: " << buffer << " = " << myAttributes[buffer] << endl;
314
            pos = e;
315
            buffer = "";
316
            break;
317
 
318
        default:
319
            buffer += c;
320
            break;
321
        }
322
 
323
        pos++;
324
    }
325
 
326
    position = endPosition;
327
 
328
    if (!foundEnd)
329
    {
330
        while (position < xmlData.length())
331
        {
332
            c = xmlData.at(position);
333
 
334
            switch (c)
335
            {
336
            case '<':
337
                if (xmlData.at(position + 1) == '/')
338
                {
339
                    position += 2;
340
                    endPosition = xmlData.find('>', position);
341
 
342
                    try
343
                    {
344
                        if (myTagName.compare(xmlData.substr(position, endPosition - position)) == 0)
345
                        {
346
                            //cout << "Found end tag: " << myTagName << endl;
347
                            return endPosition;
348
                        }
349
                        else
350
                        {
351
                            throw new Exception("Invalid end tag found. " + xmlData.substr(position, endPosition - position) + "::" + myTagName);
352
                        }
353
                    }
354
                    catch (std::out_of_range & ex)
355
                    {
356
                        LOG.debug("parseTag exception: " + string(ex.what()));
1314 runge 357
                        LOG.debug("A xmlData=" + xmlData + " :: position=" + convert::int2string(position) + " :: endPosition=" + convert::int2string(endPosition));
1309 runge 358
                        throw ex;
359
                    }
360
 
361
                }
362
 
363
                Node subNode;
364
                position = subNode.parseTag(filename, xmlData, position);
365
 
366
                if (!subNode.myIsEmpty)
367
                {
368
                    this->myChildren.push_back(subNode);
369
                }
370
 
371
                break;
372
            }
373
 
374
            position++;
375
        }
376
    }
377
 
378
    return position;
379
}
380
 
381
string Node::toString()
382
{
383
    string buffer = "<" + this->myTagName;
384
 
385
    for (attributeList::iterator iter = this->myAttributes.begin(); iter != this->myAttributes.end(); iter++)
386
    {
387
        buffer += " " + iter->first + "=\"" + iter->second + "\"";
388
    }
389
 
390
    if (this->myChildren.size() > 0)
391
    {
392
        buffer += ">\n";
393
 
394
        for (unsigned int n = 0; n < this->myChildren.size(); n++)
395
        {
396
            buffer += this->myChildren[n].toString();
397
        }
398
 
399
        buffer += "</" + this->myTagName + ">\n";
400
    }
401
    else
402
    {
403
        buffer += "/>\n";
404
    }
405
 
406
    return buffer;
407
}
408
 
409
}
410
}