Subversion Repositories HomeAutomation

Rev

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