Statistics
| Branch: | Revision:

root / src / sim / cxmlelement.cc @ e1750c09

History | View | Annotate | Download (10.8 KB)

1
//==========================================================================
2
//  CXMLELEMENT.CC - part of
3
//                 OMNeT++/OMNEST
4
//              Discrete System Simulation in C++
5
//
6
// Contents:
7
//   class cXMLElement
8
//
9
//==========================================================================
10

    
11
/*--------------------------------------------------------------*
12
  Copyright (C) 2002-2008 Andras Varga
13
  Copyright (C) 2006-2008 OpenSim Ltd.
14

15
  This file is distributed WITHOUT ANY WARRANTY. See the file
16
  `license' for details on this and other legal matters.
17
*--------------------------------------------------------------*/
18

    
19
#include <string.h>
20
#include <iostream>
21
#include <sstream>
22
#include <string>
23
#include "opp_ctype.h"
24
#include "platmisc.h"
25
#include "cxmlelement.h"
26
#include "minixpath.h"
27
#include "cexception.h"
28
#include "cenvir.h"
29
#include "cmodule.h" // for ModNameParamResolver
30

    
31
USING_NAMESPACE
32

    
33

    
34
using std::ostream;
35

    
36

    
37
cXMLElement::cXMLElement(const char *tagname, const char *srclocation, cXMLElement *parent)
38
{
39
    ename = tagname;
40
    srcloc = srclocation;
41

    
42
    this->parent = 0;
43
    firstchild = 0;
44
    lastchild = 0;
45
    prevsibling = 0;
46
    nextsibling = 0;
47

    
48
    if (parent)
49
        parent->appendChild(this);
50
}
51

    
52
cXMLElement::~cXMLElement()
53
{
54
    if (parent)
55
    {
56
        parent->removeChild(this);
57
    }
58
    while (firstchild)
59
    {
60
        delete removeChild(firstchild);
61
    }
62
}
63

    
64
const char *cXMLElement::getTagName() const
65
{
66
    return ename.c_str();
67
}
68

    
69
const char *cXMLElement::getSourceLocation() const
70
{
71
    return srcloc.c_str();
72
}
73

    
74
const char *cXMLElement::getNodeValue() const
75
{
76
    return value.c_str();
77
}
78

    
79
void cXMLElement::setNodeValue(const char *s, int len)
80
{
81
    value.assign(s, len);
82
}
83

    
84
void cXMLElement::appendNodeValue(const char *s, int len)
85
{
86
    value.append(s, len);
87
}
88

    
89
const char *cXMLElement::getAttribute(const char *attr) const
90
{
91
    cXMLAttributeMap::const_iterator it = attrs.find(std::string(attr));
92
    if (it==attrs.end())
93
        return NULL;
94
    return it->second.c_str();
95
}
96

    
97
void cXMLElement::setAttribute(const char *attr, const char *value)
98
{
99
    attrs[std::string(attr)] = std::string(value);
100
}
101

    
102
cXMLElement *cXMLElement::getParentNode() const
103
{
104
    return parent;
105
}
106

    
107
cXMLElement *cXMLElement::getFirstChild() const
108
{
109
   return firstchild;
110
}
111

    
112
cXMLElement *cXMLElement::getLastChild() const
113
{
114
    return lastchild;
115
}
116

    
117
cXMLElement *cXMLElement::getNextSibling() const
118
{
119
    return nextsibling;
120
}
121

    
122
cXMLElement *cXMLElement::getPreviousSibling() const
123
{
124
    return prevsibling;
125
}
126

    
127
void cXMLElement::appendChild(cXMLElement *node)
128
{
129
    if (node->parent)
130
        node->parent->removeChild(node);
131
    node->parent = this;
132
    node->prevsibling = lastchild;
133
    node->nextsibling = 0;
134
    if (node->prevsibling)
135
        node->prevsibling->nextsibling = node;
136
    else
137
        firstchild = node;
138
    lastchild = node;
139
}
140

    
141
void cXMLElement::insertChildBefore(cXMLElement *where, cXMLElement *node)
142
{
143
    if (node->parent)
144
        node->parent->removeChild(node);
145
    node->parent = this;
146
    node->prevsibling = where->prevsibling;
147
    node->nextsibling = where;
148
    where->prevsibling = node;
149
    if (node->prevsibling)
150
        node->prevsibling->nextsibling = node;
151
    else
152
        firstchild = node;
153
}
154

    
155
cXMLElement *cXMLElement::removeChild(cXMLElement *node)
156
{
157
    if (node->prevsibling)
158
        node->prevsibling->nextsibling = node->nextsibling;
159
    else
160
        firstchild = node->nextsibling;
161
    if (node->nextsibling)
162
        node->nextsibling->prevsibling = node->prevsibling;
163
    else
164
        lastchild = node->prevsibling;
165
    node->parent = node->prevsibling = node->nextsibling = 0;
166
    return node;
167
}
168

    
169
bool cXMLElement::hasChildren() const
170
{
171
    return firstchild!=NULL;
172
}
173

    
174
bool cXMLElement::hasAttributes() const
175
{
176
    return !attrs.empty();
177
}
178

    
179
const cXMLAttributeMap& cXMLElement::getAttributes() const
180
{
181
    return attrs;
182
}
183

    
184
cXMLElement *cXMLElement::getFirstChildWithTag(const char *tagname) const
185
{
186
    cXMLElement *node = this->getFirstChild();
187
    while (node)
188
    {
189
        if (!strcasecmp(node->getTagName(),tagname))
190
            return node;
191
        node = node->getNextSibling();
192
    }
193
    return NULL;
194
}
195

    
196
cXMLElement *cXMLElement::getNextSiblingWithTag(const char *tagname) const
197
{
198
    cXMLElement *node = this->getNextSibling();
199
    while (node)
200
    {
201
        if (!strcasecmp(node->getTagName(),tagname))
202
            return node;
203
        node = node->getNextSibling();
204
    }
205
    return NULL;
206
}
207

    
208
cXMLElementList cXMLElement::getChildren() const
209
{
210
    cXMLElementList list;
211
    for (cXMLElement *child=getFirstChild(); child; child=child->getNextSibling())
212
        list.push_back(child);
213
    return list;
214
}
215

    
216
cXMLElementList cXMLElement::getChildrenByTagName(const char *tagname) const
217
{
218
    cXMLElementList list;
219
    for (cXMLElement *child=getFirstChild(); child; child=child->getNextSibling())
220
        if (!strcasecmp(child->getTagName(),tagname))
221
            list.push_back(child);
222
    return list;
223
}
224

    
225
cXMLElementList cXMLElement::getElementsByTagName(const char *tagname) const
226
{
227
    cXMLElementList list;
228
    if (!strcasecmp(getTagName(),tagname))
229
        list.push_back(const_cast<cXMLElement *>(this));
230
    doGetElementsByTagName(tagname,list);
231
    return list;
232
}
233

    
234
void cXMLElement::doGetElementsByTagName(const char *tagname, cXMLElementList& list) const
235
{
236
    for (cXMLElement *child=getFirstChild(); child; child=child->getNextSibling())
237
    {
238
        if (!strcasecmp(child->getTagName(),tagname))
239
            list.push_back(child);
240
        child->doGetElementsByTagName(tagname,list);
241
    }
242
}
243

    
244
cXMLElement *cXMLElement::getFirstChildWithAttribute(const char *tagname, const char *attr, const char *attrvalue) const
245
{
246
    for (cXMLElement *child=getFirstChild(); child; child=child->getNextSibling())
247
    {
248
        if (!tagname || !strcasecmp(child->getTagName(),tagname))
249
        {
250
            const char *val = child->getAttribute(attr);
251
            if (val && (!attrvalue || !strcmp(val,attrvalue)))
252
                return child;
253
        }
254
    }
255
    return NULL;
256
}
257

    
258
cXMLElement *cXMLElement::getElementById(const char *idattrvalue) const
259
{
260
    const char *id = getAttribute("id");
261
    if (id && !strcmp(id,idattrvalue))
262
        return const_cast<cXMLElement *>(this);
263
    for (cXMLElement *child=getFirstChild(); child; child=child->getNextSibling())
264
    {
265
        cXMLElement *res = child->getElementById(idattrvalue);
266
        if (res)
267
            return res;
268
    }
269
    return NULL;
270
}
271

    
272
cXMLElement *cXMLElement::getDocumentElementByPath(cXMLElement *documentnode, const char *pathexpr,
273
                                                   cXMLElement::ParamResolver *resolver)
274
{
275
    return MiniXPath(resolver).matchPathExpression(documentnode, pathexpr, documentnode);
276
}
277

    
278
cXMLElement *cXMLElement::getElementByPath(const char *pathexpr, cXMLElement *root, cXMLElement::ParamResolver *resolver) const
279
{
280
    if (pathexpr[0]=='/' && !root)
281
        throw cRuntimeError("cXMLElement::getElementByPath(): absolute path expression "
282
                            "(that begins with  '/') can only be used if root node is "
283
                            "also specified (path expression: `%s')", pathexpr);
284
    if (root && !root->getParentNode())
285
        throw cRuntimeError("cXMLElement::getElementByPath(): root element must have a "
286
                            "parent node, the \"document node\" (path expression: `%s')", pathexpr);
287

    
288
    return MiniXPath(resolver).matchPathExpression(const_cast<cXMLElement *>(this),
289
                                                   pathexpr,
290
                                                   root ? root->getParentNode() : NULL);
291
}
292

    
293
std::string cXMLElement::tostr(int depth) const
294
{
295
    std::stringstream os;
296
    int i;
297
    for (i=0; i<depth; i++) os << "  ";
298
    os << "<" << getTagName();
299
    cXMLAttributeMap map = getAttributes();
300
    for (cXMLAttributeMap::iterator it=map.begin(); it!=map.end(); it++)
301
        os << " " << it->first << "=\"" << it->second << "\"";
302
    if (!*getNodeValue() && !getFirstChild())
303
        {os << "/>\n"; return os.str();}
304
    os << ">";
305
    os << getNodeValue();
306
    if (!getFirstChild())
307
        {os << "</" << getTagName() << ">\n"; return os.str();}
308
    os << "\n";
309
    for (cXMLElement *child=getFirstChild(); child; child=child->getNextSibling())
310
        os << child->tostr(depth+1);
311
    for (i=0; i<depth; i++) os << "  ";
312
    os << "</" << getTagName() << ">\n";
313
    return os.str();
314
}
315

    
316
std::string cXMLElement::detailedInfo() const
317
{
318
    return tostr(0);
319
}
320

    
321
void cXMLElement::debugDump() const
322
{
323
    ev << detailedInfo();
324
}
325

    
326
//---------------
327

    
328
static std::string my_itostr(int d)
329
{
330
    char buf[32];
331
    sprintf(buf, "%d", d);
332
    return std::string(buf);
333
}
334

    
335
bool ModNameParamResolver::resolve(const char *paramname, std::string& value)
336
{
337
    //printf("resolving $%s in context=%s\n", paramname, mod ? mod->getFullPath().c_str() : "NULL");
338
    if (!mod)
339
        return false;
340
    cModule *parentMod = mod->getParentModule();
341
    cModule *grandparentMod = parentMod ? parentMod->getParentModule() : NULL;
342

    
343
    if (!strcmp(paramname, "MODULE_FULLPATH"))
344
        value = mod->getFullPath();
345
    else if (!strcmp(paramname, "MODULE_FULLNAME"))
346
        value = mod->getFullName();
347
    else if (!strcmp(paramname, "MODULE_NAME"))
348
        value = mod->getName();
349
    else if (!strcmp(paramname, "MODULE_INDEX"))
350
        value = my_itostr(mod->getIndex());
351
    else if (!strcmp(paramname, "MODULE_ID"))
352
        value = my_itostr(mod->getId());
353

    
354
    else if (!strcmp(paramname, "PARENTMODULE_FULLPATH") && parentMod)
355
        value = parentMod->getFullPath();
356
    else if (!strcmp(paramname, "PARENTMODULE_FULLNAME") && parentMod)
357
        value = parentMod->getFullName();
358
    else if (!strcmp(paramname, "PARENTMODULE_NAME") && parentMod)
359
        value = parentMod->getName();
360
    else if (!strcmp(paramname, "PARENTMODULE_INDEX") && parentMod)
361
        value = my_itostr(parentMod->getIndex());
362
    else if (!strcmp(paramname, "PARENTMODULE_ID") && parentMod)
363
        value = my_itostr(parentMod->getId());
364

    
365
    else if (!strcmp(paramname, "GRANDPARENTMODULE_FULLPATH") && grandparentMod)
366
        value = grandparentMod->getFullPath();
367
    else if (!strcmp(paramname, "GRANDPARENTMODULE_FULLNAME") && grandparentMod)
368
        value = grandparentMod->getFullName();
369
    else if (!strcmp(paramname, "GRANDPARENTMODULE_NAME") && grandparentMod)
370
        value = grandparentMod->getName();
371
    else if (!strcmp(paramname, "GRANDPARENTMODULE_INDEX") && grandparentMod)
372
        value = my_itostr(grandparentMod->getIndex());
373
    else if (!strcmp(paramname, "GRANDPARENTMODULE_ID") && grandparentMod)
374
        value = my_itostr(grandparentMod->getId());
375
    else
376
        return false;
377

    
378
    //printf("  --> '%s'\n", value.c_str());
379
    return true;
380
}
381

    
382
bool StringMapParamResolver::resolve(const char *paramname, std::string& value)
383
{
384
    StringMap::iterator it = params.find(paramname);
385
    if (it==params.end())
386
        return false;
387
    value = it->second;
388
    return true;
389
}
390