Subversion Repositories gelsvn

Rev

Rev 540 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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