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/sxml.hpp"
00029 #include "xml/sxs.hpp"
00030 #include "xml/xmlmodel.h"
00031 #include "xml/defxml.hpp"
00032 #include "xml/declxml.hpp"
00033 #include "xml/miscxml.h"
00034
00035 #include "base/common.hpp"
00036 #include "base/memory.hpp"
00037 #include "base/list.hpp"
00038 #include "base/map.hpp"
00039 #include "base/stack.hpp"
00040 #include "base/string.hpp"
00041 #include "base/template.hpp"
00042
00043 BEGIN_TERIMBER_NAMESPACE
00044 #pragma pack(4)
00045
00047 xml_node::~xml_node()
00048 {
00049 }
00050
00051 xml_node::xml_node(const namedNodeDecl* decl) :
00052 _decl(decl)
00053 {
00054 }
00055
00056 void
00057 xml_node::clear()
00058 {
00059 _decl = 0;
00060 }
00061
00063 xml_tree_node::xml_tree_node(const namedNodeDecl* decl, xml_tree_node* parent) :
00064 xml_node(decl), _parent(parent), _left(0), _right(0)
00065 {
00066 }
00067
00068 xml_tree_node::~xml_tree_node()
00069 {
00070 }
00071
00072 void
00073 xml_tree_node::clear()
00074 {
00075 xml_node::clear();
00076 _parent = 0;
00077 _left = 0;
00078 _right = 0;
00079 }
00080
00082 xml_value_node::~xml_value_node()
00083 {
00084 }
00085
00086 xml_value_node::xml_value_node(const namedNodeDecl* decl, xml_tree_node* parent) :
00087 xml_tree_node(decl, parent)
00088 {
00089 _value.strVal = 0;
00090 }
00091
00092 const char*
00093 xml_value_node::persist(byte_allocator& allocator_) const
00094 {
00095 switch (_decl->get_type())
00096 {
00097 case ATTRIBUTE_NODE:
00098 return cast_to_attribute()->persist_attribute(_value, &allocator_);
00099 default:
00100 return _value.strVal;
00101 }
00102 }
00103
00104 void
00105 xml_value_node::clear()
00106 {
00107 xml_node::clear();
00108 _value.strVal = 0;
00109 }
00110
00112
00113 xml_container::xml_container(const namedNodeDecl* decl, xml_tree_node* parent) :
00114 xml_tree_node(decl, parent), _first_child(0), _last_child(0)
00115 {
00116 }
00117
00118 void
00119 xml_container::clear()
00120 {
00121 xml_tree_node::clear();
00122 _first_child = 0;
00123 _last_child = 0;
00124 }
00125
00126
00127
00129 xml_element::xml_element(const elementDecl* decl, xml_tree_node* parent) :
00130 xml_container(decl, parent), _first_attr(0), _last_attr(0)
00131 {
00132 }
00133
00135 xml_document::xml_document( mem_pool_t& small_manager, mem_pool_t& big_manager,
00136 size_t xml_size,
00137 const xml_grammar* grammar_) :
00138 xml_container(get_document_decl(), 0),
00139 xml_grammar(small_manager, big_manager, xml_size),
00140 _standalone(os_minus_one),
00141 _model_allocator(1024*64),
00142 _on_fly(grammar_ == 0),
00143 _root(0, this),
00144 _doc_type(&_doctype_decl, this)
00145 {
00146 if (grammar_)
00147 {
00148 copy(*grammar_);
00149 _decl = grammar_->find_element_decl(grammar_->_doc_name);
00150 if (!_decl)
00151 exception::_throw("Invalid root element name");
00152 }
00153
00154
00155 container_reset();
00156 }
00157
00158 xml_document::~xml_document()
00159 {
00160 }
00161
00162 void
00163 xml_document::clear()
00164 {
00165 _model_map.clear();
00166 xml_container::clear();
00167 xml_grammar::clear();
00168 _data_allocator.clear_extra();
00169 _model_allocator.clear_extra();
00170 _tmp_allocator.clear_extra();
00171 _root.clear();
00172
00173 _root._parent = this;
00174
00175 _decl = get_document_decl();
00176
00177 _doc_type.clear();
00178
00179 _doc_type._decl = &_doctype_decl;
00180 _doc_type._parent = this;
00181
00182 container_reset();
00183 _on_fly = true;
00184 _standalone = os_minus_one;
00185 }
00186
00187 void
00188 xml_document::add_escaped_symbols()
00189 {
00190 bool wasAdded = false;
00191 entityDecl& decl_apos = add_entity_decl(str_apos, wasAdded);
00192 decl_apos._is_encoded_char = true;
00193 if (wasAdded)
00194 decl_apos._value = str_ch_apos;
00195
00196 entityDecl& decl_quote = add_entity_decl(str_quote, wasAdded);
00197 decl_quote._is_encoded_char = true;
00198 if (wasAdded)
00199 decl_quote._value = str_ch_quote;
00200
00201 entityDecl& decl_amp = add_entity_decl(str_amp, wasAdded);
00202 decl_amp._is_encoded_char = true;
00203 if (wasAdded)
00204 decl_amp._value = str_ch_amp;
00205
00206 entityDecl& decl_lt = add_entity_decl(str_lt, wasAdded);
00207 decl_lt._is_encoded_char = true;
00208 if (wasAdded)
00209 decl_lt._value = str_ch_lt;
00210
00211 entityDecl& decl_gt = add_entity_decl(str_gt, wasAdded);
00212 decl_gt._is_encoded_char = true;
00213 if (wasAdded)
00214 decl_gt._value = str_ch_gt;
00215 }
00216
00217 content_interface*
00218 xml_document::find_model(const elementDecl* decl)
00219 {
00220 model_map_t::iterator iter = _model_map.find(decl);
00221 return iter != _model_map.end() ? *iter : 0;
00222 }
00223
00224 void
00225 xml_document::add_model(const elementDecl* decl, content_interface* model)
00226 {
00227 if (_model_map.find(decl) != _model_map.end())
00228 xml_exception_throw("Dublicate xml model", 0);
00229
00230 _model_map.insert(_model_allocator, decl, model);
00231 }
00232
00234 void
00235 xml_document::validate(xml_element& el)
00236 {
00237 validate_attributes(el);
00238 validate_children(el);
00239 }
00240
00241 void
00242 xml_document::validate_attributes(xml_element& el)
00243 {
00244 for (attribute_decl_map_t::const_iterator iter = el.cast_decl()->_attributes.begin(); iter != el.cast_decl()->_attributes.end(); ++iter)
00245 {
00246 const namedNodeDecl* itdecl = &*iter;
00247
00248 switch (iter->_rule)
00249 {
00250
00251 case attributeRule_MIN:
00252 case attributeRule_MAX:
00253 xml_exception_throw("no rule, for element: ",
00254 (const char*)el._decl->_name,
00255 " and attribute: ",
00256 (const char*)iter->_name,
00257 0);
00258 break;
00259 case ATTR_RULE_DEFAULT:
00260 case ATTR_RULE_REQUIRED:
00261 case ATTR_RULE_FIXED:
00262 {
00263
00264 bool find = false;
00265 if (el.has_attributes())
00266 {
00267 for (const xml_tree_node* iterAttr = el._first_attr; iterAttr; iterAttr = iterAttr->_right)
00268 {
00269 if (iterAttr->_decl == itdecl)
00270 {
00271 find = true;
00272 if (iter->_atype == ATTR_TYPE_CDATA && iter->_rule == ATTR_RULE_FIXED)
00273 {
00274 terimber_xml_value val;
00275 val.strVal = iterAttr->cast_to_attribute()->_defval;
00276 if (compare_value(iterAttr->cast_to_attribute()->_ctype, xml_value_node::cast_to_node_value(&*iterAttr)->_value, val, false, false))
00277 xml_exception_throw("Invalid fixed attribute value, for element: ",
00278 (const char*)el._decl->_name,
00279 " and attribute: ",
00280 (const char*)iter->_name,
00281 0);
00282 }
00283 break;
00284 }
00285 }
00286 }
00287
00288 if (!find)
00289 xml_exception_throw("Required attribute not found, for element: ",
00290 (const char*)el._decl->_name,
00291 " and attribute: ",
00292 (const char*)iter->_name,
00293 0);
00294 }
00295 break;
00296 default:
00297 break;
00298 }
00299 }
00300 }
00301
00302 void
00303 xml_document::validate_children(xml_element& el)
00304 {
00305
00306 switch (el.cast_decl()->_content)
00307 {
00308 case contentSpec_MIN:
00309 case contentSpec_MAX:
00310 xml_exception_throw("no rule, for element: ",
00311 (const char*)el._decl->_name,
00312 0);
00313 break;
00314 case CONTENT_EMPTY:
00315 if (el.has_children())
00316 xml_exception_throw("EMPTY rule doesn't allow children, for element: ",
00317 (const char*)el._decl->_name,
00318 0);
00319 break;
00320 case CONTENT_ANY:
00321 break;
00322 case CONTENT_MIXED:
00323 {
00324
00325 content_interface* model = find_model(el.cast_decl());
00326 if (!model)
00327 {
00328 model = new (check_pointer(_model_allocator.allocate(sizeof(content_mixed)))) content_mixed(el.cast_decl()->_token, _model_allocator);
00329 add_model(el.cast_decl(), model);
00330 }
00331
00332 model->validate(el);
00333 }
00334 break;
00335 case CONTENT_CHILDREN:
00336 {
00337
00338 content_interface* model = find_model(el.cast_decl());
00339 if (!model)
00340 {
00341 model = new (check_pointer(_model_allocator.allocate(sizeof(content_children)))) content_children(el.cast_decl()->_token, _model_allocator);
00342 add_model(el.cast_decl(), model);
00343 }
00344
00345 model->validate(el);
00346 }
00347 break;
00348 default:
00349 assert(false);
00350 break;
00351 }
00352 }
00353
00354
00355
00356
00357 xml_element*
00358 xml_document::add_element(const char* name, xml_tree_node* sibling, bool after)
00359 {
00360 xml_element* retVal = 0;
00361 if (_container_stack.top() == this)
00362 {
00363
00364
00365
00366 if (!set_doc_name(name))
00367 exception::_throw("Invalid root element");
00368
00369 if (!check_root())
00370 exception::_throw("Invalid root element");
00371
00372 retVal = &_root;
00373
00374 sibling ? (after ? append_node(sibling, retVal) : insert_node(sibling, retVal)) : add_node(retVal);
00375 }
00376 else
00377 {
00378
00379 xml_container* parent = _container_stack.top();
00380
00381 xml_element* pel = xml_element::cast_to_element(parent);
00382
00383 const elementDecl* pdecl = pel->cast_decl();
00384 bool pany = pdecl->_content == CONTENT_ANY || pdecl->_content == CONTENT_CHILDREN && pdecl->_token->find_any_resursively();
00385
00386 retVal = new(check_pointer(_data_allocator.allocate(sizeof(xml_element)))) xml_element(&add_element_decl(name, _on_fly, false, pany), parent);
00387 sibling ? (after ? parent->append_node(sibling, retVal) : parent->insert_node(sibling, retVal)) : parent->add_node(retVal);
00388
00389
00390 if (retVal->_decl == _root._decl)
00391 exception::_throw("There is exactly one element, called the root");
00392
00393 }
00394
00395 return retVal;
00396 }
00397
00398 xml_value_node*
00399 xml_document::add_attribute(xml_element& el, const char* name, const char* value_org, xml_tree_node* sibling, bool after)
00400 {
00401 bool wasAdded = false;
00402 const attributeDecl& attr_decl = add_attribute_decl(*el.cast_decl(), name, !is_on_fly(), wasAdded);
00403
00404
00405 for (const xml_tree_node* node = el._first_attr; node; node = node->_right)
00406 if (node->_decl == &attr_decl)
00407 xml_exception_throw("Dublicate attribute found: ",
00408 name,
00409 " beneath parent element: ",
00410 (const char*)el._decl->_name,
00411 0);
00412
00413
00414 xml_value_node* retVal = new(check_pointer(_data_allocator.allocate(sizeof(xml_value_node)))) xml_value_node(&attr_decl, &el);
00415 sibling ? (after ? el.append_attribute(sibling, retVal) : el.insert_attribute(sibling, retVal)) : el.add_attribute(retVal);
00416
00417 assign_attribute_value(el, attr_decl, retVal, value_org);
00418 return retVal;
00419 }
00420
00421 void
00422 xml_document::assign_attribute_value(xml_element& el, const attributeDecl& attr_decl, xml_value_node* retVal, const char* value_org)
00423 {
00424
00425 size_t start_char = 0;
00426
00427 const char* value = value_org;
00428 if (value && attr_decl._atype != ATTR_TYPE_CDATA)
00429 {
00430 while (*value == ch_space)
00431 {
00432 ++start_char;
00433 ++value;
00434 }
00435
00436 if (*value)
00437 {
00438 const char* first_samuri = value;
00439 const char* last_samuri = value;
00440
00441
00442 while (*first_samuri)
00443 {
00444 switch (*first_samuri)
00445 {
00446 case ch_space:
00447 break;
00448 default:
00449
00450 last_samuri = first_samuri;
00451 }
00452
00453 ++first_samuri;
00454 }
00455
00456 if (last_samuri + 1 != first_samuri)
00457 {
00458
00459 char* value_ = (char*)_tmp_allocator.allocate(last_samuri - value + 2);
00460 memcpy(value_, value_org, last_samuri - value + 1);
00461 value_[last_samuri - value + 1] = 0;
00462
00463 value = value_;
00464 }
00465 else
00466 value = value;
00467 }
00468
00469 }
00470
00471
00472 switch (attr_decl._atype)
00473 {
00474 case attributeType_MIN:
00475 case attributeType_MAX:
00476 assert(false);
00477 break;
00478 case ATTR_TYPE_ID:
00479 {
00480 attributeRefDecl* decl = find_reference_decl(value);
00481
00482 if (!decl)
00483 decl = &add_reference_decl(value, true);
00484 else if (decl->_declared)
00485 xml_exception_throw("Dublicate ID found: ",
00486 value,
00487 " beneath parent element: ",
00488 (const char*)el._decl->_name,
00489 0);
00490 else
00491 decl->_declared = true;
00492
00493
00494
00495 retVal->_value.strVal = copy_string(value, _data_allocator, os_minus_one);
00496
00497 if (!is_name_first_char(*value))
00498 xml_exception_throw("Illigal ID char: ",
00499 value,
00500 " beneath parent element: ",
00501 (const char*)el._decl->_name,
00502 0);
00503
00504 const char* value_ = value + 1;
00505 while (*value_)
00506 if (!is_name_char(*value_))
00507 xml_exception_throw("Illigal ID char: ",
00508 value_,
00509 " beneath parent element: ",
00510 (const char*)el._decl->_name,
00511 0);
00512 else
00513 ++value_;
00514
00515 }
00516 break;
00517 case ATTR_TYPE_IDREF:
00518 {
00519 attributeRefDecl* decl = find_reference_decl(value);
00520 if (!decl)
00521 decl = &add_reference_decl(value, false);
00522 else if (!decl->_refered)
00523 decl->_refered = true;
00524
00525
00526
00527 retVal->_value.strVal = copy_string(value, _data_allocator, os_minus_one);
00528 }
00529 break;
00530 case ATTR_TYPE_IDREFS:
00531 {
00532 _list< const char* > values;
00533 tokenValues(value, values, _tmp_allocator);
00534 if (values.empty())
00535 xml_exception_throw("Invalid IDREFS syntax found: ",
00536 value,
00537 " beneath parent element: ",
00538 (const char*)el._decl->_name,
00539 0);
00540
00541 for (_list< const char* >::iterator iter = values.begin(); iter != values.end(); ++iter)
00542 {
00543 attributeRefDecl* decl = find_reference_decl(*iter);
00544 if (!decl)
00545 decl = &add_reference_decl(value, false);
00546 else if (!decl->_refered)
00547 decl->_refered = true;
00548 }
00549
00550
00551 retVal->_value.strVal = copy_string(value, _data_allocator,os_minus_one);
00552 }
00553 break;
00554 case ATTR_TYPE_ENTITY:
00555 {
00556 const entityDecl* decl = find_entity_decl(value);
00557 if (!decl)
00558 xml_exception_throw("Unresolved entity: ",
00559 value,
00560 " beneath parent element: ",
00561 (const char*)el._decl->_name,
00562 0);
00563
00564
00565 if (decl->_is_in_subset)
00566 xml_exception_throw("Illigal external entity: ",
00567 value,
00568 " beneath parent element: ",
00569 (const char*)el._decl->_name,
00570 0);
00571
00572
00573
00574 retVal->_value.strVal = copy_string((const char*)decl->_value, _data_allocator, os_minus_one);
00575 }
00576 break;
00577 case ATTR_TYPE_ENTITIES:
00578 {
00579 _list< const char* > values;
00580 tokenValues(value, values, _tmp_allocator);
00581
00582 if (values.empty())
00583 xml_exception_throw("Invalid ENTITIES syntax found: ",
00584 value,
00585 " beneath parent element: ",
00586 (const char*)el._decl->_name,
00587 0);
00588
00589
00590 string_t strDummy(&_tmp_allocator);
00591 char str_ch_space[2] = {ch_space, ch_null};
00592
00593 for (_list< const char* >::const_iterator iter = values.begin(); iter != values.end(); ++iter)
00594 {
00595 const entityDecl* decl = find_entity_decl(*iter);
00596 if (!decl)
00597 xml_exception_throw("Unresolved entity: ",
00598 *iter,
00599 " beneath parent element: ",
00600 (const char*)el._decl->_name,
00601 0);
00602
00603 if (decl->_is_in_subset)
00604 xml_exception_throw("Illigal external entity: ",
00605 *iter,
00606 " beneath parent element: ",
00607 (const char*)el._decl->_name,
00608 0);
00609
00610
00611 if (strDummy.length())
00612 strDummy += str_ch_space;
00613
00614 strDummy += decl->_value;
00615 }
00616
00617 retVal->_value.strVal = copy_string((const char*)strDummy, _data_allocator, os_minus_one);
00618 }
00619 break;
00620 case ATTR_TYPE_NMTOKEN:
00621
00622 {
00623 const char* value_ = value;
00624 while (*value_)
00625 if (!is_name_char(*value_))
00626 xml_exception_throw("Illigal token char: ",
00627 value_,
00628 " beneath parent element: ",
00629 (const char*)el._decl->_name,
00630 0);
00631 else
00632 ++value_;
00633
00634 retVal->_value.strVal = copy_string(value, _data_allocator, os_minus_one);
00635 }
00636 break;
00637 case ATTR_TYPE_NMTOKENS:
00638 {
00639 _list< const char* > values;
00640 tokenValues(value, values, _tmp_allocator);
00641
00642 if (values.empty())
00643 xml_exception_throw("Invalid NMTOKENS syntax found: ",
00644 value,
00645 " beneath parent element: ",
00646 (const char*)el._decl->_name,
00647 0);
00648
00649
00650 string_t strDummy(&_tmp_allocator);
00651 char str_ch_space[2] = {ch_space, ch_null};
00652
00653 for (_list< const char* >::const_iterator iter = values.begin(); iter != values.end(); ++iter)
00654 {
00655 if (strDummy.length())
00656 strDummy += str_ch_space;
00657
00658 const char* value_ = *iter;
00659 while (*value_)
00660 if (!is_name_char(*value_))
00661 xml_exception_throw("Illigal token char: ",
00662 value_,
00663 " beneath parent element: ",
00664 (const char*)el._decl->_name,
00665 0);
00666 else
00667 ++value_;
00668
00669 strDummy += *iter;
00670 }
00671
00672
00673 retVal->_value.strVal = copy_string((const char*)strDummy, _data_allocator, os_minus_one);
00674 }
00675 break;
00676 case ATTR_TYPE_NOTATION:
00677 {
00678 const notationDecl* decl = find_notation_decl(retVal->_decl->_name);
00679 if (!decl)
00680 xml_exception_throw("Can't find notation: ",
00681 (const char*)retVal->_decl->_name,
00682 " beneath parent element: ",
00683 (const char*)el._decl->_name,
00684 0);
00685 }
00686
00687 case ATTR_TYPE_ENUMERATION:
00688 {
00689 bool find = false;
00690 for (_list< enumNodeDecl >::const_iterator iter = retVal->cast_to_attribute()->_enum.begin(); iter != retVal->cast_to_attribute()->_enum.end(); ++iter)
00691 {
00692 if (!strcmp(iter->_value, value))
00693 {
00694 retVal->_value.lVal = (sb4_t)iter->_id;
00695 find = true;
00696 break;
00697 }
00698 }
00699
00700 if (!find)
00701 xml_exception_throw("Invalid enumaration value: ",
00702 value,
00703 " beneath parent element: ",
00704 (const char*)el._decl->_name,
00705 0);
00706 }
00707 break;
00708 default:
00709
00710 retVal->_value = parse_value(retVal->cast_to_attribute()->_ctype, value, os_minus_one, &_data_allocator);
00711 break;
00712 }
00713 }
00714
00715 void
00716 xml_document::update_attribute(xml_element* el, xml_value_node* att, const char* value)
00717 {
00718 const attributeDecl& attr_decl = *att->cast_to_attribute();
00719 assign_attribute_value(*el, attr_decl, att, value);
00720 }
00721
00722 void
00723 xml_document::add_def_attributes(xml_element& el, attr_states_map_t& attrStates)
00724 {
00725 for (attr_states_map_t::iterator iter = attrStates.begin(); iter != attrStates.end(); ++iter)
00726 {
00727 if (!*iter)
00728 {
00729 const attributeDecl* attr_decl = iter.key();
00730 switch (attr_decl->_rule)
00731 {
00732 case ATTR_RULE_DEFAULT:
00733 case ATTR_RULE_FIXED:
00734 *iter = add_attribute(el, attr_decl->_name, attr_decl->_defval);
00735 break;
00736 case ATTR_RULE_REQUIRED:
00737 if (attr_decl->_defval.length())
00738 *iter = add_attribute(el, attr_decl->_name, attr_decl->_defval);
00739 break;
00740 default:
00741 break;
00742 }
00743 }
00744 }
00745 }
00746
00747
00748 terimber_xml_value
00749 xml_document::find_attribute_value(const xml_element& el, const char* name) const
00750 {
00751 const attributeDecl* decl = find_attribute_decl(*el.cast_decl(), name);
00752 for (const xml_tree_node* iter = el._first_attr; iter; iter = iter->_right)
00753 if (iter->_decl == decl)
00754 return xml_value_node::cast_to_node_value(iter)->_value;
00755
00756 return terimber_xml_value();
00757 }
00758
00759 xml_value_node*
00760 xml_document::find_attribute(const xml_element& el, const char* name)
00761 {
00762 const namedNodeDecl* decl = find_attribute_decl(*el.cast_decl(), name);
00763 for (xml_tree_node* iter = el._first_attr; iter; iter = iter->_right)
00764 if (iter->_decl == decl)
00765 return xml_value_node::cast_to_node_value(iter);
00766
00767 return 0;
00768 }
00769
00770
00771 bool
00772 xml_document::set_doc_name(const char* name)
00773 {
00774 if (_on_fly && _root._decl)
00775 return false;
00776
00777 if (_on_fly || !_doc_name.length())
00778 _doc_name = name;
00779 else
00780 return _doc_name == name;
00781
00782 return true;
00783 }
00784
00785 bool
00786 xml_document::check_root()
00787 {
00788 if (_on_fly)
00789 {
00790
00791 _root._decl = find_element_decl(_doc_name);
00792 if (!_root._decl)
00793 _root._decl = &add_element_decl(_doc_name, true, false, false);
00794 }
00795 else
00796 {
00797 _root._decl = find_element_decl(_doc_name);
00798 if (!_root._decl)
00799 return false;
00800 }
00801
00802 return true;
00803 }
00804
00805 void
00806 xml_document::clear_root()
00807 {
00808 _root.clear();
00809 _root._parent = this;
00810 _doc_name = 0;
00811 }
00812
00813 void
00814 xml_document::container_reset()
00815 {
00816 _stack_allocator.clear_extra();
00817 _container_stack.clear();
00818 _container_stack.push(_stack_allocator, this);
00819 }
00820
00821 void
00822 xml_document::container_push(xml_element* el)
00823 {
00824 _container_stack.push(_stack_allocator, el);
00825 }
00826
00827 void
00828 xml_document::container_start_doctype()
00829 {
00830 _container_stack.push(_stack_allocator, &_doc_type);
00831 add_node(&_doc_type);
00832 }
00833
00834 void
00835 xml_document::container_stop_doctype()
00836 {
00837 container_pop();
00838 _on_fly = false;
00839 }
00840
00841 xml_element*
00842 xml_document::container_pop()
00843 {
00844 xml_container* el = _container_stack.top();
00845 if (el->_decl == _decl)
00846 return 0;
00847 else
00848 {
00849 _container_stack.pop(_stack_allocator);
00850 return static_cast< xml_element* >(el);
00851 }
00852 }
00853
00854 bool
00855 xml_document::container_peak()
00856 {
00857 xml_container* el = _container_stack.top();
00858 return el->_decl != _decl;
00859 }
00860
00861
00862 #pragma pack()
00863 END_TERIMBER_NAMESPACE
00864