Subversion Repositories gelsvn

Rev

Rev 375 | Rev 377 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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

Generated by GNU Enscript 1.6.6.
285

Generated by GNU Enscript 1.6.6.
291
 
286
 
292
 
287
 
293
 
288