00001 /* 00002 * Copyright (C) 2001-2003 Peter J Jones (pjones@pmade.org) 00003 * All Rights Reserved 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in 00013 * the documentation and/or other materials provided with the 00014 * distribution. 00015 * 3. Neither the name of the Author nor the names of its contributors 00016 * may be used to endorse or promote products derived from this software 00017 * without specific prior written permission. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' 00020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 00021 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00022 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 00023 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00024 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00025 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 00026 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00027 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00028 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00029 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00030 * SUCH DAMAGE. 00031 */ 00032 00033 /** 00034 @file 00035 00036 This file contains the definition of the xml::document class. 00037 */ 00038 00039 #ifndef _xmlwrapp_document_h_ 00040 #define _xmlwrapp_document_h_ 00041 00042 // xmlwrapp includes 00043 #include "xmlwrapp/init.h" 00044 #include "xmlwrapp/node.h" 00045 00046 // standard includes 00047 #include <iosfwd> 00048 #include <string> 00049 #include <cstddef> 00050 00051 // forward declaration 00052 namespace xslt 00053 { 00054 00055 class stylesheet; 00056 namespace impl 00057 { 00058 class result; 00059 } 00060 00061 } // end xslt namespace 00062 00063 namespace xml 00064 { 00065 00066 // forward declarations 00067 class tree_parser; 00068 00069 namespace impl 00070 { 00071 struct doc_impl; 00072 } 00073 00074 /** 00075 The xml::document class is used to hold the XML tree and various bits of 00076 information about it. 00077 */ 00078 class document 00079 { 00080 public: 00081 /// size type 00082 typedef std::size_t size_type; 00083 00084 /** 00085 Create a new XML document with the default settings. The new document 00086 will contain a root node with a name of "blank". 00087 00088 @author Peter Jones 00089 */ 00090 document(); 00091 00092 /** 00093 Create a new XML document and set the name of the root element to the 00094 given text. 00095 00096 @param root_name What to set the name of the root element to. 00097 @author Peter Jones 00098 */ 00099 explicit document(const char *root_name); 00100 00101 /** 00102 Create a new XML document and set the root node. 00103 00104 @param n The node to use as the root node. n will be copied. 00105 @author Peter Jones 00106 */ 00107 explicit document(const node& n); 00108 00109 /** 00110 Copy construct a new XML document. The new document will be an exact 00111 copy of the original. 00112 00113 @param other The other document object to copy from. 00114 @author Peter Jones 00115 */ 00116 document(const document& other); 00117 00118 /** 00119 Copy another document object into this one using the assignment 00120 operator. This document object will be an exact copy of the other 00121 document after the assignement. 00122 00123 @param other The document to copy from. 00124 @return *this. 00125 @author Peter Jones 00126 */ 00127 document& operator=(const document& other); 00128 00129 /** 00130 Swap one xml::document object for another. 00131 00132 @param other The other document to swap 00133 @author Peter Jones 00134 */ 00135 void swap(document& other); 00136 00137 /** 00138 Clean up after an XML document object. 00139 00140 @author Peter Jones 00141 */ 00142 ~document(); 00143 00144 /** 00145 Get a reference to the root node of this document. If no root node 00146 has been set, the returned node will be a blank node. You should take 00147 caution to use a reference so that you don't copy the whole node 00148 tree! 00149 00150 @return A const reference to the root node. 00151 @author Peter Jones 00152 */ 00153 const node& get_root_node() const; 00154 00155 /** 00156 Get a reference to the root node of this document. If no root node 00157 has been set, the returned node will be a blank node. You should take 00158 caution to use a reference so that you don't copy the whole node 00159 tree! 00160 00161 @return A reference to the root node. 00162 @author Peter Jones 00163 */ 00164 node& get_root_node(); 00165 00166 /** 00167 Set the root node to the given node. A full copy is made and stored 00168 in the document object. 00169 00170 @param n The new root node to use. 00171 @author Peter Jones 00172 */ 00173 void set_root_node(const node& n); 00174 00175 /** 00176 Get the XML version for this document. For generated documents, the 00177 version will be the default. For parsed documents, this will be the 00178 version from the XML processing instruction. 00179 00180 @return The XML version string for this document. 00181 @author Peter Jones 00182 */ 00183 const std::string& get_version() const; 00184 00185 /** 00186 Set the XML version number for this document. This version string 00187 will be used when generating the XML output. 00188 00189 @param version The version string to use, like "1.0". 00190 @author Peter Jones 00191 */ 00192 void set_version(const char *version); 00193 00194 /** 00195 Get the XML encoding for this document. The default encoding is 00196 ISO-8859-1. 00197 00198 @return The encoding string. 00199 @author Peter Jones 00200 */ 00201 const std::string& get_encoding() const; 00202 00203 /** 00204 Set the XML encoding string. If you don't set this, it will default 00205 to ISO-8859-1. 00206 00207 @param encoding The XML encoding to use. 00208 @author Peter Jones 00209 @author Dmitriy Nikitinskiy 00210 */ 00211 void set_encoding(const char *encoding); 00212 00213 /** 00214 Find out if the current document is a standalone document. For 00215 generated documents, this will be the default. For parsed documents 00216 this will be set based on the XML processing instruction. 00217 00218 @return True if this document is standalone. 00219 @return False if this document is not standalone. 00220 @author Peter Jones 00221 */ 00222 bool get_is_standalone() const; 00223 00224 /** 00225 Set the standalone flag. This will show up in the XML output in the 00226 correct processing instruction. 00227 00228 @param sa What to set the standalone flag to. 00229 @author Peter Jones 00230 */ 00231 void set_is_standalone(bool sa); 00232 00233 /** 00234 Walk through the document and expand <xi:include> elements. For more 00235 information, please see the w3c recomendation for XInclude. 00236 http://www.w3.org/2001/XInclude. 00237 00238 The return value of this function may change to int after a bug has 00239 been fixed in libxml2 (xmlXIncludeDoProcess). 00240 00241 @return False if there was an error with substitutions. 00242 @return True if there were no errors (with or without substitutions). 00243 @author Peter Jones 00244 @author Daniel Evison 00245 */ 00246 bool process_xinclude(); 00247 00248 /** 00249 Test to see if this document has an internal subset. That is, DTD 00250 data that is declared within the XML document itself. 00251 00252 @return True if this document has an internal subset. 00253 @return False otherwise. 00254 @author Peter Jones 00255 */ 00256 bool has_internal_subset() const; 00257 00258 /** 00259 Test to see if this document has an external subset. That is, it 00260 references a DTD from an external source, such as a file or URL. 00261 00262 @return True if this document has an external subset. 00263 @return False otherwise. 00264 @author Peter Jones 00265 */ 00266 bool has_external_subset() const; 00267 00268 /** 00269 Validate this document against the DTD that has been attached to it. 00270 This would happen at parse time if there was a !DOCTYPE definition. 00271 If the DTD is valid, and the document is valid, this member function 00272 will return true. 00273 00274 If it returns false, you may want to send the document through 00275 xmllint to get the actual error messages. 00276 00277 @return True if the document is valid. 00278 @return False if there was a problem with the DTD or XML doc. 00279 @author Peter Jones 00280 */ 00281 bool validate(); 00282 00283 /** 00284 Parse the given DTD and try to validate this document against it. If 00285 the DTD is valid, and the document is valid, this member function 00286 will return true. 00287 00288 If it returns false, you may want to send the document through 00289 xmllint to get the actual error messages. 00290 00291 This member function will add the parsed DTD to this document as the 00292 external subset after the validation. If there is already an external 00293 DTD attached to this document it will be removed and deleted. 00294 00295 @param dtdname A filename or URL for the DTD to use. 00296 @return True if the document is valid. 00297 @return False if there was a problem with the DTD or XML doc. 00298 @author Peter Jones 00299 */ 00300 bool validate(const char *dtdname); 00301 00302 /** 00303 Returns the number of child nodes of this document. This will always 00304 be at least one, since all xmlwrapp documents must have a root node. 00305 This member function is useful to find out how many document children 00306 there are, including processing instructions, comments, etc. 00307 00308 @return The number of children nodes that this document has. 00309 @author Peter Jones 00310 */ 00311 size_type size() const; 00312 00313 /** 00314 Get an iterator to the first child node of this document. If what you 00315 really wanted was the root node (the first element) you should use 00316 the get_root_node() member function instead. 00317 00318 @return A xml::node::iterator that points to the first child node. 00319 @return An end iterator if there are no children in this document 00320 @author Peter Jones 00321 */ 00322 node::iterator begin(); 00323 00324 /** 00325 Get a const_iterator to the first child node of this document. If 00326 what you really wanted was the root node (the first element) you 00327 should use the get_root_node() member function instead. 00328 00329 @return A xml::node::const_iterator that points to the first child node. 00330 @return An end const_iterator if there are no children in this document. 00331 @author Peter Jones 00332 */ 00333 node::const_iterator begin() const; 00334 00335 /** 00336 Get an iterator that points one past the last child node for this 00337 document. 00338 00339 @return An end xml::node::iterator. 00340 @author Peter Jones 00341 */ 00342 node::iterator end(); 00343 00344 /** 00345 Get a const_iterator that points one past the last child node for 00346 this document. 00347 00348 @return An end xml::node::const_iterator. 00349 @author Peter Jones 00350 */ 00351 node::const_iterator end() const; 00352 00353 /** 00354 Add a child xml::node to this document. You should not add a element 00355 type node, since there can only be one root node. This member 00356 function is only useful for adding processing instructions, comments, 00357 etc.. If you do try to add a node of type element, an exception will 00358 be thrown. 00359 00360 @param child The child xml::node to add. 00361 @author Peter Jones 00362 */ 00363 void push_back (const node &child); 00364 00365 /** 00366 Insert a new child node. The new node will be inserted at the end of 00367 the child list. This is similar to the xml::node::push_back member 00368 function except that an iterator to the inserted node is returned. 00369 00370 The rules from the push_back member function apply here. Don't add a 00371 node of type element. 00372 00373 @param n The node to insert as a child of this document. 00374 @return An iterator that points to the newly inserted node. 00375 @see xml::document::push_back 00376 @author Peter Jones 00377 */ 00378 node::iterator insert (const node &n); 00379 00380 /** 00381 Insert a new child node. The new node will be inserted before the 00382 node pointed to by the given iterator. 00383 00384 The rules from the push_back member function apply here. Don't add a 00385 node of type element. 00386 00387 @param position An iterator that points to the location where the new node should be inserted (before it). 00388 @param n The node to insert as a child of this document. 00389 @return An iterator that points to the newly inserted node. 00390 @see xml::document::push_back 00391 @author Peter Jones 00392 */ 00393 node::iterator insert(node::iterator position, const node &n); 00394 00395 /** 00396 Replace the node pointed to by the given iterator with another node. 00397 The old node will be removed, including all its children, and 00398 replaced with the new node. This will invalidate any iterators that 00399 point to the node to be replaced, or any pointers or references to 00400 that node. 00401 00402 Do not replace this root node with this member function. The same 00403 rules that apply to push_back apply here. If you try to replace a 00404 node of type element, an exception will be thrown. 00405 00406 @param old_node An iterator that points to the node that should be removed. 00407 @param new_node The node to put in old_node's place. 00408 @return An iterator that points to the new node. 00409 @see xml::document::push_back 00410 @author Peter Jones 00411 */ 00412 node::iterator replace(node::iterator old_node, const node& new_node); 00413 00414 /** 00415 Erase the node that is pointed to by the given iterator. The node 00416 and all its children will be removed from this node. This will 00417 invalidate any iterators that point to the node to be erased, or any 00418 pointers or references to that node. 00419 00420 Do not remove the root node using this member function. The same 00421 rules that apply to push_back apply here. If you try to erase the 00422 root node, an exception will be thrown. 00423 00424 @param to_erase An iterator that points to the node to be erased. 00425 @return An iterator that points to the node after the one being erased. 00426 @see xml::document::push_back 00427 @author Peter Jones 00428 */ 00429 node::iterator erase(node::iterator to_erase); 00430 00431 /** 00432 Erase all nodes in the given range, from frist to last. This will 00433 invalidate any iterators that point to the nodes to be erased, or any 00434 pointers or references to those nodes. 00435 00436 Do not remove the root node using this member function. The same 00437 rules that apply to push_back apply here. If you try to erase the 00438 root node, an exception will be thrown. 00439 00440 @param first The first node in the range to be removed. 00441 @param last An iterator that points one past the last node to erase. Think xml::node::end(). 00442 @return An iterator that points to the node after the last one being erased. 00443 @see xml::document::push_back 00444 @author Peter Jones 00445 */ 00446 node::iterator erase(node::iterator first, node::iterator last); 00447 00448 /** 00449 Convert the XML document tree into XML text data and place it into 00450 the given string. 00451 00452 @param s The string to place the XML text data. 00453 @author Peter Jones 00454 */ 00455 void save_to_string(std::string& s) const; 00456 00457 /** 00458 Convert the XML document tree into XML text data and place it into 00459 the given filename. 00460 00461 @param filename The name of the file to place the XML text data into. 00462 @param compression_level 0 is no compression, 1-9 allowed, where 1 is 00463 for better speed, and 9 is for smaller size 00464 @return True if the data was saved successfully. 00465 @return False otherwise. 00466 @author Peter Jones 00467 */ 00468 bool save_to_file(const char *filename, int compression_level = 0) const; 00469 00470 /** 00471 Convert the XML document tree into XML text data and then insert it 00472 into the given stream. 00473 00474 @param stream The stream to insert the XML into. 00475 @param doc The document to insert. 00476 @return The stream from the first parameter. 00477 @author Peter Jones 00478 */ 00479 friend std::ostream& operator<< (std::ostream &stream, const document &doc); 00480 00481 private: 00482 impl::doc_impl *pimpl_; 00483 00484 void set_doc_data (void *data); 00485 void set_doc_data_from_xslt (void *data, xslt::impl::result *xr); 00486 void* get_doc_data(); 00487 void* get_doc_data_read_only() const; 00488 void* release_doc_data(); 00489 00490 friend class tree_parser; 00491 friend class xslt::stylesheet; 00492 }; 00493 00494 } // namespace xml 00495 00496 #endif // _xmlwrapp_document_h_