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/sxs.hpp"
00029 #include "xml/defxml.hpp"
00030 #include "xml/declxml.hpp"
00031 
00032 #include "base/common.hpp"
00033 #include "base/memory.hpp"
00034 #include "base/list.hpp"
00035 #include "base/map.hpp"
00036 #include "base/string.hpp"
00037 #include "base/template.hpp"
00038 
00039 BEGIN_TERIMBER_NAMESPACE
00040 #pragma pack(4)
00041 
00043 nodeDecl::~nodeDecl()
00044 {
00045 }
00046 
00047 nodeDecl::nodeDecl(xmlNodeType type) :
00048         _type(type)
00049 {
00050 }
00051 
00052 nodeDecl::nodeDecl(const nodeDecl& x) :
00053         _type(x._type)
00054 {
00055 }
00056 
00058 namedNode::namedNode(const char* name, byte_allocator* allocator_) :
00059         _name(name, allocator_)
00060 {
00061 }
00062 
00063 namedNode::namedNode(const namedNode& x) : _name(x._name)
00064 {
00065 }
00066 
00067 void 
00068 namedNode::clear()
00069 {
00070         _name = 0;
00071 }
00072 
00074 namedNodeDecl::namedNodeDecl(xmlNodeType type, const char* name, byte_allocator* allocator_) :
00075         nodeDecl(type),
00076         namedNode(name, allocator_)
00077 {
00078 }
00079 
00080 namedNodeDecl::namedNodeDecl(const namedNodeDecl& x) :
00081         nodeDecl(x), namedNode(x)
00082 {
00083 }
00084 
00085 void 
00086 namedNodeDecl::clear()
00087 {
00088         namedNode::clear();
00089 }
00090 
00092 enumNodeDecl::enumNodeDecl(byte_allocator* allocator_) :
00093         _id(0), _value(allocator_)
00094 {
00095 }
00096 
00097 enumNodeDecl::enumNodeDecl(const enumNodeDecl& x) :
00098         _id(x._id), _value(x._value)
00099 {
00100 }
00101 
00103 attributeDecl::attributeDecl(const char* name, byte_allocator* allocator_) : 
00104         namedNodeDecl(ATTRIBUTE_NODE, name, allocator_),
00105         _atype(attributeType_MIN), 
00106         _ctype(vt_unknown), 
00107         _defval(allocator_),
00108         _rule(attributeRule_MIN)
00109 {
00110 }
00111 
00112 attributeDecl::attributeDecl(const attributeDecl& x) :
00113         namedNodeDecl(x),
00114         _atype(x._atype), 
00115         _ctype(x._ctype), 
00116         _enum(x._enum),
00117         _defval(x._defval),
00118         _rule(x._rule)
00119 {
00120 }
00121 
00122 const char* 
00123 attributeDecl::persist_attribute(const terimber_xml_value& value, byte_allocator* allocator_) const
00124 {
00125         if (_ctype == vt_enum)
00126         {
00127                 for (_list< enumNodeDecl >::const_iterator iter = _enum.begin(); iter != _enum.end(); ++iter)
00128                         if (iter->_id == value.lVal)
00129                         {
00130                                 terimber_xml_value dummy;
00131                                 dummy.strVal = iter->_value;
00132                                 return persist_value(vt_string, dummy, allocator_);
00133                         }
00134 
00135                 return 0;
00136         }
00137         else
00138                 return persist_value(_ctype, value, allocator_);
00139 
00140 }
00141 
00143 notationDecl::notationDecl(const char* name, byte_allocator* allocator_) :
00144         namedNodeDecl(NOTATION_NODE, name, allocator_),
00145         _systemId(allocator_),
00146         _publicId(allocator_) 
00147 {
00148 }
00149 
00150 
00151 notationDecl::notationDecl(const notationDecl& x) :
00152         namedNodeDecl(x),
00153         _systemId(x._systemId),
00154         _publicId(x._publicId) 
00155 {
00156 }
00157 
00159 entityDecl::entityDecl(const char* name, byte_allocator* allocator_) :
00160         namedNodeDecl(ENTITY_NODE, name, allocator_),
00161         _systemId(allocator_), 
00162         _publicId(allocator_), 
00163         _notation(allocator_), 
00164         _value(allocator_),
00165         _is_in_subset(false), 
00166         _is_parameter(false), 
00167         _is_encoded_char(false), 
00168         _is_unparsed(false)
00169 {
00170 }
00171 
00172 entityDecl::entityDecl(const entityDecl& x) :
00173         namedNodeDecl(x),
00174         _systemId(x._systemId), 
00175         _publicId(x._publicId), 
00176         _notation(x._notation), 
00177         _value(x._value),
00178         _is_in_subset(x._is_in_subset), 
00179         _is_parameter(x._is_parameter), 
00180         _is_encoded_char(x._is_encoded_char), 
00181         _is_unparsed(x._is_unparsed)
00182 {
00183 }
00184 
00186 attributeRefDecl::attributeRefDecl(const char* name, byte_allocator* allocator_) :
00187         namedNode(name, allocator_),
00188         _declared(false),
00189         _refered(false)
00190 {
00191 }
00192 
00193 attributeRefDecl::attributeRefDecl(const attributeRefDecl& x) :
00194         namedNode(x),
00195         _declared(x._declared),
00196         _refered(x._refered)
00197 {
00198 }
00199 
00201 elementDecl::elementDecl(const char*name, byte_allocator* allocator_) :
00202         namedNodeDecl(ELEMENT_NODE, name, allocator_), 
00203         _content(contentSpec_MIN), 
00204         _token(0),
00205         _attributes()
00206 {
00207 }
00208 
00209 elementDecl::elementDecl(const elementDecl& x) :
00210         namedNodeDecl(x), 
00211         _content(x._content), 
00212         _token(x._token),
00213         _attributes(x._attributes)
00214 {
00215 }
00216 
00217 
00219 dfa_token::dfa_token() :
00220         _rule(dfaRule_MIN), _decl(0), _first(0), _last(0)
00221 {
00222 }
00223 
00224 dfa_token::dfa_token(byte_allocator& allocator_, const dfa_token& x) :
00225         _rule(x._rule), _decl(x._decl), _first(x._first), _last(x._last)
00226 {       
00227 }
00228 
00229 dfa_token::dfa_token(dfaRule rule, const elementDecl* decl, dfa_token* first, dfa_token* last) :
00230         _rule(rule), _decl(decl), _first(first), _last(last)
00231 {
00232 }
00233 
00234 dfa_token::~dfa_token()
00235 {
00236 }
00237 
00238 void 
00239 dfa_token::assign(byte_allocator& allocator_, const dfa_token& x)
00240 {
00241         _decl = x._decl;
00242         _rule = x._rule;
00243         
00244         if (x._first)
00245         {
00246                 _first = new(check_pointer(allocator_.allocate(sizeof(dfa_token)))) dfa_token(allocator_, *x._first);
00247                 
00248                 _first->assign(allocator_, *x._first);
00249         }
00250         
00251         if (x._last)
00252         {
00253                 _last = new(check_pointer(allocator_.allocate(sizeof(dfa_token)))) dfa_token(allocator_, *x._last);
00254                 
00255                 _last->assign(allocator_, *x._last);
00256         }
00257 }
00258 
00259 bool
00260 dfa_token::find_any_resursively() const
00261 {
00262         if (_first 
00263                 && (_first->_decl && _first->_decl->_content == CONTENT_ANY
00264                         || _first->find_any_resursively())
00265                 )
00266                 return true;
00267 
00268         if (_last
00269                 && (_last->_decl && _last->_decl->_content == CONTENT_ANY
00270                         || _last->find_any_resursively())
00271                 )
00272                 return true;
00273 
00274         return false;
00275 }
00276 
00278 xml_grammar::xml_grammar(mem_pool_t& small_manager, mem_pool_t& big_manager, size_t xml_size) : 
00279         _small_manager(small_manager),
00280         _big_manager(big_manager),
00281         _xml_size(__max(xml_size, os_def_size)),
00282         _data_allocator(xml_size <= os_def_size ? *small_manager.loan_object() : *big_manager.loan_object()),
00283         _tmp_allocator(*small_manager.loan_object()),
00284         _document_decl(DOCUMENT_NODE, 0, 0), 
00285         _doctype_decl(DOCUMENT_TYPE_NODE, 0, 0),
00286         _text_decl(TEXT_NODE, 0, 0),
00287         _comment_decl(COMMENT_NODE, 0, 0), 
00288         _cdata_decl(CDATA_SECTION_NODE, 0, 0),
00289         _read_only(false),
00290         _doc_name(&_data_allocator),
00291         _public_id(&_data_allocator),
00292         _system_id(&_data_allocator)
00293 {
00294 }
00295 
00296 xml_grammar::~xml_grammar()
00297 {
00298         clear();
00299         _xml_size <= os_def_size ? _small_manager.return_object(&_data_allocator) : _big_manager.return_object(&_data_allocator);
00300         _small_manager.return_object(&_tmp_allocator);
00301 }
00302 
00303 xml_grammar& 
00304 xml_grammar::copy(const xml_grammar& x)
00305 {
00306         if (this != &x)
00307         {
00308                 _doc_name = x._doc_name;
00309                 _public_id = x._public_id;
00310                 _system_id = x._system_id;
00311 
00312                 
00313                 notationDecl dummy_notation(0, &_data_allocator);
00314                 _notationMap.clear();   
00315                 for (notation_decl_map_t::const_iterator INot = x._notationMap.begin(); INot != x._notationMap.end(); ++INot) 
00316                 {
00317                         notationDecl& decl = *_notationMap.insert(_data_allocator, INot.key(), dummy_notation).first;
00318                         decl._name = INot->_name;
00319                         decl._publicId = INot->_publicId;
00320                         decl._systemId = INot->_systemId;
00321                 }
00322 
00323                 entityDecl dummy_entity(0, &_data_allocator);
00324                 _entityMap.clear();     
00325                 for (entity_decl_map_t::const_iterator IEnt = x._entityMap.begin(); IEnt != x._entityMap.end(); ++IEnt) 
00326                 {
00327                         entityDecl& decl = *_entityMap.insert(_data_allocator, IEnt.key(), dummy_entity).first;
00328                         decl._is_encoded_char = IEnt->_is_encoded_char;
00329                         decl._is_in_subset = IEnt->_is_in_subset;
00330                         decl._is_parameter = IEnt->_is_parameter;
00331                         decl._is_unparsed = IEnt->_is_unparsed;
00332                         decl._name = IEnt->_name;
00333                         decl._notation = IEnt->_notation;
00334                         decl._publicId = IEnt->_publicId;
00335                         decl._systemId = IEnt->_systemId;
00336                         decl._value = IEnt->_value;
00337                 }
00338 
00339                 attributeRefDecl dummy_attributeRef(0, &_data_allocator);
00340                 _attributeRefMap.clear();       
00341                 for (attribute_ref_decl_map_t::const_iterator iterAttRef = x._attributeRefMap.begin(); iterAttRef != x._attributeRefMap.end(); ++iterAttRef) 
00342                 {
00343                         attributeRefDecl& decl = *_attributeRefMap.insert(_data_allocator, iterAttRef.key(), dummy_attributeRef).first;
00344                         decl._declared = iterAttRef->_declared;
00345                         decl._name = iterAttRef->_name;
00346                         decl._refered = iterAttRef->_refered;
00347                 }
00348 
00349                 namedNodeDecl dummy_pi(PROCESSING_INSTRUCTION_NODE, 0, &_data_allocator);
00350                 _piMap.clear();         
00351                 for (namednode_decl_map_t::const_iterator IPi = x._piMap.begin(); IPi != x._piMap.end(); ++IPi) 
00352                 {
00353                         namedNodeDecl& decl = *_piMap.insert(_data_allocator, IPi.key(), dummy_pi).first;
00354                         decl._name = IPi->_name;
00355                 }
00356 
00357                 elementDecl dummy_element(0, &_data_allocator);
00358                 attributeDecl dummy_attribute(0, &_data_allocator);
00359                 enumNodeDecl dummy_enum(&_data_allocator);
00360                 _elementMap.clear();    
00361                 for (element_decl_map_t::const_iterator IEl = x._elementMap.begin(); IEl != x._elementMap.end(); ++IEl) 
00362                 {
00363                         elementDecl& decl = *_elementMap.insert(_data_allocator, IEl.key(), dummy_element).first;
00364                         
00365                         
00366                         decl._name = IEl->_name;
00367 
00368                         
00369                         for (attribute_decl_map_t::const_iterator IAttr = IEl->_attributes.begin(); IAttr != IEl->_attributes.end(); ++IAttr) 
00370                         {
00371                                 attributeDecl& declAttr = *decl._attributes.insert(_data_allocator, IAttr.key(), dummy_attribute).first;
00372                                 declAttr._atype = IAttr->_atype;
00373                                 declAttr._ctype = IAttr->_ctype;
00374                                 declAttr._defval = IAttr->_defval;
00375                                 declAttr._name = IAttr->_name;
00376                                 declAttr._rule = IAttr->_rule;
00377 
00378                                 
00379                                 for (_list< enumNodeDecl >::const_iterator IEn = IAttr->_enum.begin(); IEn != IAttr->_enum.end(); ++IEn)
00380                                 {
00381                                         enumNodeDecl& entryEn = *declAttr._enum.push_back(_data_allocator, dummy_enum);
00382                                         entryEn._id = IEn->_id;
00383                                         entryEn._value = IEn->_value;
00384                                 }
00385                         }
00386                         
00387                         
00388                         decl._content = IEl->_content;
00389                         if (IEl->_token)
00390                         {
00391                                 decl._token = new(check_pointer(_data_allocator.allocate(sizeof(dfa_token)))) dfa_token(_data_allocator, *IEl->_token);
00392                                 decl._token->assign(_data_allocator, *IEl->_token);
00393                         }
00394                 }
00395 
00396                 _read_only = true;
00397         }
00398         return *this;
00399 }
00400 
00401 elementDecl& 
00402 xml_grammar::add_element_decl(const char* name, bool on_fly, bool fromDecl, bool modelAny)
00403 {
00404         
00405         check_readonly();
00406 
00407         
00408         size_t hash_value = do_hash((const char*)name, os_minus_one);
00409         element_decl_map_t::pairii_t range = _elementMap.equal_range(hash_value);
00410         element_decl_map_t::iterator start(range.first);
00411 
00412         if (start != range.second) 
00413                 for (start = range.first; start != range.second; ++start)
00414                         if (start->_name == name) 
00415                         {
00416                                 if (fromDecl && start->_content != contentSpec_MIN)
00417                                         xml_exception_throw("Dublicate element name: ", 
00418                                                                                 (const char*)name,
00419                                                                                 0);
00420                                 return *start;
00421                         } 
00422         
00423         
00424         
00425         elementDecl decl(0, &_data_allocator);
00426         start = _elementMap.insert(_data_allocator, hash_value, decl).first;
00427         if (start == _elementMap.end())
00428                 xml_exception_throw("Not enough memory", 0);
00429 
00430         start->_name = name;
00431 
00432         if (on_fly || fromDecl || modelAny || (name[0] == 'A' && name[1] == 'N' && name[2] == 'Y' && name[3] == 0))
00433                 start->_content = CONTENT_ANY;
00434 
00435         return *start;
00436 }
00437 
00438 const elementDecl* 
00439 xml_grammar::find_element_decl(const char* name) const
00440 {
00441         if (_elementMap.empty())
00442                 return 0;
00443         
00444         element_decl_map_t::paircc_t range = _elementMap.equal_range(do_hash(name, os_minus_one));
00445         for (element_decl_map_t::const_iterator start = range.first; start != range.second; ++start)
00446                 if (start->_name == name) 
00447                         return &*start;
00448 
00449         return 0;
00450 }
00451 
00452 elementDecl* 
00453 xml_grammar::find_element_decl(const char* name)
00454 {
00455         check_readonly();
00456         if (_elementMap.empty())
00457                 return 0;
00458         
00459         element_decl_map_t::pairii_t range = _elementMap.equal_range(do_hash(name, os_minus_one));
00460         for (element_decl_map_t::iterator start = range.first; start != range.second; ++start)
00461                 if (start->_name == name) 
00462                         return &*start;
00463 
00464         return 0;
00465 }
00466 
00467 notationDecl& 
00468 xml_grammar::add_notation_decl(const char* name)
00469 {
00470         check_readonly();
00471         size_t hash_value = do_hash(name, os_minus_one);
00472         notation_decl_map_t::pairii_t range = _notationMap.equal_range(hash_value);
00473         notation_decl_map_t::iterator start(range.first);
00474 
00475         if (start != range.second) 
00476                 for (start = range.first; start != range.second; ++start)
00477                         if (start->_name == name) 
00478                                 xml_exception_throw("Dublicate notation name: ",
00479                                                                         (const char*)name,
00480                                                                         0);
00481 
00482         
00483         notationDecl decl(0, &_data_allocator);
00484         start = _notationMap.insert(_data_allocator, hash_value, decl).first;
00485         if (start == _notationMap.end())
00486                 xml_exception_throw("Not enough memory", 0);
00487 
00488         start->_name = name;
00489         return *start;
00490 }
00491 
00492 const notationDecl* 
00493 xml_grammar::find_notation_decl(const char* name) const
00494 {
00495         if (_notationMap.empty())
00496                 return 0;
00497 
00498         notation_decl_map_t::paircc_t range = _notationMap.equal_range(do_hash(name, os_minus_one));
00499 
00500         for (notation_decl_map_t::const_iterator start = range.first; start != range.second; ++start)
00501                 if (start->_name == name) 
00502                         return &*start;
00503 
00504         return 0;
00505 }
00506 
00507 entityDecl& 
00508 xml_grammar::add_entity_decl(const char* name, bool& wasAdded)
00509 {
00510         check_readonly();
00511         wasAdded = false;
00512         size_t hash_value = do_hash(name, os_minus_one);
00513         entity_decl_map_t::pairii_t range = _entityMap.equal_range(hash_value);
00514         entity_decl_map_t::iterator start(range.first);
00515 
00516         if (start != range.second) 
00517                 for (start = range.first; start != range.second; ++start)
00518                         if (start->_name == name) 
00519                                 return *start;
00520 
00521         
00522         entityDecl decl(0, &_data_allocator);
00523         start = _entityMap.insert(_data_allocator, hash_value, decl).first;
00524         if (start == _entityMap.end())
00525                 xml_exception_throw("Not enough memory", 0);
00526 
00527         start->_name = name;
00528         wasAdded = true;
00529 
00530         return *start;
00531 }
00532 
00533 const entityDecl* 
00534 xml_grammar::find_entity_decl(const char* name) const
00535 {
00536         if (_entityMap.empty())
00537                 return 0;
00538 
00539         entity_decl_map_t::paircc_t range = _entityMap.equal_range(do_hash(name, os_minus_one));
00540 
00541         for (entity_decl_map_t::const_iterator start = range.first; start != range.second; ++start)
00542                 if (start->_name == name) 
00543                         return &*start;
00544 
00545         return 0;
00546 }
00547 
00548 entityDecl* 
00549 xml_grammar::find_entity_decl(const char* name)
00550 {
00551         check_readonly();
00552 
00553         if (_entityMap.empty())
00554                 return 0;
00555 
00556         entity_decl_map_t::pairii_t range = _entityMap.equal_range(do_hash(name, os_minus_one));
00557 
00558         for (entity_decl_map_t::iterator start = range.first; start != range.second; ++start)
00559                 if (start->_name == name) 
00560                         return &*start;
00561 
00562         return 0;
00563 }
00564 
00565 attributeDecl& 
00566 xml_grammar::add_attribute_decl(const elementDecl& decl, const char* name, bool mustPresent, bool& wasAdded)
00567 {
00568         
00569         check_readonly();
00570 
00571         elementDecl& decl_ = const_cast< elementDecl& >(decl);
00572         wasAdded = false;
00573         
00574         size_t hash_value = do_hash(name, os_minus_one);
00575         attribute_decl_map_t::pairii_t range = decl_._attributes.equal_range(hash_value);
00576         attribute_decl_map_t::iterator start(range.first);
00577 
00578         if (start != range.second) 
00579                 for (start = range.first; start != range.second; ++start)
00580                         if (start->_name == name) 
00581                                 return *start;
00582 
00583         if (mustPresent && decl._content != CONTENT_ANY)
00584         {
00585                 xml_exception_throw("Unknown attribute found: ",
00586                                         name,
00587                                         " beneath parent element: ",
00588                                         (const char*)decl._name,
00589                                         0);
00590         }
00591         
00592         attributeDecl adecl(0, &_data_allocator);
00593         start = decl_._attributes.insert(_data_allocator, hash_value, adecl).first;
00594         if (start == decl_._attributes.end())
00595                 xml_exception_throw("Not enough memory", 0);
00596 
00597         start->_name = name;
00598         start->_atype = ATTR_TYPE_CDATA;
00599         start->_ctype = vt_string;
00600         start->_rule = ATTR_RULE_IMPLIED;
00601 
00602         wasAdded = true;
00603 
00604         return *start;
00605 }
00606 
00607 const attributeDecl* 
00608 xml_grammar::find_attribute_decl(const elementDecl& decl, const char* qname) const
00609 {
00610         if (decl._attributes.empty())
00611                 return 0;
00612 
00613         attribute_decl_map_t::paircc_t range = decl._attributes.equal_range(do_hash(qname, os_minus_one));
00614         for (attribute_decl_map_t::const_iterator start = range.first; start != range.second; ++start)
00615                 if (start->_name == qname) 
00616                         return &*start;
00617 
00618         return 0;
00619 }
00620 
00621 attributeRefDecl& 
00622 xml_grammar::add_reference_decl(const char* name, bool fromID)
00623 {
00624         check_readonly();
00625         size_t hash_value = do_hash(name, os_minus_one);
00626         attribute_ref_decl_map_t::pairii_t range = _attributeRefMap.equal_range(hash_value);
00627         attribute_ref_decl_map_t::iterator start(range.first);
00628 
00629         if (start != range.second) 
00630                 for (start = range.first; start != range.second; ++start)
00631                         if (start->_name == name) 
00632                                 xml_exception_throw("Dublicate attribute reference name: ",
00633                                                                         (const char*)name,
00634                                                                         0);
00635 
00636         
00637         attributeRefDecl decl(0, &_data_allocator);
00638         start = _attributeRefMap.insert(_data_allocator, hash_value, decl).first;
00639         if (start == _attributeRefMap.end())
00640                 xml_exception_throw("Not enough memory", 0);
00641 
00642         start->_name = name;
00643         (fromID ? start->_declared : start->_refered) = true;
00644 
00645         return *start;
00646 }
00647 
00648 attributeRefDecl* 
00649 xml_grammar::find_reference_decl(const char* name)
00650 {
00651         if (_attributeRefMap.empty())
00652                 return 0;
00653 
00654         size_t hash_value = do_hash(name, os_minus_one);
00655         attribute_ref_decl_map_t::pairii_t range = _attributeRefMap.equal_range(hash_value);
00656 
00657         for (attribute_ref_decl_map_t::iterator start = range.first; start != range.second; ++start)
00658                 if (start->_name == name) 
00659                         return &*start;
00660 
00661         return 0;
00662 }
00663 
00664 namedNodeDecl& 
00665 xml_grammar::add_pi_decl(const char* name)
00666 {
00667         check_readonly();
00668         size_t hash_value = do_hash(name, os_minus_one);
00669         namednode_decl_map_t::pairii_t range = _piMap.equal_range(hash_value);
00670         namednode_decl_map_t::iterator start(range.first);
00671 
00672         if (start != range.second) 
00673                 for (start = range.first; start != range.second; ++start)
00674                         if (start->_name == name) 
00675                                 return *start;
00676 
00677         
00678         namedNodeDecl decl(PROCESSING_INSTRUCTION_NODE, 0, &_data_allocator);
00679         start = _piMap.insert(_data_allocator, hash_value, decl).first;
00680         if (start == _piMap.end())
00681                 xml_exception_throw("Not enough memory", 0);
00682 
00683         start->_name = name;
00684         return *start;
00685 }
00686 
00687 const namedNodeDecl* 
00688 xml_grammar::find_pi_decl(const char* name) const
00689 {
00690         if (_piMap.empty())
00691                 return 0;
00692 
00693         namednode_decl_map_t::paircc_t range = _piMap.equal_range(do_hash(name, os_minus_one));
00694 
00695         for (namednode_decl_map_t::const_iterator start = range.first; start != range.second; ++start)
00696                 if (start->_name == name) 
00697                         return &*start;
00698 
00699         return 0;
00700 }
00701 
00702 
00703 void 
00704 xml_grammar::resolve_references()
00705 {
00706         for (attribute_ref_decl_map_t::const_iterator iter = _attributeRefMap.begin(); iter != _attributeRefMap.end(); ++iter)
00707                 if (!iter->_declared && iter->_refered)
00708                         xml_exception_throw("Undeclared ID: ", (const char*)iter->_name, 0);
00709 }
00710 
00711 
00713 void xml_exception_throw(const char* first, ...)
00714 {
00715         va_list va;
00716         va_start(va, first);
00717         const char* entry = first;
00718         string_t ex;
00719         while (entry)
00720         {
00721                 ex += entry;
00722                 entry = va_arg(va, const char*);
00723         }
00724         va_end(va);
00725 
00726         exception::_throw(ex);
00727 }
00728 
00729 #pragma pack()
00730 END_TERIMBER_NAMESPACE
00731