// ---------------------------------------------------------------------------- | |
// 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 <boost/property_tree/detail/ptree_utils.hpp> | |
#include <boost/property_tree/detail/xml_parser_error.hpp> | |
#include <boost/property_tree/detail/xml_parser_writer_settings.hpp> | |
#include <string> | |
#include <algorithm> | |
#include <locale> | |
namespace boost { namespace property_tree { namespace xml_parser | |
{ | |
template<class Ch> | |
std::basic_string<Ch> condense(const std::basic_string<Ch> &s) | |
{ | |
std::basic_string<Ch> r; | |
std::locale loc; | |
bool space = false; | |
typename std::basic_string<Ch>::const_iterator end = s.end(); | |
for (typename std::basic_string<Ch>::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<class Ch> | |
std::basic_string<Ch> encode_char_entities(const std::basic_string<Ch> &s) | |
{ | |
// Don't do anything for empty strings. | |
if(s.empty()) return s; | |
typedef typename std::basic_string<Ch> Str; | |
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<Ch>(" "); | |
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<Ch>("<"); break; | |
case Ch('>'): r += detail::widen<Ch>(">"); break; | |
case Ch('&'): r += detail::widen<Ch>("&"); break; | |
case Ch('"'): r += detail::widen<Ch>("""); break; | |
case Ch('\''): r += detail::widen<Ch>("'"); break; | |
default: r += *it; break; | |
} | |
} | |
} | |
return r; | |
} | |
template<class Ch> | |
std::basic_string<Ch> decode_char_entities(const std::basic_string<Ch> &s) | |
{ | |
typedef typename std::basic_string<Ch> Str; | |
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<Ch>("lt")) r += Ch('<'); | |
else if (ent == detail::widen<Ch>("gt")) r += Ch('>'); | |
else if (ent == detail::widen<Ch>("amp")) r += Ch('&'); | |
else if (ent == detail::widen<Ch>("quot")) r += Ch('"'); | |
else if (ent == detail::widen<Ch>("apos")) r += Ch('\''); | |
else | |
BOOST_PROPERTY_TREE_THROW(xml_parser_error("invalid character entity", "", 0)); | |
it = semicolon; | |
} | |
else | |
r += *it; | |
} | |
return r; | |
} | |
template<class Ch> | |
const std::basic_string<Ch> &xmldecl() | |
{ | |
static std::basic_string<Ch> s = detail::widen<Ch>("<?xml>"); | |
return s; | |
} | |
template<class Ch> | |
const std::basic_string<Ch> &xmlattr() | |
{ | |
static std::basic_string<Ch> s = detail::widen<Ch>("<xmlattr>"); | |
return s; | |
} | |
template<class Ch> | |
const std::basic_string<Ch> &xmlcomment() | |
{ | |
static std::basic_string<Ch> s = detail::widen<Ch>("<xmlcomment>"); | |
return s; | |
} | |
template<class Ch> | |
const std::basic_string<Ch> &xmltext() | |
{ | |
static std::basic_string<Ch> s = detail::widen<Ch>("<xmltext>"); | |
return s; | |
} | |
} } } | |
#endif |