wsdlpull 1.23
XmlSerializer.cpp
Go to the documentation of this file.
1/* Copyright (c) 2005,2007 Vivek Krishna
2 * Based on kxml2 by Stefan Haustein, Oberhausen, Rhld., Germany
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 *
21 */
22
23
26#include "xmlpull/XmlUtils.h"
27
28XmlSerializer::XmlSerializer(std::ostream &os,std::string enc)
29 :writer(os),
30 encoding(enc),
31 elementStack(16),
32 nspStack(16),
33 nspCounts(8),
34 indent(8)
35{
36 init();
37}
38
40 :writer(std::cout),
41 encoding(enc),
42 elementStack(16),
43 nspStack(16),
44 nspCounts(8),
45 indent(8)
46{
47 init();
48}
49
51{
52}
53
54void
55XmlSerializer::init()
56{
57 nspCounts[0] = 2;
58 nspCounts[1] = 2;
59 nspStack[0] = "";
60 nspStack[1] = "";
61 nspStack[2] = "xml";
62 nspStack[3] = "http://www.w3.org/XML/1998/namespace";
63 pending = false;
64 auto_ = 0;
65 depth = 0;
66 if (encoding.find("utf",0)!=std::string::npos)
67 unicode = true;
68 else
69 unicode = false;
70}
71
72void
73XmlSerializer::check(bool close)
74{
75 if (!pending)
76 return;
77 depth++;
78 pending = false;
79
80 if (indent.size() <= depth) {
81 indent.resize(depth + 4);
82 }
83 indent[depth] = indent[depth - 1];
84
85 for (int i = nspCounts[depth - 1];
86 i < nspCounts[depth];
87 i++) {
88
89 writer<<' ';
90 writer<<"xmlns";
91 if (""!=nspStack[i * 2]) {
92 writer<<':';
93 writer<<nspStack[i * 2];
94 }
95 else if (getNamespace() != "" && nspStack[i * 2 + 1]!="")
96 exception("Cannot set default namespace for elements in no namespace");
97 writer<<"=\"";
98 writeEscaped(nspStack[i * 2 + 1], '"');
99 writer<<'"';
100 }
101
102 if (nspCounts.size() <= depth + 1) {
103 nspCounts.resize(depth + 8);
104 }
105
106 nspCounts[depth + 1] = nspCounts[depth];
107 // nspCounts[depth + 2] = nspCounts[depth];
108
109 writer<<(close ? " />" : ">");
110}
111
112void
113XmlSerializer::writeEscaped(std::string s, int quot)
114{
115
116 for (size_t i = 0; i < s.length(); i++) {
117 unsigned char c = s[i];
118 switch (c) {
119 case '\n':
120 case '\r':
121 case '\t':
122 if(quot == -1)
123 writer<<c;
124 else
125 writer<<"&#"+((int) c)+';';
126 break;
127 case '&' :
128 writer<<"&amp;";
129 break;
130 case '>' :
131 writer<<"&gt;";
132 break;
133 case '<' :
134 writer<<"&lt;";
135 break;
136 case '"' :
137 case '\'' :
138 if (c == quot) {
139 writer<<(c == '"' ? "&quot;" : "&apos;");
140 break;
141 }
142 default :
143 //if(c < ' ')
144 // exception("Illegal control code:"+((int) c));
145
146 if (c >= ' ' && c !='@' && (c < 127 || unicode))
147 writer<<c;
148 else
149 writer<<"&#" << ((int) c) << ";";
150 }
151 }
152}
153
154
155void
157{
158 writer<<"<!DOCTYPE";
159 writer<<dd;
160 writer<<">";
161}
162
163void
165 while (depth > 0) {
166 endTag(
167 elementStack[depth * 3 - 3],
168 elementStack[depth * 3 - 1]);
169 }
170 flush();
171}
172
173void
174XmlSerializer::entityRef(std::string name)
175{
176 check(false);
177 writer<<'&';
178 writer<<name;
179 writer<<';';
180}
181
182bool
183XmlSerializer:: getFeature(std::string name) {
184 //return false;
185 return ("http://xmlpull.org/v1/doc/features.html#indent-output" == name)
186 ? indent[depth]
187 : false;
188}
189
190std::string
191XmlSerializer::getPrefix(std::string ns, bool create)
192{
193 return getPrefix(ns, false, create);
194}
195
196
197std::string
199 bool includeDefault,
200 bool create)
201{
202
203 for (int i = nspCounts[depth + 1] * 2 - 2;
204 i >= 0;
205 i -= 2) {
206
207 if (nspStack[i + 1] == ns
208 && (includeDefault || nspStack[i]!="")) {
209 std::string cand = nspStack[i];
210 for (int j = i + 2;
211 j < nspCounts[depth + 1] * 2;
212 j++) {
213 if (nspStack[j]==cand) {
214 cand = "";
215 break;
216 }
217 }
218 if (cand != "")
219 return cand;
220 }
221 }
222
223 if (!create)
224 return "";
225
226 std::string prefix;
227
228 if (ns=="")
229 prefix = "";
230 else {
231 do {
232 prefix = "n" + (auto_++);
233 for (int i = nspCounts[depth + 1] * 2 - 2;
234 i >= 0;
235 i -= 2) {
236 if (prefix==nspStack[i]) {
237 prefix = "";
238 break;
239 }
240 }
241 }
242 while (prefix == "");
243 }
244
245 bool p = pending;
246 pending = false;
247 setPrefix(prefix, ns);
248 pending = p;
249 return prefix;
250}
251
252void
254{
255 text(s);
256}
257
258void
259XmlSerializer::setFeature(std::string name, bool value)
260{
261 if ("http://xmlpull.org/v1/doc/features.html#indent-output"==name) {
262 indent[depth] = value;
263 }
264 else
265 exception("Unsupported Feature");
266}
267
268void
269XmlSerializer::setPrefix(std::string prefix, std::string nsp)
270{
271 check(false);
272 std::string defined = getPrefix(nsp, true, false);
273
274 // boil out if already defined
275
276 if (prefix==defined)
277 return;
278
279 int pos = (nspCounts[depth + 1]++) << 1;
280
281 if (nspStack.size() < pos + 1) {
282 nspStack.resize(nspStack.size() + 16);
283 }
284
285 nspStack[pos++] = prefix;
286 nspStack[pos] = nsp;
287}
288
289void
291 bool standalone)
292 {
293 writer<<"<?xml version='1.0' ";
294
295 if (encoding != "") {
296 this->encoding = enc;
297 if (encoding.find("utf",0)!=std::string::npos)
298 unicode = true;
299 }
300
301 if (encoding != "") {
302 writer<<"encoding='";
303 writer<<encoding;
304 writer<<"' ";
305 }
306
307 writer<<"standalone='";
308 writer<<(standalone ? "yes" : "no");
309 writer<<"' ";
310 writer<<"?>";
311 }
312
314XmlSerializer::startTag(std::string nsp, std::string name)
315{
316 check(false);
317
318 // if (namespace == "")
319 // namespace = "";
320
321 if (indent[depth]) {
322 writer<<"\r\n";
323 for (int i = 0; i < depth; i++)
324 writer<<" ";
325 }
326
327 int esp = depth * 3;
328 if (elementStack.size() < esp + 3) {
329 elementStack.resize(elementStack.size() + 16);
330 }
331
332 std::string prefix =
333 nsp == ""
334 ? ""
335 : getPrefix(nsp, true, true);
336
337 if (nsp=="") {
338 for (int i = nspCounts[depth];
339 i < nspCounts[depth + 1];
340 i++) {
341
342 if (nspStack[i * 2]== "" && nspStack[i * 2 + 1]!= "") {
343 exception("Cannot set default namespace for elements in no namespace");
344 }
345 }
346 }
347
348 elementStack[esp++] = nsp;
349 elementStack[esp++] = prefix;
350 elementStack[esp] = name;
351
352 writer<<'<';
353 if (prefix!="") {
354 writer<<prefix;
355 writer<<':';
356 }
357
358 writer<<name;
359
360 pending = true;
361 return *this;
362}
363
366 std::string name,
367 std::string value)
368{
369 if (!pending)
370 exception("illegal position for attribute");
371
372 // int cnt = nspCounts[depth];
373
374 if (nsp == "")
375 nsp = "";
376
377 // depth--;
378 // pending = false;
379
380 std::string prefix =(nsp=="")? "": getPrefix(nsp, false, true);
381
382 // pending = true;
383 // depth++;
384
385 /* if (cnt != nspCounts[depth]) {
386 writer<<' ';
387 writer<<"xmlns";
388 if (nspStack[cnt * 2] != "") {
389 writer<<':';
390 writer<<nspStack[cnt * 2];
391 }
392 writer<<"=\"";
393 writeEscaped(nspStack[cnt * 2 + 1], '"');
394 writer<<'"';
395 }
396 */
397
398 writer<<' ';
399 if (prefix!="") {
400 writer<<prefix;
401 writer<<':';
402 }
403 writer<<name;
404 writer<<'=';
405 char q = value.find('"') == std::string::npos ? '"' : '\'';
406 writer<<q;
407 writeEscaped(value, q);
408 writer<<q;
409 return *this;
410}
411
412void
414{
415 check(false);
416 writer.flush();
417}
418
420XmlSerializer::endTag(std::string nsp, std::string name)
421{
422
423 if (!pending)
424 depth--;
425 // if (nsp == "")
426 // nsp = "";
427
428 if ((nsp == ""
429 && elementStack[depth * 3] != "")
430 || (nsp != ""
431 && nsp!=elementStack[depth * 3])
432 || elementStack[depth * 3 + 2] != name)
433
434 exception("</{"+nsp+"}"+name+"> does not match start");
435
436 if (pending) {
437 check(true);
438 depth--;
439 }
440 else {
441 if (indent[depth + 1]) {
442 writer<<"\r\n";
443 for (int i = 0; i < depth; i++)
444 writer<<" ";
445 }
446
447 writer<<"</";
448 std::string prefix = elementStack[depth * 3 + 1];
449 if (prefix != "") {
450 writer<<prefix;
451 writer<<':';
452 }
453 writer<<name;
454 writer<<'>';
455 }
456
457 nspCounts[depth + 1] = nspCounts[depth];
458 return *this;
459}
460
461
462std::string
463XmlSerializer::getNamespace()
464{
465 return getDepth() == 0 ? "" : elementStack[getDepth() * 3 - 3];
466}
467
468std::string
469XmlSerializer::getName()
470{
471 return getDepth() == 0 ? "" : elementStack[getDepth() * 3 - 1];
472}
473
474int
475XmlSerializer::getDepth() {
476 return pending ? depth + 1 : depth;
477}
478
479XmlSerializer&
480XmlSerializer::text(std::string txt){
481 check(false);
482 indent[depth] = false;
483 writeEscaped(txt, -1);
484 return *this;
485 }
486
487XmlSerializer&
488XmlSerializer::text(std::string txt, int start, int len)
489{
490 text(txt.substr(start, len));
491 return *this;
492}
493
494void
495XmlSerializer::cdsect(std::string data)
496{
497 check(false);
498 writer<<"<![CDATA[";
499 writer<<data;
500 writer<<"]]>";
501}
502
503void
504XmlSerializer::comment(std::string comment) {
505 check(false);
506 writer<<"<!--";
507 writer<<comment;
508 writer<<"-->";
509}
510
511void
512XmlSerializer::processingInstruction(std::string pi)
513{
514 check(false);
515 writer<<"<?";
516 writer<<pi;
517 writer<<"?>";
518}
519
520void
521XmlSerializer::exception (std::string desc)
522{
523 XmlPullParserException e (desc,elementStack.front(),0,0);
524 throw e;
525}
XmlSerializer & startTag(std::string nsp, std::string name)
void ignorableWhitespace(std::string s)
XmlSerializer & text(std::string txt)
void setPrefix(std::string prefix, std::string nsp)
XmlSerializer(std::ostream &os, std::string encoding="utf")
void startDocument(std::string encoding, bool standalone)
bool getFeature(std::string name)
void entityRef(std::string name)
XmlSerializer & attribute(std::string nsp, std::string name, std::string value)
void docdecl(std::string dd)
void setFeature(std::string name, bool value)
XmlSerializer & endTag(std::string nsp, std::string name)
std::string getNamespace()
std::string getPrefix(std::string nsp, bool create)