// ---------------------------------------------------------------------------- // 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 #include #include #include #include #include namespace boost { namespace property_tree { namespace xml_parser { template void read_xml_node(detail::rapidxml::xml_node *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(), Ptree()))->second; for (xml_attribute *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 *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(), 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(), Ptree(node->value()))); } break; default: // Skip other node types break; } } template 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 v(std::istreambuf_iterator(stream.rdbuf()), std::istreambuf_iterator()); 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 doc; if (flags & no_comments) { if (flags & trim_whitespace) doc.BOOST_NESTED_TEMPLATE parse(&v.front()); else doc.BOOST_NESTED_TEMPLATE parse<0>(&v.front()); } else { if (flags & trim_whitespace) doc.BOOST_NESTED_TEMPLATE parse(&v.front()); else doc.BOOST_NESTED_TEMPLATE parse(&v.front()); } // Create ptree from nodes Ptree local; for (xml_node *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( std::count(&v.front(), e.where(), Ch('\n')) + 1); BOOST_PROPERTY_TREE_THROW( xml_parser_error(e.what(), filename, line)); } } } } } #endif