00001 /* 00002 ** ClanLib SDK 00003 ** Copyright (c) 1997-2005 The ClanLib Team 00004 ** 00005 ** This software is provided 'as-is', without any express or implied 00006 ** warranty. In no event will the authors be held liable for any damages 00007 ** arising from the use of this software. 00008 ** 00009 ** Permission is granted to anyone to use this software for any purpose, 00010 ** including commercial applications, and to alter it and redistribute it 00011 ** freely, subject to the following restrictions: 00012 ** 00013 ** 1. The origin of this software must not be misrepresented; you must not 00014 ** claim that you wrote the original software. If you use this software 00015 ** in a product, an acknowledgment in the product documentation would be 00016 ** appreciated but is not required. 00017 ** 2. Altered source versions must be plainly marked as such, and must not be 00018 ** misrepresented as being the original software. 00019 ** 3. This notice may not be removed or altered from any source distribution. 00020 ** 00021 ** Note: Some of the libraries ClanLib link to may have additional 00022 ** requirements or restrictions. 00023 ** 00024 ** File Author(s): 00025 ** 00026 ** Magnus Norddahl 00027 */ 00028 00029 #include "precomp.h" 00030 #include "dom_document.h" 00031 #include "dom_document_type.h" 00032 #include "dom_implementation.h" 00033 #include "dom_element.h" 00034 #include "dom_document_fragment.h" 00035 #include "dom_text.h" 00036 #include "dom_comment.h" 00037 #include "dom_cdata_section.h" 00038 #include "dom_processing_instruction.h" 00039 #include "dom_attr.h" 00040 #include "dom_entity_reference.h" 00041 #include "dom_node_list.h" 00042 //#include "xml_tokenizer.h" 00043 //#include "xml_writer.h" 00044 //#include "xml_token.h" 00045 //#include "xml_token_load.h" 00046 //#include "xml_token_save.h" 00047 //#include "xml_token_string.h" 00048 #include "dom_document_generic.h" 00049 #include <stack> 00050 00052 // CL_DomDocument construction: 00053 00054 CL_DomDocument::CL_DomDocument() : CL_DomNode(CL_SharedPtr<CL_DomNode_Generic>(new CL_DomDocument_Generic)) 00055 { 00056 } 00057 /* 00058 CL_DomDocument::CL_DomDocument(CL_IODevice *input, bool delete_input, bool eat_whitespace) 00059 : CL_DomNode(CL_SharedPtr<CL_DomNode_Generic>(new CL_DomDocument_Generic)) 00060 { 00061 load(input, delete_input, eat_whitespace); 00062 } 00063 */ 00064 CL_DomDocument::CL_DomDocument(const CL_SharedPtr<CL_DomNode_Generic> &impl) : CL_DomNode(impl) 00065 { 00066 } 00067 00068 CL_DomDocument::~CL_DomDocument() 00069 { 00070 } 00071 00073 // CL_DomDocument attributes: 00074 00075 CL_DomDocumentType CL_DomDocument::get_doctype() 00076 { 00077 return CL_DomDocumentType(*this); 00078 } 00079 00080 CL_DomImplementation CL_DomDocument::get_implementation() 00081 { 00082 return CL_DomImplementation(*this); 00083 } 00084 00085 CL_DomElement CL_DomDocument::get_document_element() 00086 { 00087 CL_DomNode cur(impl->first_child); 00088 while (!cur.is_null()) 00089 { 00090 if (cur.is_element()) return cur.to_element(); 00091 cur = cur.get_next_sibling(); 00092 } 00093 return CL_DomElement(); 00094 } 00095 00097 // CL_DomDocument operations: 00098 00099 CL_DomElement CL_DomDocument::create_element(const std::string &tag_name) 00100 { 00101 return CL_DomElement(*this, tag_name); 00102 } 00103 00104 CL_DomDocumentFragment CL_DomDocument::create_document_fragment() 00105 { 00106 return CL_DomDocumentFragment(*this); 00107 } 00108 00109 CL_DomText CL_DomDocument::create_text_node(const std::string &data) 00110 { 00111 return CL_DomText(*this, data); 00112 } 00113 00114 CL_DomComment CL_DomDocument::create_comment(const std::string &data) 00115 { 00116 return CL_DomComment(*this, data); 00117 } 00118 00119 CL_DomCDATASection CL_DomDocument::create_cdata_section(const std::string &data) 00120 { 00121 return CL_DomCDATASection(*this, data); 00122 } 00123 00124 CL_DomProcessingInstruction CL_DomDocument::create_processing_instruction( 00125 const std::string &target, 00126 const std::string &data) 00127 { 00128 return CL_DomProcessingInstruction(*this, target, data); 00129 } 00130 00131 CL_DomAttr CL_DomDocument::create_attribute(const std::string &name) 00132 { 00133 return CL_DomAttr(*this, name); 00134 } 00135 00136 CL_DomEntityReference CL_DomDocument::create_entity_reference(const std::string &name) 00137 { 00138 return CL_DomEntityReference(*this, name); 00139 } 00140 00141 CL_DomNodeList CL_DomDocument::get_elements_by_tag_name(const std::string &tag_name) 00142 { 00143 return CL_DomNodeList(*this, tag_name); 00144 } 00145 /* 00146 std::vector<CL_DomNode> CL_DomDocument::load( 00147 CL_IODevice *input, 00148 bool delete_input, 00149 bool eat_whitespace, 00150 CL_DomNode insert_point) 00151 { 00152 clear_all(); 00153 00154 CL_XMLTokenizer tokenizer(input, delete_input); 00155 tokenizer.set_eat_whitespace(eat_whitespace); 00156 00157 if (insert_point.is_element() == false) 00158 insert_point = *this; 00159 00160 std::stack<CL_DomNode> node_stack; 00161 node_stack.push(insert_point); 00162 00163 std::vector<CL_DomNode> result; 00164 00165 try 00166 { 00167 CL_XMLTokenLoad cur_token = tokenizer.next(); 00168 while (cur_token.get_type() != CL_XMLToken::NULL_TOKEN) 00169 { 00170 switch (cur_token.get_type()) 00171 { 00172 case CL_XMLToken::TEXT_TOKEN: 00173 node_stack.top().append_child(create_text_node(cur_token.get_value())); 00174 if (node_stack.top() == insert_point) 00175 result.push_back(node_stack.top().get_last_child()); 00176 break; 00177 00178 case CL_XMLToken::CDATA_SECTION_TOKEN: 00179 node_stack.top().append_child(create_cdata_section(cur_token.get_value())); 00180 if (node_stack.top() == insert_point) 00181 result.push_back(node_stack.top().get_last_child()); 00182 break; 00183 00184 case CL_XMLToken::ELEMENT_TOKEN: 00185 if (cur_token.get_variant() != CL_XMLToken::END) 00186 { 00187 CL_DomElement element = create_element(cur_token.get_name()); 00188 node_stack.top().append_child(element); 00189 if (node_stack.top() == insert_point) 00190 result.push_back(node_stack.top().get_last_child()); 00191 00192 int size = cur_token.get_attributes_number(); 00193 for (int i=0; i<size; i++) 00194 { 00195 std::pair<CL_XMLTokenString, CL_XMLTokenString> const & attribute = cur_token.get_attribute_fast(i); 00196 element.set_attribute(attribute.first.to_string(), attribute.second.to_string()); 00197 } 00198 00199 if (cur_token.get_variant() == CL_XMLToken::BEGIN) 00200 node_stack.push(element); 00201 } 00202 else 00203 { 00204 node_stack.pop(); 00205 if (node_stack.empty()) throw CL_Error("Malformed XML tree!"); 00206 } 00207 break; 00208 00209 case CL_XMLToken::NULL_TOKEN: 00210 break; 00211 00212 case CL_XMLToken::ENTITY_REFERENCE_TOKEN: 00213 break; 00214 00215 case CL_XMLToken::ENTITY_TOKEN: 00216 break; 00217 00218 case CL_XMLToken::COMMENT_TOKEN: 00219 break; 00220 00221 case CL_XMLToken::DOCUMENT_TYPE_TOKEN: 00222 break; 00223 00224 case CL_XMLToken::NOTATION_TOKEN: 00225 break; 00226 00227 case CL_XMLToken::PROCESSING_INSTRUCTION_TOKEN: 00228 break; 00229 } 00230 00231 cur_token = tokenizer.next(); 00232 } 00233 } 00234 catch (CL_Error e) 00235 { 00236 for (std::vector<CL_DomNode>::size_type i = 0; i < result.size(); i++) 00237 { 00238 insert_point.remove_child(result[i]); 00239 } 00240 throw e; 00241 } 00242 return result; 00243 } 00244 00245 void CL_DomDocument::save(CL_IODevice *output, bool delete_output, bool insert_whitespace) 00246 { 00247 CL_XMLWriter writer(output, delete_output); 00248 writer.set_insert_whitespace(insert_whitespace); 00249 00250 std::stack<CL_DomNode> node_stack; 00251 CL_DomNode cur_node = get_first_child(); 00252 while (!cur_node.is_null()) 00253 { 00254 // Create opening node: 00255 CL_XMLTokenSave opening_node; 00256 opening_node.set_type((CL_XMLToken::TokenType) cur_node.get_node_type()); 00257 opening_node.set_variant(cur_node.has_child_nodes() ? CL_XMLToken::BEGIN : CL_XMLToken::SINGLE); 00258 opening_node.set_name(cur_node.get_node_name()); 00259 opening_node.set_value(cur_node.get_node_value()); 00260 if (cur_node.is_element()) 00261 { 00262 for (int i = 0; i < cur_node.impl->attributes.get_length(); ++i) 00263 { 00264 opening_node.set_attribute(cur_node.impl->attributes.item(i).to_attr().get_name(), 00265 cur_node.impl->attributes.item(i).to_attr().get_value()); 00266 } 00267 } 00268 writer.write(opening_node); 00269 00270 // Create any possible child nodes: 00271 if (cur_node.has_child_nodes()) 00272 { 00273 node_stack.push(cur_node); 00274 cur_node = cur_node.get_first_child(); 00275 continue; 00276 } 00277 00278 // Create closing nodes until we reach next opening node in tree: 00279 while (true) 00280 { 00281 if (cur_node.has_child_nodes()) 00282 { 00283 CL_XMLTokenSave closing_node; 00284 closing_node.set_type((CL_XMLToken::TokenType) cur_node.get_node_type()); 00285 closing_node.set_name(cur_node.get_node_name()); 00286 closing_node.set_variant(CL_XMLToken::END); 00287 writer.write(closing_node); 00288 } 00289 00290 cur_node = cur_node.get_next_sibling(); 00291 if (!cur_node.is_null()) break; 00292 if (node_stack.empty()) break; 00293 00294 cur_node = node_stack.top(); 00295 node_stack.pop(); 00296 } 00297 } 00298 } 00299 */ 00300 void CL_DomDocument::clear_all() 00301 { 00302 while (!get_first_child().is_null()) 00303 { 00304 CL_DomNode node = get_first_child(); 00305 remove_child(node); 00306 } 00307 } 00308 00310 // CL_DomDocument implementation:
1.4.1