1 // ---------------------------------------------------------------------------- 2 // Copyright (C) 2002-2006 Marcin Kalicinski 3 // 4 // Distributed under the Boost Software License, Version 1.0. 5 // (See accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt) 7 // 8 // For more information, see www.boost.org 9 // ---------------------------------------------------------------------------- 10 #ifndef BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_UTILS_HPP_INCLUDED 11 #define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_UTILS_HPP_INCLUDED 12 13 #include <boost/property_tree/detail/ptree_utils.hpp> 14 #include <boost/property_tree/detail/xml_parser_error.hpp> 15 #include <boost/property_tree/detail/xml_parser_writer_settings.hpp> 16 #include <string> 17 #include <algorithm> 18 #include <locale> 19 20 namespace boost { namespace property_tree { namespace xml_parser 21 { 22 23 template<class Str> condense(const Str & s)24 Str condense(const Str &s) 25 { 26 typedef typename Str::value_type Ch; 27 Str r; 28 std::locale loc; 29 bool space = false; 30 typename Str::const_iterator end = s.end(); 31 for (typename Str::const_iterator it = s.begin(); 32 it != end; ++it) 33 { 34 if (isspace(*it, loc) || *it == Ch('\n')) 35 { 36 if (!space) 37 r += Ch(' '), space = true; 38 } 39 else 40 r += *it, space = false; 41 } 42 return r; 43 } 44 45 46 template<class Str> encode_char_entities(const Str & s)47 Str encode_char_entities(const Str &s) 48 { 49 // Don't do anything for empty strings. 50 if(s.empty()) return s; 51 52 typedef typename Str::value_type Ch; 53 54 Str r; 55 // To properly round-trip spaces and not uglify the XML beyond 56 // recognition, we have to encode them IF the text contains only spaces. 57 Str sp(1, Ch(' ')); 58 if(s.find_first_not_of(sp) == Str::npos) { 59 // The first will suffice. 60 r = detail::widen<Str>(" "); 61 r += Str(s.size() - 1, Ch(' ')); 62 } else { 63 typename Str::const_iterator end = s.end(); 64 for (typename Str::const_iterator it = s.begin(); it != end; ++it) 65 { 66 switch (*it) 67 { 68 case Ch('<'): r += detail::widen<Str>("<"); break; 69 case Ch('>'): r += detail::widen<Str>(">"); break; 70 case Ch('&'): r += detail::widen<Str>("&"); break; 71 case Ch('"'): r += detail::widen<Str>("""); break; 72 case Ch('\''): r += detail::widen<Str>("'"); break; 73 default: r += *it; break; 74 } 75 } 76 } 77 return r; 78 } 79 80 template<class Str> decode_char_entities(const Str & s)81 Str decode_char_entities(const Str &s) 82 { 83 typedef typename Str::value_type Ch; 84 Str r; 85 typename Str::const_iterator end = s.end(); 86 for (typename Str::const_iterator it = s.begin(); it != end; ++it) 87 { 88 if (*it == Ch('&')) 89 { 90 typename Str::const_iterator semicolon = std::find(it + 1, end, Ch(';')); 91 if (semicolon == end) 92 BOOST_PROPERTY_TREE_THROW(xml_parser_error("invalid character entity", "", 0)); 93 Str ent(it + 1, semicolon); 94 if (ent == detail::widen<Str>("lt")) r += Ch('<'); 95 else if (ent == detail::widen<Str>("gt")) r += Ch('>'); 96 else if (ent == detail::widen<Str>("amp")) r += Ch('&'); 97 else if (ent == detail::widen<Str>("quot")) r += Ch('"'); 98 else if (ent == detail::widen<Str>("apos")) r += Ch('\''); 99 else 100 BOOST_PROPERTY_TREE_THROW(xml_parser_error("invalid character entity", "", 0)); 101 it = semicolon; 102 } 103 else 104 r += *it; 105 } 106 return r; 107 } 108 109 template<class Str> xmldecl()110 const Str &xmldecl() 111 { 112 static Str s = detail::widen<Str>("<?xml>"); 113 return s; 114 } 115 116 template<class Str> xmlattr()117 const Str &xmlattr() 118 { 119 static Str s = detail::widen<Str>("<xmlattr>"); 120 return s; 121 } 122 123 template<class Str> xmlcomment()124 const Str &xmlcomment() 125 { 126 static Str s = detail::widen<Str>("<xmlcomment>"); 127 return s; 128 } 129 130 template<class Str> xmltext()131 const Str &xmltext() 132 { 133 static Str s = detail::widen<Str>("<xmltext>"); 134 return s; 135 } 136 137 } } } 138 139 #endif 140