xml_parser_utils.hpp 4.6 KB

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