1 #ifndef XML_GENERATOR_CLASS
2 #define XML_GENERATOR_CLASS
4 /*****************************************************************************\
6 * Name : xml_generator *
7 * Author : Chris Koeritz *
9 *******************************************************************************
10 * Copyright (c) 2007-$now By Author. This program is free software; you can *
11 * redistribute it and/or modify it under the terms of the GNU General Public *
12 * License as published by the Free Software Foundation; either version 2 of *
13 * the License or (at your option) any later version. This is online at: *
14 * http://www.fsf.org/copyleft/gpl.html *
15 * Please send any updates to: fred@gruntose.com *
16 \*****************************************************************************/
18 #include <basis/astring.h>
19 #include <basis/contracts.h>
20 #include <structures/string_table.h>
27 //! Supports simple XML output with consistency checking.
32 enum behavioral_mods {
34 CLEAN_ILLEGAL_CHARS = 0x2
37 xml_generator(int modifiers = HUMAN_READABLE | CLEAN_ILLEGAL_CHARS);
38 //!< creates an xml generator with the specified behavior.
40 virtual ~xml_generator();
42 DEFINE_CLASS_NAME("xml_generator");
44 //! the possible ways that operations here can complete.
46 OKAY = basis::common::OKAY,
47 NOT_FOUND = basis::common::NOT_FOUND,
48 ERRONEOUS_TAG = basis::common::INVALID //temporary until we can shed a compatibility concern.
49 // DEF INE_OUTCOME(ERRONEOUS_TAG, -75, "The most recently opened tag must be "
50 // "closed before a new tag can be opened and before any other tag can "
54 static const char *outcome_name(const basis::outcome &to_name);
55 //!< reports the string version of "to_name".
57 void reset(); //!< throws out all accumulated information.
59 basis::astring generate();
60 //!< writes the current state into a string and returns it.
61 /*!< if there was an error during generation, the string will be empty.
62 note that unclosed tags are not considered an error; they will simply be
63 closed. note that the accumulated string is not cleared after the
64 generate() invocation. use reset() to clear out all prior state. */
66 void generate(basis::astring &generated);
67 //!< synonym method, writes the current state into "generated".
69 basis::outcome add_header(const basis::astring &tag_name, const structures::string_table &attributes);
70 //!< adds an xml style header with the "tag_name" and "attributes".
71 /*!< headers can be located anywhere in the file. */
73 basis::outcome open_tag(const basis::astring &tag_name, const structures::string_table &attributes);
74 //!< adds a tag with "tag_name" and the "attributes", if any.
75 /*!< this adds an item into the output string in the form: @code
76 <tag_name attrib1="value1" attrib2="value2"...> @endcode
77 it is required that you close the tag later on, after the tag's contents
80 basis::outcome open_tag(const basis::astring &tag_name);
81 //!< adds a tag with "tag_name" without any attributes.
83 basis::outcome close_tag(const basis::astring &tag_name);
84 //!< closes a previously added "tag_name".
85 /*!< this will generate xml code like so: @code
87 note that it is an error to try to close any tag but the most recently
90 void close_all_tags();
91 //!< a wide-bore method that closes all outstanding tags.
93 basis::outcome add_content(const basis::astring &content);
94 //!< stores content into the currently opened tag.
95 /*!< it is an error to add content when no tag is open. */
97 void set_indentation(int to_indent);
98 //!< sets the number of spaces to indent for the human readable form.
100 static basis::astring clean_reserved(const basis::astring &to_modify,
101 bool replace_spaces = false);
102 //!< returns a cleaned version of "to_modify" to make it XML appropriate.
103 /*!< if "replace_spaces" is true, then any spaces will be turned into
104 their html code equivalent; this helps in attribute names. */
106 static void clean_reserved_mod(basis::astring &to_modify,
107 bool replace_spaces = false);
108 //!< ensures that "to_modify" contains only characters valid for XML.
109 /*!< this is only different from the other clean method because this
110 one modifies the string in place. */
113 tag_stack *_tags; //!< the already opened tags.
114 basis::astring *_accumulator; //!< stores our output.
115 bool _human_read; //!< true if the output should be human readable.
116 bool _clean_chars; //!< true if strings should be validated and repaired.
117 int _indentation; //!< number of spaces per level of xml.
119 enum open_types { NORMAL_TAG, HEADER_TAG };
120 void print_open_tag(const tag_info &to_print, int type = NORMAL_TAG);
121 //!< opens the tag for to_print by showing the tag name and attributes.
122 void print_close_tag(const basis::astring &tag_name);
123 //!< closes the tag for "tag_name" in the output string.