Subversion Repositories HomeAutomation

Rev

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