Subversion Repositories gelsvn

Rev

Rev 595 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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

Generated by GNU Enscript 1.6.6.
263

Generated by GNU Enscript 1.6.6.
264
 
264
 
265
 
265
 
266
 
266