00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "xml/persxml.h"
00029 #include "xml/defxml.hpp"
00030 #include "xml/storexml.hpp"
00031 #include "xml/sxml.hpp"
00032 #include "xml/sxs.hpp"
00033
00034 #include "base/memory.hpp"
00035 #include "base/list.hpp"
00036 #include "base/map.hpp"
00037 #include "base/stack.hpp"
00038 #include "base/string.hpp"
00039 #include "base/template.hpp"
00040 #include "base/common.hpp"
00041
00042 BEGIN_TERIMBER_NAMESPACE
00043 #pragma pack(4)
00044
00046 xml_persistor::xml_persistor(byte_consumer& stream,
00047 const xml_document& doc,
00048 mem_pool_t& small_pool,
00049 mem_pool_t& big_pool,
00050 bool validate,
00051 bool save_doc_type,
00052 size_t size) :
00053 _xml_size(__max(size, os_def_size)),
00054 _stream(stream),
00055 _doc(doc),
00056 _small_pool(small_pool),
00057 _big_pool(big_pool),
00058 _validate(validate),
00059 _save_doc_type(save_doc_type)
00060 {
00061 _tmp_allocator = _small_pool.loan_object();
00062 if (_xml_size <= os_def_size)
00063 _stack_allocator = _small_pool.loan_object(_xml_size);
00064 else
00065 _stack_allocator = _big_pool.loan_object();
00066 }
00067
00068 xml_persistor::~xml_persistor()
00069 {
00070 _small_pool.return_object(_tmp_allocator);
00071 if (_xml_size <= os_def_size)
00072 _small_pool.return_object(_stack_allocator);
00073 else
00074 _big_pool.return_object(_stack_allocator);
00075 }
00076
00077 const char*
00078 xml_persistor::get_error() const
00079 {
00080 return _error;
00081 }
00082
00083 bool
00084 xml_persistor::persist()
00085 {
00086 try
00087 {
00088 _element_stack.clear();
00089 _stack_allocator->reset();
00090 _element_stack.push(*_stack_allocator, &_doc);
00091 _in_doc_type = false;
00092 while (!_element_stack.empty())
00093 {
00094 switch (_element_stack.top()->_decl->get_type())
00095 {
00096 case DOCUMENT_NODE:
00097 persistDocument();
00098 break;
00099 case ELEMENT_NODE:
00100 _in_doc_type ? persistElementDecl() : persistElement();
00101 break;
00102 case ATTRIBUTE_NODE:
00103 assert(!_in_doc_type);
00104 persistAttributes();
00105 break;
00106 case TEXT_NODE:
00107 persistText();
00108 break;
00109 case CDATA_SECTION_NODE:
00110 persistCDATA();
00111 break;
00112 case PROCESSING_INSTRUCTION_NODE:
00113 persistPI();
00114 break;
00115 case COMMENT_NODE:
00116 persistComment();
00117 break;
00118 case DOCUMENT_TYPE_NODE:
00119 persistDocType();
00120 break;
00121 case ENTITY_NODE:
00122 assert(_in_doc_type);
00123 persistEntityDecl();
00124 break;
00125 case NOTATION_NODE:
00126 assert(_in_doc_type);
00127 persistNotationDecl();
00128 break;
00129 default:
00130 assert(false);
00131 }
00132
00133
00134 }
00135
00136 _stream.flush();
00137 }
00138 catch (exception& x)
00139 {
00140 _error = x.what();
00141 return false;
00142 }
00143 catch (...)
00144 {
00145 _error = "Unexpected exception has been thrown";
00146 return false;
00147 }
00148
00149 return true;
00150 }
00151
00152 void
00153 xml_persistor::restore_stack(bool makeShift)
00154 {
00155 while (!_element_stack.empty())
00156 {
00157 const xml_tree_node* node = _element_stack.top();
00158 const xml_element* el = 0;
00159
00160 switch (node->_decl->get_type())
00161 {
00162 case ELEMENT_NODE:
00163 if (!_in_doc_type && (el = static_cast< const xml_element* >(node)) && el->has_children())
00164 {
00165 if (makeShift)
00166 {
00167 size_t shift = _element_stack.size() - 1;
00168 while (--shift)
00169 _stream.push(ch_hor_tab);
00170 }
00171 else
00172 makeShift = true;
00173
00174 _stream.push(ch_open_angle);
00175 _stream.push(ch_forward_slash);
00176 _stream.push(el->_decl->_name);
00177 _stream.push(ch_close_angle);
00178 _stream.push(ch_cr);
00179 _stream.push(ch_lf);
00180 }
00181 break;
00182 case DOCUMENT_TYPE_NODE:
00183 if (_save_doc_type)
00184 {
00185 _stream.push(ch_close_square);
00186 _stream.push(ch_close_angle);
00187 _stream.push(ch_cr);
00188 _stream.push(ch_lf);
00189 }
00190
00191 _in_doc_type = false;
00192 break;
00193 default:
00194 break;
00195 }
00196
00197
00198 _element_stack.pop();
00199
00200
00201 if (node->_right)
00202 {
00203
00204 _element_stack.push(*_stack_allocator, node->_right);
00205 return;
00206 }
00207 }
00208
00209 _stack_allocator->reset();
00210 }
00211
00212 void
00213 xml_persistor::persistDocument()
00214 {
00215
00216 static const char* xmlDeclStandaloneYes = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>";
00217 static const char* xmlDeclStandaloneNo = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>";
00218
00219 _stream.push(_doc._standalone == 0 ? xmlDeclStandaloneNo : xmlDeclStandaloneYes);
00220
00221 _stream.push(ch_cr);
00222 _stream.push(ch_lf);
00223 const xml_container* el = static_cast< const xml_container* >(_element_stack.top());
00224 if (el->_first_child)
00225 {
00226 _element_stack.push(*_stack_allocator, el->_first_child);
00227 return;
00228 }
00229 else
00230 restore_stack();
00231 }
00232
00233 void
00234 xml_persistor::persistDocType()
00235 {
00236 if (!_save_doc_type)
00237 {
00238 restore_stack();
00239 return;
00240 }
00241
00242
00243 _stream.push(ch_open_angle);
00244 _stream.push(ch_bang);
00245 _stream.push(str_DOCTYPE);
00246 _stream.push(ch_space);
00247 _stream.push(_doc._doc_name);
00248 _stream.push(ch_space);
00249
00250 if (_doc._system_id.length())
00251 {
00252
00253 if (_doc._public_id.length())
00254 {
00255 _stream.push(str_PUBLIC);
00256 _stream.push(ch_space);
00257 _stream.push(ch_double_quote);
00258 _stream.push(_doc._public_id);
00259 _stream.push(ch_double_quote);
00260 _stream.push(ch_space);
00261 }
00262 else
00263 {
00264 _stream.push(str_SYSTEM);
00265 _stream.push(ch_space);
00266 }
00267
00268 _stream.push(ch_double_quote);
00269 _stream.push(_doc._system_id);
00270 _stream.push(ch_double_quote);
00271
00272 const xml_tree_node* el = _element_stack.top();
00273
00274 _element_stack.pop();
00275
00276 if (el->_right)
00277 {
00278
00279 _element_stack.push(*_stack_allocator, el->_right);
00280 _stream.push(ch_close_angle);
00281 _stream.push(ch_cr);
00282 _stream.push(ch_lf);
00283 return;
00284 }
00285
00286 _stream.push(ch_close_angle);
00287 _stream.push(ch_cr);
00288 _stream.push(ch_lf);
00289 restore_stack();
00290 }
00291 else if (!_doc.is_on_fly())
00292 {
00293
00294 _in_doc_type = true;
00295 _stream.push(ch_open_square);
00296 _stream.push(ch_cr);
00297 _stream.push(ch_lf);
00298 const xml_container* el = static_cast< const xml_container* >(_element_stack.top());
00299
00300 if (el->_first_child)
00301 {
00302 _element_stack.push(*_stack_allocator, el->_first_child);
00303 return;
00304 }
00305
00306 restore_stack();
00307 }
00308 else
00309 {
00310 _stream.push(ch_open_square);
00311 _stream.push(ch_cr);
00312 _stream.push(ch_lf);
00313
00314
00315 const entity_decl_map_t& en_map = _doc.get_entityMap();
00316 for (entity_decl_map_t::const_iterator iterEn = en_map.begin(); iterEn != en_map.end(); ++iterEn)
00317 persistEntityDecl(&*iterEn);
00318
00319 const notation_decl_map_t& not_map = _doc.get_notationMap();
00320 for (notation_decl_map_t::const_iterator iterNot = not_map.begin(); iterNot != not_map.end(); ++iterNot)
00321 persistNotationDecl(&*iterNot);
00322
00323
00324 const element_decl_map_t& el_map = _doc.get_elementMap();
00325 for (element_decl_map_t::const_iterator iterEl = el_map.begin(); iterEl != el_map.end(); ++iterEl)
00326 persistElementDecl(&*iterEl);
00327
00328 restore_stack();
00329 }
00330 }
00331
00332 void
00333 xml_persistor::persistEntityDecl(const entityDecl* decl_)
00334 {
00335 const entityDecl* decl = decl_ ? decl_ : static_cast< const entityDecl* >(_element_stack.top()->_decl);
00336
00337 if (decl->_is_encoded_char)
00338 return;
00339
00340
00341
00342
00343
00344
00345 _stream.push(ch_open_angle);
00346 _stream.push(ch_bang);
00347 _stream.push(str_ENTITY);
00348 _stream.push(ch_space);
00349 if (decl->_is_parameter)
00350 {
00351
00352 _stream.push(ch_percent);
00353 _stream.push(ch_space);
00354 _stream.push(decl->_name);
00355 _stream.push(ch_space);
00356
00357 if (decl->_is_in_subset)
00358 {
00359
00360 if (decl->_publicId.length())
00361 {
00362 _stream.push(str_PUBLIC);
00363 _stream.push(ch_space);
00364 _stream.push(decl->_publicId);
00365 _stream.push(ch_space);
00366 }
00367
00368 _stream.push(str_SYSTEM);
00369 _stream.push(ch_space);
00370 _stream.push(decl->_systemId);
00371 }
00372 else
00373 {
00374
00375 _stream.push(ch_double_quote);
00376 persistValue(decl->_value);
00377 _stream.push(ch_double_quote);
00378 }
00379 }
00380 else
00381 {
00382
00383 _stream.push(decl->_name);
00384 _stream.push(ch_space);
00385
00386 if (decl->_value.length())
00387 {
00388 _stream.push(ch_double_quote);
00389 persistValue(decl->_value);
00390 _stream.push(ch_double_quote);
00391 }
00392 else
00393 {
00394 if (decl->_publicId.length())
00395 {
00396 _stream.push(str_PUBLIC);
00397 _stream.push(ch_space);
00398 _stream.push(decl->_publicId);
00399 _stream.push(ch_space);
00400 }
00401
00402 _stream.push(str_SYSTEM);
00403 _stream.push(ch_space);
00404 _stream.push(decl->_systemId);
00405
00406 if (decl->_notation.length())
00407 {
00408
00409 _stream.push(ch_space);
00410 _stream.push(str_NDATA);
00411 _stream.push(ch_space);
00412 _stream.push(decl->_notation);
00413 }
00414 }
00415 }
00416
00417 _stream.push(ch_close_angle);
00418 _stream.push(ch_cr);
00419 _stream.push(ch_lf);
00420 if (!decl_)
00421 restore_stack();
00422 }
00423
00424 void
00425 xml_persistor::persistNotationDecl(const notationDecl* decl_)
00426 {
00427 const notationDecl* decl = decl_ ? decl_ : static_cast< const notationDecl* >(_element_stack.top()->_decl);
00428
00429 _stream.push(ch_open_angle);
00430 _stream.push(ch_bang);
00431 _stream.push(str_NOTATION);
00432 _stream.push(ch_space);
00433 _stream.push(decl->_name);
00434 if (decl->_publicId.length())
00435 {
00436 _stream.push(ch_space);
00437 _stream.push(str_PUBLIC);
00438 _stream.push(ch_space);
00439 _stream.push(decl->_publicId);
00440 }
00441
00442 if (decl->_systemId.length())
00443 {
00444 _stream.push(ch_space);
00445 _stream.push(str_SYSTEM);
00446 _stream.push(ch_space);
00447 _stream.push(decl->_systemId);
00448 }
00449
00450 _stream.push(ch_close_angle);
00451 _stream.push(ch_cr);
00452 _stream.push(ch_lf);
00453 if (!decl_)
00454 restore_stack();
00455 }
00456
00457 void
00458 xml_persistor::persistElementDecl(const elementDecl* decl_)
00459 {
00460 const elementDecl* decl = decl_ ? decl_ : static_cast< const elementDecl* >(_element_stack.top()->_decl);
00461
00462 _stream.push(ch_open_angle);
00463 _stream.push(ch_bang);
00464 _stream.push(str_ELEMENT);
00465 _stream.push(ch_space);
00466 _stream.push(decl->_name);
00467 _stream.push(ch_space);
00468 switch (decl->_content)
00469 {
00470 case CONTENT_EMPTY:
00471 _stream.push(str_EMPTY);
00472 break;
00473 case CONTENT_ANY:
00474 _stream.push(str_ANY);
00475 break;
00476 case CONTENT_MIXED:
00477 {
00478 _stream.push(ch_open_paren);
00479 if (decl->_token->_rule == DFA_LEAF)
00480 {
00481 persistMixed(decl->_token);
00482 _stream.push(ch_close_paren);
00483 }
00484 else
00485 {
00486 persistMixed(decl->_token->_first);
00487 _stream.push(ch_close_paren);
00488 _stream.push(ch_asterisk);
00489 }
00490 }
00491 break;
00492 case CONTENT_CHILDREN:
00493 switch (decl->_token->_rule)
00494 {
00495 case DFA_QUESTION:
00496 _stream.push(ch_open_paren);
00497 persistChildren(decl->_token->_first, decl->_token->_first->_rule);
00498 _stream.push(ch_close_paren);
00499 _stream.push(ch_question);
00500 break;
00501 case DFA_ASTERISK:
00502 _stream.push(ch_open_paren);
00503 persistChildren(decl->_token->_first, decl->_token->_first->_rule);
00504 _stream.push(ch_close_paren);
00505 _stream.push(ch_asterisk);
00506 break;
00507 case DFA_PLUS:
00508 _stream.push(ch_open_paren);
00509 persistChildren(decl->_token->_first, decl->_token->_first->_rule);
00510 _stream.push(ch_close_paren);
00511 _stream.push(ch_plus);
00512 break;
00513 default:
00514 _stream.push(ch_open_paren);
00515 persistChildren(decl->_token, decl->_token->_rule);
00516 _stream.push(ch_close_paren);
00517 break;
00518 }
00519 default:
00520 break;
00521 }
00522 _stream.push(ch_close_angle);
00523 _stream.push(ch_cr);
00524 _stream.push(ch_lf);
00525
00526 if (!decl->_attributes.empty())
00527 {
00528
00529 _stream.push(ch_open_angle);
00530 _stream.push(ch_bang);
00531 _stream.push(str_ATTRLIST);
00532 _stream.push(ch_space);
00533 _stream.push(decl->_name);
00534
00535
00536 for (attribute_decl_map_t::const_iterator iterAttr = decl->_attributes.begin(); iterAttr != decl->_attributes.end(); ++iterAttr)
00537 persistAttributeDecl(*iterAttr);
00538
00539 _stream.push(ch_cr);
00540 _stream.push(ch_lf);
00541 _stream.push(ch_close_angle);
00542 _stream.push(ch_cr);
00543 _stream.push(ch_lf);
00544 }
00545
00546 if (!decl_)
00547 restore_stack();
00548 }
00549
00550 void
00551 xml_persistor::persistMixed(const dfa_token* parent)
00552 {
00553 switch (parent->_rule)
00554 {
00555 case DFA_LEAF:
00556 case DFA_ANY:
00557 if (parent->_decl)
00558 {
00559 _stream.push(ch_pipe);
00560 _stream.push(parent->_decl->_name);
00561 }
00562 else
00563 _stream.push(str__PCDATA);
00564 break;
00565 case DFA_CHOICE:
00566 case DFA_SEQUENCE:
00567 {
00568
00569 persistMixed(parent->_first);
00570
00571 if (parent->_last)
00572 persistMixed(parent->_last);
00573 }
00574 break;
00575 case DFA_QUESTION:
00576 _stream.push(ch_question);
00577 persistMixed(parent->_first);
00578 break;
00579 case DFA_ASTERISK:
00580 _stream.push(ch_asterisk);
00581 persistMixed(parent->_first);
00582 break;
00583 case DFA_PLUS:
00584 _stream.push(ch_plus);
00585 persistMixed(parent->_first);
00586 break;
00587 default:
00588 assert(false);
00589 }
00590 }
00591
00592 void
00593 xml_persistor::persistChildren(const dfa_token* parent, dfaRule prevRule)
00594 {
00595
00596 dfaRule curRule = parent->_rule;
00597
00598 switch (curRule)
00599 {
00600 case DFA_ANY:
00601 _stream.push(str_ANY);
00602 break;
00603 case DFA_LEAF:
00604 _stream.push(parent->_decl->_name);
00605 break;
00606 case DFA_CHOICE:
00607 if (DFA_CHOICE != prevRule) _stream.push(ch_open_paren);
00608 persistChildren(parent->_first, curRule);
00609 _stream.push(ch_pipe);
00610 persistChildren(parent->_last, curRule);
00611 if (DFA_CHOICE != prevRule) _stream.push(ch_close_paren);
00612 break;
00613 case DFA_SEQUENCE:
00614 if (DFA_SEQUENCE != prevRule) _stream.push(ch_open_paren);
00615 persistChildren(parent->_first, curRule);
00616 _stream.push(ch_comma);
00617 persistChildren(parent->_last, curRule);
00618 if (DFA_SEQUENCE != prevRule) _stream.push(ch_close_paren);
00619 break;
00620 case DFA_QUESTION:
00621 persistChildren(parent->_first, prevRule);
00622 _stream.push(ch_question);
00623 break;
00624 case DFA_ASTERISK:
00625 persistChildren(parent->_first, prevRule);
00626 _stream.push(ch_asterisk);
00627 break;
00628 case DFA_PLUS:
00629 persistChildren(parent->_first, prevRule);
00630 _stream.push(ch_plus);
00631 break;
00632 default:
00633 assert(false);
00634 }
00635 }
00636
00637 void
00638 xml_persistor::persistAttributeDecl(const attributeDecl& decl)
00639 {
00640
00641 _stream.push(ch_cr);
00642 _stream.push(ch_lf);
00643 _stream.push(decl._name);
00644 _stream.push(ch_space);
00645 switch (decl._atype)
00646 {
00647 case ATTR_TYPE_CDATA:
00648 _stream.push(str_CDATA);
00649 break;
00650 case ATTR_TYPE_ID:
00651 _stream.push(str_ID);
00652 break;
00653 case ATTR_TYPE_IDREF:
00654 _stream.push(str_IDREF);
00655 break;
00656 case ATTR_TYPE_IDREFS:
00657 _stream.push(str_IDREFS);
00658 break;
00659 case ATTR_TYPE_ENTITY:
00660 _stream.push(str_ENTITY);
00661 break;
00662 case ATTR_TYPE_ENTITIES:
00663 _stream.push(str_ENTITIES);
00664 break;
00665 case ATTR_TYPE_NMTOKEN:
00666 _stream.push(str_NMTOKEN);
00667 break;
00668 case ATTR_TYPE_NMTOKENS:
00669 _stream.push(str_NMTOKENS);
00670 break;
00671 case ATTR_TYPE_NOTATION:
00672 _stream.push(str_NOTATION);
00673 _stream.push(ch_space);
00674 case ATTR_TYPE_ENUMERATION:
00675 if (!decl._enum.empty())
00676 {
00677 _stream.push(ch_open_paren);
00678 for (_list< enumNodeDecl >::const_iterator iterEn = decl._enum.begin(); iterEn != decl._enum.end(); ++iterEn)
00679 {
00680 if (iterEn != decl._enum.begin())
00681 _stream.push(ch_pipe);
00682 _stream.push(iterEn->_value);
00683 }
00684
00685 _stream.push(ch_close_paren);
00686 }
00687 break;
00688 default:
00689 assert(false);
00690 }
00691
00692 _stream.push(ch_space);
00693 switch (decl._rule)
00694 {
00695 case ATTR_RULE_REQUIRED:
00696 _stream.push(ch_pound);
00697 _stream.push(str_REQUIRED);
00698 break;
00699 case ATTR_RULE_IMPLIED:
00700 _stream.push(ch_pound);
00701 _stream.push(str_IMPLIED);
00702 break;
00703 case ATTR_RULE_FIXED:
00704 _stream.push(ch_pound);
00705 _stream.push(str_FIXED);
00706 break;
00707 case ATTR_RULE_DEFAULT:
00708 break;
00709 default:
00710 assert(false);
00711 }
00712
00713 if (decl._defval.length())
00714 {
00715 _stream.push(ch_space);
00716 _stream.push(ch_double_quote);
00717 _stream.push(decl._defval);
00718 _stream.push(ch_double_quote);
00719 }
00720 }
00721
00722 void
00723 xml_persistor::persistElement()
00724 {
00725 const xml_element* el = static_cast< const xml_element* >(_element_stack.top());
00726
00727 size_t shift = _element_stack.size() - 1;
00728 while (--shift)
00729 _stream.push(ch_hor_tab);
00730
00731 _stream.push(ch_open_angle);
00732 _stream.push(el->_decl->_name);
00733 if (el->has_attributes())
00734 persistAttributes();
00735 if (el->has_children())
00736 {
00737 _stream.push(ch_close_angle);
00738
00739 if (el->_first_child->_decl->get_type() != TEXT_NODE)
00740 {
00741 _stream.push(ch_cr);
00742 _stream.push(ch_lf);
00743 }
00744
00745 if (el->_first_child)
00746 {
00747 _element_stack.push(*_stack_allocator, el->_first_child);
00748 return;
00749 }
00750 }
00751 else
00752 {
00753 _stream.push(ch_forward_slash);
00754 _stream.push(ch_close_angle);
00755 _stream.push(ch_cr);
00756 _stream.push(ch_lf);
00757 }
00758
00759
00760 restore_stack();
00761 }
00762
00763 void
00764 xml_persistor::persistAttributes()
00765 {
00766 const xml_element* el = static_cast< const xml_element* >(_element_stack.top());
00767 for (xml_tree_node* I = el->_first_attr; I; I = I->_right)
00768 {
00769 _stream.push(ch_space);
00770 const attributeDecl* decl = I->cast_to_attribute();
00771 _stream.push(decl->_name);
00772 _stream.push(ch_equal);
00773 _stream.push(ch_double_quote);
00774 persistValue(decl->persist_attribute(xml_value_node::cast_to_node_value(I)->_value, _tmp_allocator));
00775 _tmp_allocator->reset();
00776 _stream.push(ch_double_quote);
00777 }
00778 }
00779
00780 void
00781 xml_persistor::persistText()
00782 {
00783 persistValue(xml_value_node::cast_to_node_value(_element_stack.top())->_value.strVal, true);
00784 restore_stack(false);
00785 }
00786
00787 void
00788 xml_persistor::persistCDATA()
00789 {
00790
00791
00792
00793
00794
00795 _stream.push(ch_open_angle);
00796 _stream.push(ch_bang);
00797 _stream.push(ch_open_square);
00798 _stream.push(str_CDATA);
00799 _stream.push(ch_open_square);
00800 _stream.push(xml_value_node::cast_to_node_value(_element_stack.top())->_value.strVal);
00801 _stream.push(ch_close_square);
00802 _stream.push(ch_close_square);
00803 _stream.push(ch_close_angle);
00804 _stream.push(ch_cr);
00805 _stream.push(ch_lf);
00806 restore_stack();
00807 }
00808
00809 void
00810 xml_persistor::persistComment()
00811 {
00812
00813 _stream.push(ch_open_angle);
00814 _stream.push(ch_bang);
00815 _stream.push(ch_dash);
00816 _stream.push(ch_dash);
00817 _stream.push(xml_value_node::cast_to_node_value(_element_stack.top())->_value.strVal);
00818 _stream.push(ch_dash);
00819 _stream.push(ch_dash);
00820 _stream.push(ch_close_angle);
00821 _stream.push(ch_cr);
00822 _stream.push(ch_lf);
00823 restore_stack();
00824 }
00825
00826 void
00827 xml_persistor::persistPI()
00828 {
00829
00830
00831 _stream.push(ch_open_angle);
00832 _stream.push(ch_question);
00833 _stream.push(_element_stack.top()->_decl->_name);
00834 const char* value = xml_value_node::cast_to_node_value(_element_stack.top())->_value.strVal;
00835 if (value)
00836 {
00837 _stream.push(ch_space);
00838 _stream.push(value);
00839 }
00840 _stream.push(ch_question);
00841 _stream.push(ch_close_angle);
00842 _stream.push(ch_cr);
00843 _stream.push(ch_lf);
00844 restore_stack();
00845 }
00846
00847 void
00848 xml_persistor::persistValue(const char* value, bool charData)
00849 {
00850 if (!value)
00851 return;
00852
00853 while (*value)
00854 {
00855 switch (*value)
00856 {
00857 case ch_ampersand:
00858 _stream.push(ch_ampersand);
00859 _stream.push(str_amp);
00860 _stream.push(ch_semicolon);
00861 break;
00862 case ch_double_quote:
00863 if (charData)
00864 _stream.push(*value);
00865 else
00866 {
00867 _stream.push(ch_ampersand);
00868 _stream.push(str_quote);
00869 _stream.push(ch_semicolon);
00870 }
00871 break;
00872 case ch_single_quote:
00873 if (charData)
00874 _stream.push(*value);
00875 else
00876 {
00877 _stream.push(ch_ampersand);
00878 _stream.push(str_apos);
00879 _stream.push(ch_semicolon);
00880 }
00881 break;
00882 case ch_open_angle:
00883 _stream.push(ch_ampersand);
00884 _stream.push(str_lt);
00885 _stream.push(ch_semicolon);
00886 break;
00887 case ch_close_angle:
00888 if (charData)
00889 _stream.push(*value);
00890 else
00891 {
00892 _stream.push(ch_ampersand);
00893 _stream.push(str_gt);
00894 _stream.push(ch_semicolon);
00895 }
00896 break;
00897 default:
00898 _stream.push(*value);
00899 break;
00900 }
00901
00902 ++value;
00903 }
00904 }
00905
00906 #pragma pack()
00907 END_TERIMBER_NAMESPACE
00908