xml_parser_read_rapidxml.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // ----------------------------------------------------------------------------
  2. // Copyright (C) 2007 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_READ_RAPIDXML_HPP_INCLUDED
  11. #define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_READ_RAPIDXML_HPP_INCLUDED
  12. #include <boost/property_tree/ptree.hpp>
  13. #include <boost/property_tree/detail/xml_parser_error.hpp>
  14. #include <boost/property_tree/detail/xml_parser_flags.hpp>
  15. #include <boost/property_tree/detail/xml_parser_utils.hpp>
  16. #include <boost/property_tree/detail/rapidxml.hpp>
  17. #include <vector>
  18. namespace boost { namespace property_tree { namespace xml_parser
  19. {
  20. template<class Ptree, class Ch>
  21. void read_xml_node(detail::rapidxml::xml_node<Ch> *node,
  22. Ptree &pt, int flags)
  23. {
  24. using namespace detail::rapidxml;
  25. switch (node->type())
  26. {
  27. // Element nodes
  28. case node_element:
  29. {
  30. // Create node
  31. Ptree &pt_node = pt.push_back(std::make_pair(node->name(),
  32. Ptree()))->second;
  33. // Copy attributes
  34. if (node->first_attribute())
  35. {
  36. Ptree &pt_attr_root = pt_node.push_back(
  37. std::make_pair(xmlattr<typename Ptree::key_type>(), Ptree()))->second;
  38. for (xml_attribute<Ch> *attr = node->first_attribute();
  39. attr; attr = attr->next_attribute())
  40. {
  41. Ptree &pt_attr = pt_attr_root.push_back(
  42. std::make_pair(attr->name(), Ptree()))->second;
  43. pt_attr.data() = typename Ptree::key_type(attr->value(), attr->value_size());
  44. }
  45. }
  46. // Copy children
  47. for (xml_node<Ch> *child = node->first_node();
  48. child; child = child->next_sibling())
  49. read_xml_node(child, pt_node, flags);
  50. }
  51. break;
  52. // Data nodes
  53. case node_data:
  54. case node_cdata:
  55. {
  56. if (flags & no_concat_text)
  57. pt.push_back(std::make_pair(xmltext<typename Ptree::key_type>(),
  58. Ptree(node->value())));
  59. else
  60. pt.data() += typename Ptree::key_type(node->value(), node->value_size());
  61. }
  62. break;
  63. // Comment nodes
  64. case node_comment:
  65. {
  66. if (!(flags & no_comments))
  67. pt.push_back(std::make_pair(xmlcomment<typename Ptree::key_type>(),
  68. Ptree(typename Ptree::key_type(node->value(), node->value_size()))));
  69. }
  70. break;
  71. default:
  72. // Skip other node types
  73. break;
  74. }
  75. }
  76. template<class Ptree>
  77. void read_xml_internal(std::basic_istream<
  78. typename Ptree::key_type::value_type> &stream,
  79. Ptree &pt,
  80. int flags,
  81. const std::string &filename)
  82. {
  83. typedef typename Ptree::key_type::value_type Ch;
  84. using namespace detail::rapidxml;
  85. // Load data into vector
  86. stream.unsetf(std::ios::skipws);
  87. std::vector<Ch> v(std::istreambuf_iterator<Ch>(stream.rdbuf()),
  88. std::istreambuf_iterator<Ch>());
  89. if (!stream.good())
  90. BOOST_PROPERTY_TREE_THROW(
  91. xml_parser_error("read error", filename, 0));
  92. v.push_back(0); // zero-terminate
  93. try {
  94. // Parse using appropriate flags
  95. const int f_tws = parse_normalize_whitespace
  96. | parse_trim_whitespace;
  97. const int f_c = parse_comment_nodes;
  98. // Some compilers don't like the bitwise or in the template arg.
  99. const int f_tws_c = parse_normalize_whitespace
  100. | parse_trim_whitespace
  101. | parse_comment_nodes;
  102. xml_document<Ch> doc;
  103. if (flags & no_comments) {
  104. if (flags & trim_whitespace)
  105. doc.BOOST_NESTED_TEMPLATE parse<f_tws>(&v.front());
  106. else
  107. doc.BOOST_NESTED_TEMPLATE parse<0>(&v.front());
  108. } else {
  109. if (flags & trim_whitespace)
  110. doc.BOOST_NESTED_TEMPLATE parse<f_tws_c>(&v.front());
  111. else
  112. doc.BOOST_NESTED_TEMPLATE parse<f_c>(&v.front());
  113. }
  114. // Create ptree from nodes
  115. Ptree local;
  116. for (xml_node<Ch> *child = doc.first_node();
  117. child; child = child->next_sibling())
  118. read_xml_node(child, local, flags);
  119. // Swap local and result ptrees
  120. pt.swap(local);
  121. } catch (parse_error &e) {
  122. long line = static_cast<long>(
  123. std::count(&v.front(), e.where<Ch>(), Ch('\n')) + 1);
  124. BOOST_PROPERTY_TREE_THROW(
  125. xml_parser_error(e.what(), filename, line));
  126. }
  127. }
  128. } } }
  129. #endif