wsdlpull 1.23
|
00001 /* Copyright (c) 2005,2007 Vivek Krishna 00002 * Based on kxml2 by Stefan Haustein, Oberhausen, Rhld., Germany 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy 00004 * of this software and associated documentation files (the "Software"), to deal 00005 * in the Software without restriction, including without limitation the rights 00006 * to use, copy, modify, merge, publish, distribute, sublicense, and/or 00007 * sell copies of the Software, and to permit persons to whom the Software is 00008 * furnished to do so, subject to the following conditions: 00009 * 00010 * The above copyright notice and this permission notice shall be included in 00011 * all copies or substantial portions of the Software. 00012 * 00013 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00014 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00015 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00016 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00017 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00018 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 00019 * IN THE SOFTWARE. 00020 * 00021 */ 00022 00023 00024 #include "xmlpull/XmlSerializer.h" 00025 #include "xmlpull/XmlPullParserException.h" 00026 #include "xmlpull/XmlUtils.h" 00027 00028 XmlSerializer::XmlSerializer(std::ostream &os,std::string enc) 00029 :writer(os), 00030 encoding(enc), 00031 elementStack(16), 00032 nspStack(16), 00033 nspCounts(8), 00034 indent(8) 00035 { 00036 init(); 00037 } 00038 00039 XmlSerializer::XmlSerializer(std::string enc) 00040 :writer(std::cout), 00041 encoding(enc), 00042 elementStack(16), 00043 nspStack(16), 00044 nspCounts(8), 00045 indent(8) 00046 { 00047 init(); 00048 } 00049 00050 XmlSerializer::~XmlSerializer() 00051 { 00052 } 00053 00054 void 00055 XmlSerializer::init() 00056 { 00057 nspCounts[0] = 2; 00058 nspCounts[1] = 2; 00059 nspStack[0] = ""; 00060 nspStack[1] = ""; 00061 nspStack[2] = "xml"; 00062 nspStack[3] = "http://www.w3.org/XML/1998/namespace"; 00063 pending = false; 00064 auto_ = 0; 00065 depth = 0; 00066 if (encoding.find("utf",0)!=std::string::npos) 00067 unicode = true; 00068 else 00069 unicode = false; 00070 } 00071 00072 void 00073 XmlSerializer::check(bool close) 00074 { 00075 if (!pending) 00076 return; 00077 depth++; 00078 pending = false; 00079 00080 if (indent.size() <= depth) { 00081 indent.resize(depth + 4); 00082 } 00083 indent[depth] = indent[depth - 1]; 00084 00085 for (int i = nspCounts[depth - 1]; 00086 i < nspCounts[depth]; 00087 i++) { 00088 00089 writer<<' '; 00090 writer<<"xmlns"; 00091 if (""!=nspStack[i * 2]) { 00092 writer<<':'; 00093 writer<<nspStack[i * 2]; 00094 } 00095 else if (getNamespace() != "" && nspStack[i * 2 + 1]!="") 00096 exception("Cannot set default namespace for elements in no namespace"); 00097 writer<<"=\""; 00098 writeEscaped(nspStack[i * 2 + 1], '"'); 00099 writer<<'"'; 00100 } 00101 00102 if (nspCounts.size() <= depth + 1) { 00103 nspCounts.resize(depth + 8); 00104 } 00105 00106 nspCounts[depth + 1] = nspCounts[depth]; 00107 // nspCounts[depth + 2] = nspCounts[depth]; 00108 00109 writer<<(close ? " />" : ">"); 00110 } 00111 00112 void 00113 XmlSerializer::writeEscaped(std::string s, int quot) 00114 { 00115 00116 for (size_t i = 0; i < s.length(); i++) { 00117 unsigned char c = s[i]; 00118 switch (c) { 00119 case '\n': 00120 case '\r': 00121 case '\t': 00122 if(quot == -1) 00123 writer<<c; 00124 else 00125 writer<<"&#"+((int) c)+';'; 00126 break; 00127 case '&' : 00128 writer<<"&"; 00129 break; 00130 case '>' : 00131 writer<<">"; 00132 break; 00133 case '<' : 00134 writer<<"<"; 00135 break; 00136 case '"' : 00137 case '\'' : 00138 if (c == quot) { 00139 writer<<(c == '"' ? """ : "'"); 00140 break; 00141 } 00142 default : 00143 //if(c < ' ') 00144 // exception("Illegal control code:"+((int) c)); 00145 00146 if (c >= ' ' && c !='@' && (c < 127 || unicode)) 00147 writer<<c; 00148 else 00149 writer<<"&#" << ((int) c) << ";"; 00150 } 00151 } 00152 } 00153 00154 00155 void 00156 XmlSerializer::docdecl(std::string dd) 00157 { 00158 writer<<"<!DOCTYPE"; 00159 writer<<dd; 00160 writer<<">"; 00161 } 00162 00163 void 00164 XmlSerializer::endDocument() { 00165 while (depth > 0) { 00166 endTag( 00167 elementStack[depth * 3 - 3], 00168 elementStack[depth * 3 - 1]); 00169 } 00170 flush(); 00171 } 00172 00173 void 00174 XmlSerializer::entityRef(std::string name) 00175 { 00176 check(false); 00177 writer<<'&'; 00178 writer<<name; 00179 writer<<';'; 00180 } 00181 00182 bool 00183 XmlSerializer:: getFeature(std::string name) { 00184 //return false; 00185 return ("http://xmlpull.org/v1/doc/features.html#indent-output" == name) 00186 ? indent[depth] 00187 : false; 00188 } 00189 00190 std::string 00191 XmlSerializer::getPrefix(std::string ns, bool create) 00192 { 00193 return getPrefix(ns, false, create); 00194 } 00195 00196 00197 std::string 00198 XmlSerializer::getPrefix(std::string ns, 00199 bool includeDefault, 00200 bool create) 00201 { 00202 00203 for (int i = nspCounts[depth + 1] * 2 - 2; 00204 i >= 0; 00205 i -= 2) { 00206 00207 if (nspStack[i + 1] == ns 00208 && (includeDefault || nspStack[i]!="")) { 00209 std::string cand = nspStack[i]; 00210 for (int j = i + 2; 00211 j < nspCounts[depth + 1] * 2; 00212 j++) { 00213 if (nspStack[j]==cand) { 00214 cand = ""; 00215 break; 00216 } 00217 } 00218 if (cand != "") 00219 return cand; 00220 } 00221 } 00222 00223 if (!create) 00224 return ""; 00225 00226 std::string prefix; 00227 00228 if (ns=="") 00229 prefix = ""; 00230 else { 00231 do { 00232 prefix = "n" + (auto_++); 00233 for (int i = nspCounts[depth + 1] * 2 - 2; 00234 i >= 0; 00235 i -= 2) { 00236 if (prefix==nspStack[i]) { 00237 prefix = ""; 00238 break; 00239 } 00240 } 00241 } 00242 while (prefix == ""); 00243 } 00244 00245 bool p = pending; 00246 pending = false; 00247 setPrefix(prefix, ns); 00248 pending = p; 00249 return prefix; 00250 } 00251 00252 void 00253 XmlSerializer::ignorableWhitespace(std::string s) 00254 { 00255 text(s); 00256 } 00257 00258 void 00259 XmlSerializer::setFeature(std::string name, bool value) 00260 { 00261 if ("http://xmlpull.org/v1/doc/features.html#indent-output"==name) { 00262 indent[depth] = value; 00263 } 00264 else 00265 exception("Unsupported Feature"); 00266 } 00267 00268 void 00269 XmlSerializer::setPrefix(std::string prefix, std::string nsp) 00270 { 00271 check(false); 00272 std::string defined = getPrefix(nsp, true, false); 00273 00274 // boil out if already defined 00275 00276 if (prefix==defined) 00277 return; 00278 00279 int pos = (nspCounts[depth + 1]++) << 1; 00280 00281 if (nspStack.size() < pos + 1) { 00282 nspStack.resize(nspStack.size() + 16); 00283 } 00284 00285 nspStack[pos++] = prefix; 00286 nspStack[pos] = nsp; 00287 } 00288 00289 void 00290 XmlSerializer::startDocument(std::string enc, 00291 bool standalone) 00292 { 00293 writer<<"<?xml version='1.0' "; 00294 00295 if (encoding != "") { 00296 this->encoding = enc; 00297 if (encoding.find("utf",0)!=std::string::npos) 00298 unicode = true; 00299 } 00300 00301 if (encoding != "") { 00302 writer<<"encoding='"; 00303 writer<<encoding; 00304 writer<<"' "; 00305 } 00306 00307 writer<<"standalone='"; 00308 writer<<(standalone ? "yes" : "no"); 00309 writer<<"' "; 00310 writer<<"?>"; 00311 } 00312 00313 XmlSerializer& 00314 XmlSerializer::startTag(std::string nsp, std::string name) 00315 { 00316 check(false); 00317 00318 // if (namespace == "") 00319 // namespace = ""; 00320 00321 if (indent[depth]) { 00322 writer<<"\r\n"; 00323 for (int i = 0; i < depth; i++) 00324 writer<<" "; 00325 } 00326 00327 int esp = depth * 3; 00328 if (elementStack.size() < esp + 3) { 00329 elementStack.resize(elementStack.size() + 16); 00330 } 00331 00332 std::string prefix = 00333 nsp == "" 00334 ? "" 00335 : getPrefix(nsp, true, true); 00336 00337 if (nsp=="") { 00338 for (int i = nspCounts[depth]; 00339 i < nspCounts[depth + 1]; 00340 i++) { 00341 00342 if (nspStack[i * 2]== "" && nspStack[i * 2 + 1]!= "") { 00343 exception("Cannot set default namespace for elements in no namespace"); 00344 } 00345 } 00346 } 00347 00348 elementStack[esp++] = nsp; 00349 elementStack[esp++] = prefix; 00350 elementStack[esp] = name; 00351 00352 writer<<'<'; 00353 if (prefix!="") { 00354 writer<<prefix; 00355 writer<<':'; 00356 } 00357 00358 writer<<name; 00359 00360 pending = true; 00361 return *this; 00362 } 00363 00364 XmlSerializer& 00365 XmlSerializer::attribute(std::string nsp, 00366 std::string name, 00367 std::string value) 00368 { 00369 if (!pending) 00370 exception("illegal position for attribute"); 00371 00372 // int cnt = nspCounts[depth]; 00373 00374 if (nsp == "") 00375 nsp = ""; 00376 00377 // depth--; 00378 // pending = false; 00379 00380 std::string prefix =(nsp=="")? "": getPrefix(nsp, false, true); 00381 00382 // pending = true; 00383 // depth++; 00384 00385 /* if (cnt != nspCounts[depth]) { 00386 writer<<' '; 00387 writer<<"xmlns"; 00388 if (nspStack[cnt * 2] != "") { 00389 writer<<':'; 00390 writer<<nspStack[cnt * 2]; 00391 } 00392 writer<<"=\""; 00393 writeEscaped(nspStack[cnt * 2 + 1], '"'); 00394 writer<<'"'; 00395 } 00396 */ 00397 00398 writer<<' '; 00399 if (prefix!="") { 00400 writer<<prefix; 00401 writer<<':'; 00402 } 00403 writer<<name; 00404 writer<<'='; 00405 char q = value.find('"') == std::string::npos ? '"' : '\''; 00406 writer<<q; 00407 writeEscaped(value, q); 00408 writer<<q; 00409 return *this; 00410 } 00411 00412 void 00413 XmlSerializer::flush() 00414 { 00415 check(false); 00416 writer.flush(); 00417 } 00418 00419 XmlSerializer& 00420 XmlSerializer::endTag(std::string nsp, std::string name) 00421 { 00422 00423 if (!pending) 00424 depth--; 00425 // if (nsp == "") 00426 // nsp = ""; 00427 00428 if ((nsp == "" 00429 && elementStack[depth * 3] != "") 00430 || (nsp != "" 00431 && nsp!=elementStack[depth * 3]) 00432 || elementStack[depth * 3 + 2] != name) 00433 00434 exception("</{"+nsp+"}"+name+"> does not match start"); 00435 00436 if (pending) { 00437 check(true); 00438 depth--; 00439 } 00440 else { 00441 if (indent[depth + 1]) { 00442 writer<<"\r\n"; 00443 for (int i = 0; i < depth; i++) 00444 writer<<" "; 00445 } 00446 00447 writer<<"</"; 00448 std::string prefix = elementStack[depth * 3 + 1]; 00449 if (prefix != "") { 00450 writer<<prefix; 00451 writer<<':'; 00452 } 00453 writer<<name; 00454 writer<<'>'; 00455 } 00456 00457 nspCounts[depth + 1] = nspCounts[depth]; 00458 return *this; 00459 } 00460 00461 00462 std::string 00463 XmlSerializer::getNamespace() 00464 { 00465 return getDepth() == 0 ? "" : elementStack[getDepth() * 3 - 3]; 00466 } 00467 00468 std::string 00469 XmlSerializer::getName() 00470 { 00471 return getDepth() == 0 ? "" : elementStack[getDepth() * 3 - 1]; 00472 } 00473 00474 int 00475 XmlSerializer::getDepth() { 00476 return pending ? depth + 1 : depth; 00477 } 00478 00479 XmlSerializer& 00480 XmlSerializer::text(std::string txt){ 00481 check(false); 00482 indent[depth] = false; 00483 writeEscaped(txt, -1); 00484 return *this; 00485 } 00486 00487 XmlSerializer& 00488 XmlSerializer::text(std::string txt, int start, int len) 00489 { 00490 text(txt.substr(start, len)); 00491 return *this; 00492 } 00493 00494 void 00495 XmlSerializer::cdsect(std::string data) 00496 { 00497 check(false); 00498 writer<<"<![CDATA["; 00499 writer<<data; 00500 writer<<"]]>"; 00501 } 00502 00503 void 00504 XmlSerializer::comment(std::string comment) { 00505 check(false); 00506 writer<<"<!--"; 00507 writer<<comment; 00508 writer<<"-->"; 00509 } 00510 00511 void 00512 XmlSerializer::processingInstruction(std::string pi) 00513 { 00514 check(false); 00515 writer<<"<?"; 00516 writer<<pi; 00517 writer<<"?>"; 00518 } 00519 00520 void 00521 XmlSerializer::exception (std::string desc) 00522 { 00523 XmlPullParserException e (desc,elementStack.front(),0,0); 00524 throw e; 00525 }