Subversion Repositories gelsvn

Rev

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

Rev Author Line No. Line
595 jab 1
/* ----------------------------------------------------------------------- *
2
 * This file is part of GEL, http://www.imm.dtu.dk/GEL
3
 * Copyright (C) the authors and DTU Informatics
4
 * For license and list of authors, see ../../doc/intro.pdf
5
 * ----------------------------------------------------------------------- */
6
 
375 jrf 7
#include <fstream>
8
#include <string>
9
#include <sstream>
10
#include <cstring>
11
#include <algorithm>
12
#include <list>
595 jab 13
 
375 jrf 14
#include "XmlParser.h"
15
#include "string_utils.h"
16
 
17
namespace Util
18
{
595 jab 19
    using std::string;
20
    using std::map;
21
    using std::list;
22
    using std::pair;
375 jrf 23
 
595 jab 24
    using std::ifstream;
25
    using std::ostream;
26
    using std::ostringstream;
27
    using std::ios_base;
28
 
29
    using std::max;
30
 
31
    using std::cerr;
32
    using std::endl;
33
 
34
    /////////////////////////////////////////////////////////////////
35
    // String handling
36
    /////////////////////////////////////////////////////////////////
37
 
38
    void parse_attribs(const string& s, map<string, string>& result)
39
    {
40
        string name1, name2;
41
        list<string> atts;
42
        trim_split(s, atts, "=");
43
        if(atts.empty())
44
            return;
45
 
46
        get_last(atts.front(), name1);
47
        list<string>::iterator i = atts.begin();
48
        list<string>::iterator end = atts.end();
49
        if(i == --end)
50
            return;
51
 
52
        for(++i; i != end; ++i)
53
        {
54
            get_last(*i, name2);
55
            result[trim(name1)] = trim(*i, " \"");
56
            name1 = name2;
57
        }
58
        result[trim(name1)] = trim(*end, " \"");
375 jrf 59
    }
595 jab 60
 
61
    /////////////////////////////////////////////////////////////////
62
    // File handling
63
    /////////////////////////////////////////////////////////////////
64
 
65
    ifstream& seek_string(ifstream& in, const string& s, const size_t bufsize = 100)
375 jrf 66
    {
595 jab 67
        const int bsize = static_cast<int>(max(s.size(), bufsize));
68
        const int n = static_cast<int>(s.size());
69
        char* buf = new char[bsize + 1];
70
        char s0 = s[0];
71
 
72
        in.get(buf, bsize, s0);
73
        in.clear();
74
        in.read(buf, n);
75
        buf[n] = '\0';
76
        while(in && strcmp(s.c_str(), buf) != 0)
77
        {
78
            in.get(buf, bsize, s0);
79
            in.clear();
80
            in.read(buf, n);
81
            buf[n] = '\0';
82
        }
83
 
84
        delete [] buf;
85
        return in;
375 jrf 86
    }
87
 
595 jab 88
    ifstream& read_until(ifstream& in, string& s_in, const string s, const size_t bufsize = 500)
375 jrf 89
    {
595 jab 90
        const int bsize = static_cast<int>(max(s.size(), bufsize));
91
        const int n = static_cast<int>(s.size());
92
        char* buf = new char[bsize + 1];
93
        char s0 = s[0];
94
        ostringstream ostr;
95
 
96
        in.get(buf, bsize, s0);
97
        ostr << buf;
98
        in.clear();
99
        in.read(buf, n);
100
        buf[n] = '\0';
101
        while(in && strcmp(s.c_str(), buf) != 0)
102
        {
103
            ostr << buf;
104
            in.get(buf, bsize, s0);
105
            ostr << buf;
106
            in.clear();
107
            in.read(buf, n);
108
            buf[n] = '\0';
109
        }
110
        s_in = ostr.str();
111
 
112
        delete [] buf;
113
        return in;
375 jrf 114
    }
595 jab 115
 
116
    ifstream& operator>>(ifstream& in, XmlHead& fhead)
380 jrf 117
    {
595 jab 118
        seek_string(in, "<?xml");
119
 
120
        string head;
121
        read_until(in, head, "?>");
122
 
123
        fhead.is_xml = in.good();
124
        parse_attribs(head, fhead.atts);
125
 
126
        return in;
380 jrf 127
    }
595 jab 128
 
129
    ifstream& operator>>(ifstream& in, XmlElement& elem)
375 jrf 130
    {
595 jab 131
        seek_string(in, "<");
132
 
133
        string head;
134
        read_until(in, head, ">");
135
        if(head.empty() || head[0] == '!') return in;
136
        if(head[0] == '/')
137
        {
138
            if(elem.parent && elem.parent->name == head.substr(1))
139
                in.setstate(ios_base::eofbit);
140
            else
141
                elem.name = "";
142
            return in;
143
        }
144
 
145
        bool has_body = true;
146
 
147
        if(head[head.size() - 1] == '/')
148
        {
149
            has_body = false;
150
            head.erase(head.size() - 1);
151
        }
152
 
153
        get_first(head, elem.name);
154
        elem.name = trim(elem.name);
155
        parse_attribs(head, elem.atts);
156
 
157
        if(has_body)
158
        {
159
            delete elem.body;
160
            elem.body = new XmlBody(elem.doc);
161
            elem.body->element.parent = &elem;
162
            read_until(in, elem.body->text, "<");
163
            in.putback('<');
164
        }
165
        return in;
375 jrf 166
    }
595 jab 167
 
168
    ifstream& operator>>(ifstream& in, XmlBody& body)
375 jrf 169
    {
595 jab 170
        read_until(in, body.text, "<");
171
        in.putback('<');
172
        return in;
375 jrf 173
    }
595 jab 174
 
175
    /////////////////////////////////////////////////////////////////
176
    // Methods
177
    /////////////////////////////////////////////////////////////////
178
 
179
    XmlElement::~XmlElement()
380 jrf 180
    {
595 jab 181
        delete body;
380 jrf 182
    }
595 jab 183
 
184
    void XmlBody::process_element()
380 jrf 185
    {
595 jab 186
        if(!doc) return;
187
        if((doc->infile >> element) && !doc->infile.eof())
188
        {
189
            XmlElementHandler h = doc->handlers[element.name];
190
            if(h)
191
                h(element);
192
            else
193
                element.process_elements();
194
        }
380 jrf 195
    }
595 jab 196
 
197
    void XmlElement::process_elements()
198
    {
199
        if(!doc) return;
200
        if(!body) return;
201
 
202
        while((doc->infile >> body->element) && !doc->infile.eof())
203
        {
204
            XmlElementHandler h = doc->handlers[body->element.name];
205
            if(h)
206
                h(body->element);
207
            else
208
                body->element.process_elements();
209
        }
210
        doc->infile.clear();
211
    }
212
 
213
    XmlDoc::XmlDoc(const char *filename)
609 jab 214
    : infile(filename), body(0)
380 jrf 215
    {
595 jab 216
        if(!infile)
217
        {
218
            cerr << "cannot open input file" << filename << endl;
219
            return;
220
        }
221
 
222
        if(infile >> head)
223
            infile >> body;
224
        else
225
            cerr << filename << " is not a valid xml-file" << endl;
226
 
227
        body.doc = this;
228
        body.element.doc = this;
380 jrf 229
    }
230
 
595 jab 231
    void XmlDoc::process_elements()
380 jrf 232
    {
595 jab 233
        while(!infile.eof() && (infile >> body.element))
234
        {
235
            XmlElementHandler h = handlers[body.element.name];
236
            if(h)
237
                h(body.element);
238
            else
239
                body.element.process_elements();
240
        }
241
        infile.clear();
380 jrf 242
    }
595 jab 243
 
244
    /////////////////////////////////////////////////////////////////
245
    // Output handling
246
    /////////////////////////////////////////////////////////////////
247
 
248
    ostream& operator<<(ostream& out, const pair<string, string>& attrib)
249
    {
250
        return out << attrib.first << "=\"" << attrib.second << "\"";
251
    }
252
 
253
    ostream& operator<<(ostream& out, const XmlHead& head)
254
    {
255
        out << "<?xml";
256
        for(map<string, string>::const_iterator i = head.atts.begin(); i != head.atts.end(); ++i)
257
            out << " " << *i;
258
        out << "?>";
259
        return out;
260
    }
375 jrf 261
}