1 // ----------------------------------------------------------------------------
2 // Copyright (C) 2007 Marcin Kalicinski
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)
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
13 #include <boost/property_tree/ptree.hpp>
14 #include <boost/property_tree/detail/xml_parser_error.hpp>
15 #include <boost/property_tree/detail/xml_parser_flags.hpp>
16 #include <boost/property_tree/detail/xml_parser_utils.hpp>
17 #include <boost/property_tree/detail/rapidxml.hpp>
20 namespace boost { namespace property_tree { namespace xml_parser
23 template<class Ptree, class Ch>
24 void read_xml_node(detail::rapidxml::xml_node<Ch> *node,
27 using namespace detail::rapidxml;
34 Ptree &pt_node = pt.push_back(std::make_pair(node->name(),
38 if (node->first_attribute())
40 Ptree &pt_attr_root = pt_node.push_back(
41 std::make_pair(xmlattr<typename Ptree::key_type>(), Ptree()))->second;
42 for (xml_attribute<Ch> *attr = node->first_attribute();
43 attr; attr = attr->next_attribute())
45 Ptree &pt_attr = pt_attr_root.push_back(
46 std::make_pair(attr->name(), Ptree()))->second;
47 pt_attr.data() = typename Ptree::key_type(attr->value(), attr->value_size());
52 for (xml_node<Ch> *child = node->first_node();
53 child; child = child->next_sibling())
54 read_xml_node(child, pt_node, flags);
62 if (flags & no_concat_text)
63 pt.push_back(std::make_pair(xmltext<typename Ptree::key_type>(),
64 Ptree(node->value())));
66 pt.data() += typename Ptree::key_type(node->value(), node->value_size());
73 if (!(flags & no_comments))
74 pt.push_back(std::make_pair(xmlcomment<typename Ptree::key_type>(),
75 Ptree(typename Ptree::key_type(node->value(), node->value_size()))));
80 // Skip other node types
86 void read_xml_internal(std::basic_istream<
87 typename Ptree::key_type::value_type> &stream,
90 const std::string &filename)
92 typedef typename Ptree::key_type::value_type Ch;
93 using namespace detail::rapidxml;
95 // Load data into vector
96 stream.unsetf(std::ios::skipws);
97 std::vector<Ch> v(std::istreambuf_iterator<Ch>(stream.rdbuf()),
98 std::istreambuf_iterator<Ch>());
100 BOOST_PROPERTY_TREE_THROW(
101 xml_parser_error("read error", filename, 0));
102 v.push_back(0); // zero-terminate
105 // Parse using appropriate flags
106 const int f_tws = parse_normalize_whitespace
107 | parse_trim_whitespace;
108 const int f_c = parse_comment_nodes;
109 // Some compilers don't like the bitwise or in the template arg.
110 const int f_tws_c = parse_normalize_whitespace
111 | parse_trim_whitespace
112 | parse_comment_nodes;
113 xml_document<Ch> doc;
114 if (flags & no_comments) {
115 if (flags & trim_whitespace)
116 doc.BOOST_NESTED_TEMPLATE parse<f_tws>(&v.front());
118 doc.BOOST_NESTED_TEMPLATE parse<0>(&v.front());
120 if (flags & trim_whitespace)
121 doc.BOOST_NESTED_TEMPLATE parse<f_tws_c>(&v.front());
123 doc.BOOST_NESTED_TEMPLATE parse<f_c>(&v.front());
126 // Create ptree from nodes
128 for (xml_node<Ch> *child = doc.first_node();
129 child; child = child->next_sibling())
130 read_xml_node(child, local, flags);
132 // Swap local and result ptrees
134 } catch (parse_error &e) {
135 long line = static_cast<long>(
136 std::count(&v.front(), e.where<Ch>(), Ch('\n')) + 1);
137 BOOST_PROPERTY_TREE_THROW(
138 xml_parser_error(e.what(), filename, line));