File indexing completed on 2025-01-18 09:50:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_WRITE_HPP_INCLUDED
0012 #define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_WRITE_HPP_INCLUDED
0013
0014 #include <boost/property_tree/ptree.hpp>
0015 #include <boost/property_tree/detail/xml_parser_utils.hpp>
0016 #include <boost/optional/optional.hpp>
0017 #include <string>
0018 #include <ostream>
0019 #include <iomanip>
0020
0021 namespace boost { namespace property_tree { namespace xml_parser
0022 {
0023 template<class Str>
0024 void write_xml_indent(std::basic_ostream<typename Str::value_type> &stream,
0025 int indent,
0026 const xml_writer_settings<Str> & settings
0027 )
0028 {
0029 stream << std::basic_string<typename Str::value_type>(indent * settings.indent_count, settings.indent_char);
0030 }
0031
0032 template<class Str>
0033 void write_xml_comment(std::basic_ostream<typename Str::value_type> &stream,
0034 const Str &s,
0035 int indent,
0036 bool separate_line,
0037 const xml_writer_settings<Str> & settings
0038 )
0039 {
0040 typedef typename Str::value_type Ch;
0041 if (separate_line)
0042 write_xml_indent(stream,indent,settings);
0043 stream << Ch('<') << Ch('!') << Ch('-') << Ch('-');
0044 stream << s;
0045 stream << Ch('-') << Ch('-') << Ch('>');
0046 if (separate_line)
0047 stream << Ch('\n');
0048 }
0049
0050 template<class Str>
0051 void write_xml_text(std::basic_ostream<typename Str::value_type> &stream,
0052 const Str &s,
0053 int indent,
0054 bool separate_line,
0055 const xml_writer_settings<Str> & settings
0056 )
0057 {
0058 typedef typename Str::value_type Ch;
0059 if (separate_line)
0060 write_xml_indent(stream,indent,settings);
0061 stream << encode_char_entities(s);
0062 if (separate_line)
0063 stream << Ch('\n');
0064 }
0065
0066 template<class Ptree>
0067 void write_xml_element(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
0068 const typename Ptree::key_type &key,
0069 const Ptree &pt,
0070 int indent,
0071 const xml_writer_settings<typename Ptree::key_type> & settings)
0072 {
0073 typedef typename Ptree::key_type::value_type Ch;
0074 typedef typename Ptree::key_type Str;
0075 typedef typename Ptree::const_iterator It;
0076
0077 bool want_pretty = settings.indent_count > 0;
0078
0079 bool has_elements = false;
0080 bool has_attrs_only = pt.data().empty();
0081 for (It it = pt.begin(), end = pt.end(); it != end; ++it)
0082 {
0083 if (it->first != xmlattr<Str>() )
0084 {
0085 has_attrs_only = false;
0086 if (it->first != xmltext<Str>())
0087 {
0088 has_elements = true;
0089 break;
0090 }
0091 }
0092 }
0093
0094
0095 if (pt.data().empty() && pt.empty())
0096 {
0097 if (indent >= 0)
0098 {
0099 write_xml_indent(stream,indent,settings);
0100 stream << Ch('<') << key <<
0101 Ch('/') << Ch('>');
0102 if (want_pretty)
0103 stream << Ch('\n');
0104 }
0105 }
0106 else
0107 {
0108
0109 if (indent >= 0)
0110 {
0111
0112 write_xml_indent(stream,indent,settings);
0113 stream << Ch('<') << key;
0114
0115
0116 if (optional<const Ptree &> attribs = pt.get_child_optional(xmlattr<Str>()))
0117 for (It it = attribs.get().begin(); it != attribs.get().end(); ++it)
0118 stream << Ch(' ') << it->first << Ch('=')
0119 << Ch('"')
0120 << encode_char_entities(
0121 it->second.template get_value<Str>())
0122 << Ch('"');
0123
0124 if ( has_attrs_only )
0125 {
0126
0127 stream << Ch('/') << Ch('>');
0128 if (want_pretty)
0129 stream << Ch('\n');
0130 }
0131 else
0132 {
0133
0134 stream << Ch('>');
0135
0136
0137 if (has_elements && want_pretty)
0138 stream << Ch('\n');
0139 }
0140 }
0141
0142
0143 if (!pt.data().empty())
0144 write_xml_text(stream,
0145 pt.template get_value<Str>(),
0146 indent + 1, has_elements && want_pretty, settings);
0147
0148
0149 for (It it = pt.begin(); it != pt.end(); ++it)
0150 {
0151 if (it->first == xmlattr<Str>())
0152 continue;
0153 else if (it->first == xmlcomment<Str>())
0154 write_xml_comment(stream,
0155 it->second.template get_value<Str>(),
0156 indent + 1, want_pretty, settings);
0157 else if (it->first == xmltext<Str>())
0158 write_xml_text(stream,
0159 it->second.template get_value<Str>(),
0160 indent + 1, has_elements && want_pretty, settings);
0161 else
0162 write_xml_element(stream, it->first, it->second,
0163 indent + 1, settings);
0164 }
0165
0166
0167 if (indent >= 0 && !has_attrs_only)
0168 {
0169 if (has_elements)
0170 write_xml_indent(stream,indent,settings);
0171 stream << Ch('<') << Ch('/') << key << Ch('>');
0172 if (want_pretty)
0173 stream << Ch('\n');
0174 }
0175
0176 }
0177 }
0178
0179 template<class Ptree>
0180 void write_xml_internal(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
0181 const Ptree &pt,
0182 const std::string &filename,
0183 const xml_writer_settings<typename Ptree::key_type> & settings)
0184 {
0185 typedef typename Ptree::key_type Str;
0186 stream << detail::widen<Str>("<?xml version=\"1.0\" encoding=\"")
0187 << settings.encoding
0188 << detail::widen<Str>("\"?>\n");
0189 write_xml_element(stream, Str(), pt, -1, settings);
0190 stream.flush();
0191 if (!stream)
0192 BOOST_PROPERTY_TREE_THROW(xml_parser_error("write error", filename, 0));
0193 }
0194
0195 } } }
0196
0197 #endif