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
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>
18#include <vector>
19
20namespace boost { namespace property_tree { namespace xml_parser
21{
22
23 template<class Ptree, class Ch>
24 void read_xml_node(detail::rapidxml::xml_node<Ch> *node,
25 Ptree &pt, int flags)
26 {
27 using namespace detail::rapidxml;
28 switch (node->type())
29 {
30 // Element nodes
31 case node_element:
32 {
33 // Create node
34 Ptree &pt_node = pt.push_back(std::make_pair(node->name(),
35 Ptree()))->second;
36
37 // Copy attributes
38 if (node->first_attribute())
39 {
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())
44 {
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());
48 }
49 }
50
51 // Copy children
52 for (xml_node<Ch> *child = node->first_node();
53 child; child = child->next_sibling())
54 read_xml_node(child, pt_node, flags);
55 }
56 break;
57
58 // Data nodes
59 case node_data:
60 case node_cdata:
61 {
62 if (flags & no_concat_text)
63 pt.push_back(std::make_pair(xmltext<typename Ptree::key_type>(),
64 Ptree(node->value())));
65 else
66 pt.data() += typename Ptree::key_type(node->value(), node->value_size());
67 }
68 break;
69
70 // Comment nodes
71 case node_comment:
72 {
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()))));
76 }
77 break;
78
79 default:
80 // Skip other node types
81 break;
82 }
83 }
84
85 template<class Ptree>
86 void read_xml_internal(std::basic_istream<
87 typename Ptree::key_type::value_type> &stream,
88 Ptree &pt,
89 int flags,
90 const std::string &filename)
91 {
92 typedef typename Ptree::key_type::value_type Ch;
93 using namespace detail::rapidxml;
94
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>());
99 if (!stream.good())
100 BOOST_PROPERTY_TREE_THROW(
101 xml_parser_error("read error", filename, 0));
102 v.push_back(0); // zero-terminate
103
104 try {
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());
117 else
118 doc.BOOST_NESTED_TEMPLATE parse<0>(&v.front());
119 } else {
120 if (flags & trim_whitespace)
121 doc.BOOST_NESTED_TEMPLATE parse<f_tws_c>(&v.front());
122 else
123 doc.BOOST_NESTED_TEMPLATE parse<f_c>(&v.front());
124 }
125
126 // Create ptree from nodes
127 Ptree local;
128 for (xml_node<Ch> *child = doc.first_node();
129 child; child = child->next_sibling())
130 read_xml_node(child, local, flags);
131
132 // Swap local and result ptrees
133 pt.swap(local);
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));
139 }
140 }
141
142} } }
143
144#endif
145

source code of boost/libs/property_tree/include/boost/property_tree/detail/xml_parser_read_rapidxml.hpp