1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
// ----------------------------------------------------------------------------
// 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
|