xml_parser_utils.hpp 4.4 KB

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