// ---------------------------------------------------------------------------- | |
// 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 |