text: // ----------------------------------------------------------------------------
  // Copyright (C) 2007 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_READ_RAPIDXML_HPP_INCLUDED
  #define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_READ_RAPIDXML_HPP_INCLUDED
  
  #include <boost/property_tree/ptree.hpp>
  #include <boost/property_tree/detail/xml_parser_error.hpp>
  #include <boost/property_tree/detail/xml_parser_flags.hpp>
  #include <boost/property_tree/detail/xml_parser_utils.hpp>
  #include <boost/property_tree/detail/rapidxml.hpp>
  #include <vector>
  
  namespace boost { namespace property_tree { namespace xml_parser
  {
  
      template<class Ptree, class Ch>
      void read_xml_node(detail::rapidxml::xml_node<Ch> *node,
                         Ptree &pt, int flags)
      {
          using namespace detail::rapidxml;
          switch (node->type())
          {
              // Element nodes
              case node_element: 
              {
                  // Create node
                  Ptree &pt_node = pt.push_back(std::make_pair(node->name(),
                                                               Ptree()))->second;
  
                  // Copy attributes
                  if (node->first_attribute())
                  {
                      Ptree &pt_attr_root = pt_node.push_back(
                          std::make_pair(xmlattr<Ch>(), Ptree()))->second;
                      for (xml_attribute<Ch> *attr = node->first_attribute();
                           attr; attr = attr->next_attribute())
                      {
                          Ptree &pt_attr = pt_attr_root.push_back(
                              std::make_pair(attr->name(), Ptree()))->second;
                          pt_attr.data() = attr->value();
                      }
                  }
  
                  // Copy children
                  for (xml_node<Ch> *child = node->first_node();
                       child; child = child->next_sibling())
                      read_xml_node(child, pt_node, flags);
              }
              break;
  
              // Data nodes
              case node_data:
              case node_cdata:
              {
                  if (flags & no_concat_text)
                      pt.push_back(std::make_pair(xmltext<Ch>(),
                                                  Ptree(node->value())));
                  else
                      pt.data() += node->value();
              }
              break;
  
              // Comment nodes
              case node_comment:
              {
                  if (!(flags & no_comments))
                      pt.push_back(std::make_pair(xmlcomment<Ch>(),
                                                  Ptree(node->value())));
              }
              break;
  
              default:
                  // Skip other node types
                  break;
          }
      }
  
      template<class Ptree>
      void read_xml_internal(std::basic_istream<
                                 typename Ptree::key_type::value_type> &stream,
                             Ptree &pt,
                             int flags,
                             const std::string &filename)
      {
          typedef typename Ptree::key_type::value_type Ch;
          using namespace detail::rapidxml;
  
          // Load data into vector
          stream.unsetf(std::ios::skipws);
          std::vector<Ch> v(std::istreambuf_iterator<Ch>(stream.rdbuf()),
                            std::istreambuf_iterator<Ch>());
          if (!stream.good())
              BOOST_PROPERTY_TREE_THROW(
                  xml_parser_error("read error", filename, 0));
          v.push_back(0); // zero-terminate
  
          try {
              // Parse using appropriate flags
              const int f_tws = parse_normalize_whitespace
                              | parse_trim_whitespace;
              const int f_c = parse_comment_nodes;
              // Some compilers don't like the bitwise or in the template arg.
              const int f_tws_c = parse_normalize_whitespace
                                | parse_trim_whitespace
                                | parse_comment_nodes;
              xml_document<Ch> doc;
              if (flags & no_comments) {
                  if (flags & trim_whitespace)
                      doc.BOOST_NESTED_TEMPLATE parse<f_tws>(&v.front());
                  else
                      doc.BOOST_NESTED_TEMPLATE parse<0>(&v.front());
              } else {
                  if (flags & trim_whitespace)
                      doc.BOOST_NESTED_TEMPLATE parse<f_tws_c>(&v.front());
                  else
                      doc.BOOST_NESTED_TEMPLATE parse<f_c>(&v.front());
              }
  
              // Create ptree from nodes
              Ptree local;
              for (xml_node<Ch> *child = doc.first_node();
                   child; child = child->next_sibling())
                  read_xml_node(child, local, flags);
  
              // Swap local and result ptrees
              pt.swap(local);
          } catch (parse_error &e) {
              long line = static_cast<long>(
                  std::count(&v.front(), e.where<Ch>(), Ch('\n')) + 1);
              BOOST_PROPERTY_TREE_THROW(
                  xml_parser_error(e.what(), filename, line));  
          }
      }
  
  } } }
  
  #endif
  