Chris@16: // ---------------------------------------------------------------------------- Chris@16: // Copyright (C) 2002-2006 Marcin Kalicinski Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. Chris@16: // (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // For more information, see www.boost.org Chris@16: // ---------------------------------------------------------------------------- Chris@16: #ifndef BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_UTILS_HPP_INCLUDED Chris@16: #define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_UTILS_HPP_INCLUDED Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace property_tree { namespace xml_parser Chris@16: { Chris@16: Chris@101: template Chris@101: Str condense(const Str &s) Chris@16: { Chris@101: typedef typename Str::value_type Ch; Chris@101: Str r; Chris@16: std::locale loc; Chris@16: bool space = false; Chris@101: typename Str::const_iterator end = s.end(); Chris@101: for (typename Str::const_iterator it = s.begin(); Chris@16: it != end; ++it) Chris@16: { Chris@16: if (isspace(*it, loc) || *it == Ch('\n')) Chris@16: { Chris@16: if (!space) Chris@16: r += Ch(' '), space = true; Chris@16: } Chris@16: else Chris@16: r += *it, space = false; Chris@16: } Chris@16: return r; Chris@16: } Chris@16: Chris@101: Chris@101: template Chris@101: Str encode_char_entities(const Str &s) Chris@16: { Chris@16: // Don't do anything for empty strings. Chris@16: if(s.empty()) return s; Chris@16: Chris@101: typedef typename Str::value_type Ch; Chris@101: Chris@16: Str r; Chris@16: // To properly round-trip spaces and not uglify the XML beyond Chris@16: // recognition, we have to encode them IF the text contains only spaces. Chris@16: Str sp(1, Ch(' ')); Chris@16: if(s.find_first_not_of(sp) == Str::npos) { Chris@16: // The first will suffice. Chris@101: r = detail::widen(" "); Chris@16: r += Str(s.size() - 1, Ch(' ')); Chris@16: } else { Chris@16: typename Str::const_iterator end = s.end(); Chris@16: for (typename Str::const_iterator it = s.begin(); it != end; ++it) Chris@16: { Chris@16: switch (*it) Chris@16: { Chris@101: case Ch('<'): r += detail::widen("<"); break; Chris@101: case Ch('>'): r += detail::widen(">"); break; Chris@101: case Ch('&'): r += detail::widen("&"); break; Chris@101: case Ch('"'): r += detail::widen("""); break; Chris@101: case Ch('\''): r += detail::widen("'"); break; Chris@101: case Ch('\t'): r += detail::widen(" "); break; Chris@101: case Ch('\n'): r += detail::widen(" "); break; Chris@16: default: r += *it; break; Chris@16: } Chris@16: } Chris@16: } Chris@16: return r; Chris@16: } Chris@16: Chris@101: template Chris@101: Str decode_char_entities(const Str &s) Chris@16: { Chris@101: typedef typename Str::value_type Ch; Chris@16: Str r; Chris@16: typename Str::const_iterator end = s.end(); Chris@16: for (typename Str::const_iterator it = s.begin(); it != end; ++it) Chris@16: { Chris@16: if (*it == Ch('&')) Chris@16: { Chris@16: typename Str::const_iterator semicolon = std::find(it + 1, end, Ch(';')); Chris@16: if (semicolon == end) Chris@16: BOOST_PROPERTY_TREE_THROW(xml_parser_error("invalid character entity", "", 0)); Chris@16: Str ent(it + 1, semicolon); Chris@101: if (ent == detail::widen("lt")) r += Ch('<'); Chris@101: else if (ent == detail::widen("gt")) r += Ch('>'); Chris@101: else if (ent == detail::widen("amp")) r += Ch('&'); Chris@101: else if (ent == detail::widen("quot")) r += Ch('"'); Chris@101: else if (ent == detail::widen("apos")) r += Ch('\''); Chris@16: else Chris@16: BOOST_PROPERTY_TREE_THROW(xml_parser_error("invalid character entity", "", 0)); Chris@16: it = semicolon; Chris@16: } Chris@16: else Chris@16: r += *it; Chris@16: } Chris@16: return r; Chris@16: } Chris@16: Chris@101: template Chris@101: const Str &xmldecl() Chris@16: { Chris@101: static Str s = detail::widen(""); Chris@16: return s; Chris@16: } Chris@16: Chris@101: template Chris@101: const Str &xmlattr() Chris@16: { Chris@101: static Str s = detail::widen(""); Chris@16: return s; Chris@16: } Chris@16: Chris@101: template Chris@101: const Str &xmlcomment() Chris@16: { Chris@101: static Str s = detail::widen(""); Chris@16: return s; Chris@16: } Chris@16: Chris@101: template Chris@101: const Str &xmltext() Chris@16: { Chris@101: static Str s = detail::widen(""); Chris@16: return s; Chris@16: } Chris@16: Chris@16: } } } Chris@16: Chris@16: #endif