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