Example #1
0
typename Ptree::size_type total_data_size(const Ptree &pt)
{
    typename Ptree::size_type size = pt.data().size();
    for (typename Ptree::const_iterator it = pt.begin(); it != pt.end(); ++it)
        size += total_data_size(it->second);
    return size;
}
    void read_xml_node(detail::pdalboostrapidxml::xml_node<Ch> *node,
                       Ptree &pt, int flags)
    {
        using namespace detail::pdalboostrapidxml;
        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<typename Ptree::key_type>(), 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() = typename Ptree::key_type(attr->value(), attr->value_size());
                    }
                }

                // 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<typename Ptree::key_type>(),
                                                Ptree(node->value())));
                else
                    pt.data() += typename Ptree::key_type(node->value(), node->value_size());
            }
            break;

            // Comment nodes
            case node_comment:
            {
                if (!(flags & no_comments))
                    pt.push_back(std::make_pair(xmlcomment<typename Ptree::key_type>(),
                                    Ptree(typename Ptree::key_type(node->value(), node->value_size()))));
            }
            break;

            default:
                // Skip other node types
                break;
        }
    }
    void read_xml_node( pugi::xml_node node, Ptree &pt, int flags)
    {
        typedef typename Ptree::key_type::value_type Ch;

        switch ( node.type() )
        {
            case pugi::node_element:
                {
                    Ptree &tmp = pt.push_back(std::make_pair( node.name(), Ptree()))->second;
                    for ( pugi::xml_attribute attr = node.first_attribute(); attr; attr = attr.next_attribute() )
                        tmp.put( xmlattr<Ch>() + "." + attr.name(), attr.value());
                    for ( pugi::xml_node child = node.first_child(); child; child = child.next_sibling())
                        read_xml_node(child, tmp, flags);
                }
                break;
            case pugi::node_pcdata:
                {
                    if (flags & no_concat_text)
                        pt.push_back(std::make_pair(xmltext<Ch>(), Ptree( node.value() )));
                    else
                        pt.data() += node.value();
                }
                break;
            case pugi::node_comment:
                {
                    if (!(flags & no_comments))
                        pt.push_back(std::make_pair(xmlcomment<Ch>(), Ptree( node.value() )));
                }
                break;
            default:
                // skip other types
                break;
        }
    }
Example #4
0
    void write_info_helper(std::basic_ostream<typename Ptree::char_type> &stream, 
                           const Ptree &pt, 
                           int indent)
    {

        // Character type
        typedef typename Ptree::char_type Ch;
        
        // Write data
        if (indent >= 0)
        {
            if (!pt.data().empty())
            {
                std::basic_string<Ch> data = create_escapes(pt.template get_own<std::basic_string<Ch> >());
                if (is_simple_data(data))
                    stream << Ch(' ') << data << Ch('\n');
                else
                    stream << Ch(' ') << Ch('\"') << data << Ch('\"') << Ch('\n');
            }
            else if (pt.empty())
                stream << Ch(' ') << Ch('\"') << Ch('\"') << Ch('\n');
            else
                stream << Ch('\n');
        }
        
        // Write keys
        if (!pt.empty())
        {
            
            // Open brace
            if (indent >= 0) 
                stream << std::basic_string<Ch>(4 * indent, Ch(' ')) << Ch('{') << Ch('\n');
            
            // Write keys
            typename Ptree::const_iterator it = pt.begin();
            for (; it != pt.end(); ++it)
            {

                // Output key
                std::basic_string<Ch> key = create_escapes(it->first);
                stream << std::basic_string<Ch>(4 * (indent + 1), Ch(' '));
                if (is_simple_key(key))
                    stream << key;
                else
                    stream << Ch('\"') << key << Ch('\"');

                // Output data and children  
                write_info_helper(stream, it->second, indent + 1);

            }
            
            // Close brace
            if (indent >= 0) 
                stream << std::basic_string<Ch>(4 * indent, Ch(' ')) << Ch('}') << Ch('\n');

        }
    }
Example #5
0
typename Ptree::size_type total_keys_size(const Ptree &pt)
{
    typename Ptree::size_type size = 0;
    for (typename Ptree::const_iterator it = pt.begin(); it != pt.end(); ++it)
    {
        size += it->first.size();
        size += total_keys_size(it->second);
    }
    return size;
}
    void write_json_helper(std::basic_ostream<typename Ptree::key_type::value_type> &stream, 
                           const Ptree &pt,
                           int indent, bool pretty)
    {

        typedef typename Ptree::key_type::value_type Ch;
        typedef typename std::basic_string<Ch> Str;

        // Value or object or array
        if (indent > 0 && pt.empty())
        {
            // Write value
            Str data = create_escapes(pt.template get_value<Str>());
            stream << Ch('"') << data << Ch('"');

        }
        else if (indent > 0 && pt.count(Str()) == pt.size())
        {
            // Write array
            stream << Ch('[');
            if (pretty) stream << Ch('\n');
            typename Ptree::const_iterator it = pt.begin();
            for (; it != pt.end(); ++it)
            {
                if (pretty) stream << Str(4 * (indent + 1), Ch(' '));
                write_json_helper(stream, it->second, indent + 1, pretty);
                if (lslboost::next(it) != pt.end())
                    stream << Ch(',');
                if (pretty) stream << Ch('\n');
            }
            stream << Str(4 * indent, Ch(' ')) << Ch(']');

        }
        else
        {
            // Write object
            stream << Ch('{');
            if (pretty) stream << Ch('\n');
            typename Ptree::const_iterator it = pt.begin();
            for (; it != pt.end(); ++it)
            {
                if (pretty) stream << Str(4 * (indent + 1), Ch(' '));
                stream << Ch('"') << create_escapes(it->first) << Ch('"') << Ch(':');
                if (pretty) {
                    if (it->second.empty())
                        stream << Ch(' ');
                    else
                        stream << Ch('\n') << Str(4 * (indent + 1), Ch(' '));
                }
                write_json_helper(stream, it->second, indent + 1, pretty);
                if (lslboost::next(it) != pt.end())
                    stream << Ch(',');
                if (pretty) stream << Ch('\n');
            }
            if (pretty) stream << Str(4 * indent, Ch(' '));
            stream << Ch('}');
        }

    }
Example #7
0
 void operator()(Ch) const
 {
     if (c.stack.empty())
         c.stack.push_back(&c.root);
     else
     {
         Ptree *parent = c.stack.back();
         Ptree *child = &parent->push_back(std::make_pair(c.name, Ptree()))->second;
         c.stack.push_back(child);
         c.name.clear();
     }
 }
Example #8
0
 void check_dupes(const Ptree &pt)
 {
     if(pt.size() <= 1)
         return;
     const typename Ptree::key_type *lastkey = 0;
     typename Ptree::const_assoc_iterator it = pt.ordered_begin(),
                                          end = pt.not_found();
     lastkey = &it->first;
     for(++it; it != end; ++it) {
         if(*lastkey == it->first)
             BOOST_PROPERTY_TREE_THROW(ini_parser_error(
                 "duplicate key", "", 0));
         lastkey = &it->first;
     }
 }
Example #9
0
    void write_ini(std::basic_ostream<
                       typename Ptree::key_type::value_type
                   > &stream,
                   const Ptree &pt,
                   int flags = 0)
    {
        using detail::check_dupes;

        typedef typename Ptree::key_type::value_type Ch;
        typedef std::basic_string<Ch> Str;

        BOOST_ASSERT(validate_flags(flags));
        (void)flags;

        if (!pt.data().empty())
            BOOST_PROPERTY_TREE_THROW(ini_parser_error(
                "ptree has data on root", "", 0));
        check_dupes(pt);

        for (typename Ptree::const_iterator it = pt.begin(), end = pt.end();
             it != end; ++it)
        {
            check_dupes(it->second);
            if (it->second.empty()) {
                stream << it->first << Ch('=')
                    << it->second.template get_value<
                        std::basic_string<Ch> >()
                    << Ch('\n');
            } else {
                if (!it->second.data().empty())
                    BOOST_PROPERTY_TREE_THROW(ini_parser_error(
                        "mixed data and children", "", 0));
                stream << Ch('[') << it->first << Ch(']') << Ch('\n');
                for (typename Ptree::const_iterator it2 = it->second.begin(),
                         end2 = it->second.end(); it2 != end2; ++it2)
                {
                    if (!it2->second.empty())
                        BOOST_PROPERTY_TREE_THROW(ini_parser_error(
                            "ptree is too deep", "", 0));
                    stream << it2->first << Ch('=')
                        << it2->second.template get_value<
                            std::basic_string<Ch> >()
                        << Ch('\n');
                }
            }
        }

    }
    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;

        // Create and load document from stream
        stream.unsetf(std::ios::skipws);

        if (!stream.good())
            throw xml_parser_error("read error", filename, 0);

        std::vector<Ch> buf;
        std::copy(std::istream_iterator<Ch>(stream), std::istream_iterator<Ch>(), std::back_inserter(buf));
        buf.push_back(0); // zero-terminate  

        unsigned int pugi_flags = pugi::parse_w3c;
        if ( flags & no_comments )
            pugi_flags = pugi_flags & ~pugi::parse_comments;

        pugi::xml_parser parser(&buf[0], pugi_flags);
        pugi::xml_node doc = parser.document();

        // Create ptree from nodes
        Ptree local;
        for ( pugi::xml_node child = doc.first_child(); child; child = child.next_sibling())
            read_xml_node( child, local, flags );

        // Swap local and result ptrees
        pt.swap(local);
    }
      TypeEnumere* TypeEnumere::Construire(Opencxx::TypeInfo& informationType,
                                           Opencxx::Environment* environement)
      {

        
        if (informationType.WhatIs() == EnumType)
        {
          Ptree* spec ;
          informationType.IsEnum(spec) ;
          
          return new TypeEnumere(spec->Cdr()->Cdr()->Car()->Cdr()->Car()) ;
          
          
        }
        else
          
          return NULL ;
          
      }
    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::pdalboostrapidxml;

        // 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));  
        }
    }
 void read_info(const std::string &filename, Ptree &pt,
                const std::locale &loc = std::locale())
 {
     std::basic_ifstream<typename Ptree::key_type::value_type>
         stream(filename.c_str());
     if (!stream) {
         BOOST_PROPERTY_TREE_THROW(info_parser_error(
             "cannot open file for reading", filename, 0));
     }
     stream.imbue(loc);
     Ptree local;
     read_info_internal(stream, local, filename, 0);
     pt.swap(local);
 }
Example #14
0
    void read_cmdline(int argc, 
                      typename Ptree::char_type *argv[], 
                      const std::basic_string<typename Ptree::char_type> &metachars,
                      Ptree &pt)
    {

        typedef typename Ptree::char_type Ch;
        typedef std::basic_string<Ch> Str;

        Ptree local;
        
        // For all arguments
        for (int i = 0; i < argc; ++i)
        {
            Str text = detail::trim<Ch>(argv[i]);
            if (!text.empty())
                if (metachars.find(text[0]) != Str::npos)
                {
                    if (text.size() == 1)
                    {
                        Ptree &child = local.put(text, Str());
                        Str key; 
                        if (child.size() < 10) 
                            key.push_back(typename Ptree::char_type('0' + child.size()));
                        child.push_back(std::make_pair(key, Ptree(child.data())));
                    }
                    else if (text.size() == 2)
                    {
                        Ptree &child = local.put(text.substr(1, 1), Str());
                        Str key; 
                        if (child.size() < 10) 
                            key.push_back(typename Ptree::char_type('0' + child.size()));
                        child.push_back(std::make_pair(key, Ptree(child.data())));
                    }
                    else
                    {
                        Ptree &child = local.put(text.substr(1, 1), detail::trim<Ch>(text.substr(2, Str::npos)));
                        Str key; 
                        if (child.size() < 10) 
                            key.push_back(typename Ptree::char_type('0' + child.size()));
                        child.push_back(std::make_pair(key, Ptree(child.data())));
                    }
                }
                else
                {
                    Ptree &child = local.put(Str(), detail::trim<Ch>(text));
                    Str key; 
                    if (child.size() < 10) 
                        key.push_back(typename Ptree::char_type('0' + child.size()));
                    child.push_back(std::make_pair(key, Ptree(child.data())));
                }
        }

        // Swap local and pt
        pt.swap(local);

    }
Example #15
0
    bool verify_json(const Ptree &pt, int depth)
    {

        typedef typename Ptree::char_type Ch;
        typedef typename std::basic_string<Ch> Str;

        // Root ptree cannot have data
        if (depth == 0 && !pt.template get_own<Str>().empty())
            return false;
        
        // Ptree cannot have both children and data
        if (!pt.template get_own<Str>().empty() && !pt.empty())
            return false;

        // Check children
        typename Ptree::const_iterator it = pt.begin();
        for (; it != pt.end(); ++it)
            if (!verify_json(it->second, depth + 1))
                return false;

        // Success
        return true;

    }
Example #16
0
Ptree get_test_ptree()
{
    using namespace boost::property_tree;
    typedef typename Ptree::key_type::value_type Ch;
    Ptree pt;
    pt.put_value(detail::widen<Ch>("data0"));
    pt.put(detail::widen<Ch>("key1"), detail::widen<Ch>("data1"));
    pt.put(detail::widen<Ch>("key1.key"), detail::widen<Ch>("data2"));
    pt.put(detail::widen<Ch>("key2"), detail::widen<Ch>("data3"));
    pt.put(detail::widen<Ch>("key2.key"), detail::widen<Ch>("data4"));
    return pt;
}
Example #17
0
File: read.hpp Project: DINKIN/omim
    void read_json_internal(
        std::basic_istream<typename Ptree::key_type::value_type> &stream,
        Ptree &pt, const std::string &filename)
    {
        typedef typename Ptree::key_type::value_type char_type;
        typedef standard_callbacks<Ptree> callbacks_type;
        typedef detail::encoding<char_type> encoding_type;
        typedef std::istreambuf_iterator<char_type> iterator;
        callbacks_type callbacks;
        encoding_type encoding;
        detail::parser<callbacks_type, encoding_type, iterator, iterator>
            parser(callbacks, encoding);
        parser.set_input(filename,
            boost::make_iterator_range(iterator(stream), iterator()));
        parser.parse_value();
        parser.finish();

        pt.swap(callbacks.output());
    }
Example #18
0
 void read_info(typename Ptree::BOOST_NESTED_TEMPLATE for_char<Ch>::basic_istream &stream, Ptree &pt)
 {
     Ptree local;
     read_info_internal(stream, local, typename Ptree::string_type(), 0);
     pt.swap(local);
 }
    void write_xml_element(std::basic_ostream<typename Ptree::char_type> &stream, 
                           const std::basic_string<typename Ptree::char_type> &key,
                           const Ptree &pt, 
                           int indent)
    {

        typedef typename Ptree::char_type Ch;
        typedef typename std::basic_string<Ch> Str;
        typedef typename Ptree::const_iterator It;

        // Find if elements present
        bool has_elements = false;
        for (It it = pt.begin(), end = pt.end(); it != end; ++it)
            if (it->first != xmlattr<Ch>() &&
                it->first != xmltext<Ch>())
            {
                has_elements = true;
                break;
            }
        
        // Write element
        if (pt.data().empty() && pt.empty())    // Empty key
        {
            if (indent >= 0)
                stream << Str(4 * indent, Ch(' ')) << Ch('<') << key << 
                          Ch('/') << Ch('>') << std::endl;
        }
        else    // Nonempty key
        {
        
            // Write opening tag, attributes and data
            if (indent >= 0)
            {
            
                // Write opening brace and key
                stream << Str(4 * indent, Ch(' '));
                stream << Ch('<') << key;

                // Write attributes
                if (optional<const Ptree &> attribs = pt.get_child_optional(xmlattr<Ch>()))
                    for (It it = attribs.get().begin(); it != attribs.get().end(); ++it)
                        stream << Ch(' ') << it->first << Ch('=') << 
                                  Ch('"') << it->second.template get_own<std::basic_string<Ch> >() << Ch('"');

                // Write closing brace
                stream << Ch('>');

                // Break line if needed
                if (has_elements)
                    stream << Ch('\n');

            }
            
            // Write data text, if present
            if (!pt.data().empty())
                write_xml_text(stream, pt.template get_own<std::basic_string<Ch> >(), indent + 1, has_elements);
            
            // Write elements, comments and texts
            for (It it = pt.begin(); it != pt.end(); ++it)
            {
                if (it->first == xmlattr<Ch>())
                    continue;
                else if (it->first == xmlcomment<Ch>())
                    write_xml_comment(stream, it->second.template get_own<std::basic_string<Ch> >(), indent + 1);
                else if (it->first == xmltext<Ch>())
                    write_xml_text(stream, it->second.template get_own<std::basic_string<Ch> >(), indent + 1, has_elements);
                else
                    write_xml_element(stream, it->first, it->second, indent + 1);
            }
            
            // Write closing tag
            if (indent >= 0)
            {
                if (has_elements)
                    stream << Str(4 * indent, Ch(' '));
                stream << Ch('<') << Ch('/') << key << Ch('>') << std::endl;
            }

        }
    }
Example #20
0
    void read_ini(std::basic_istream<
                    typename Ptree::key_type::value_type> &stream,
                  Ptree &pt)
    {
        typedef typename Ptree::key_type::value_type Ch;
        typedef std::basic_string<Ch> Str;
        const Ch semicolon = stream.widen(';');
        const Ch hash = stream.widen('#');
        const Ch lbracket = stream.widen('[');
        const Ch rbracket = stream.widen(']');

        Ptree local;
        unsigned long line_no = 0;
        Ptree *section = 0;
        Str line;

        // For all lines
        while (stream.good())
        {

            // Get line from stream
            ++line_no;
            std::getline(stream, line);
            if (!stream.good() && !stream.eof())
                BOOST_PROPERTY_TREE_THROW(ini_parser_error(
                    "read error", "", line_no));

            // If line is non-empty
            line = property_tree::detail::trim(line, stream.getloc());
            if (!line.empty())
            {
                // Comment, section or key?
                if (line[0] == semicolon || line[0] == hash)
                {
                    // Ignore comments
                }
                else if (line[0] == lbracket)
                {
                    // If the previous section was empty, drop it again.
                    if (section && section->empty())
                        local.pop_back();
                    typename Str::size_type end = line.find(rbracket);
                    if (end == Str::npos)
                        BOOST_PROPERTY_TREE_THROW(ini_parser_error(
                            "unmatched '['", "", line_no));
                    Str key = property_tree::detail::trim(
                        line.substr(1, end - 1), stream.getloc());
                    if (local.find(key) != local.not_found())
                        BOOST_PROPERTY_TREE_THROW(ini_parser_error(
                            "duplicate section name", "", line_no));
                    section = &local.push_back(
                        std::make_pair(key, Ptree()))->second;
                }
                else
                {
                    Ptree &container = section ? *section : local;
                    typename Str::size_type eqpos = line.find(Ch('='));
                    if (eqpos == Str::npos)
                        BOOST_PROPERTY_TREE_THROW(ini_parser_error(
                            "'=' character not found in line", "", line_no));
                    if (eqpos == 0)
                        BOOST_PROPERTY_TREE_THROW(ini_parser_error(
                            "key expected", "", line_no));
                    Str key = property_tree::detail::trim(
                        line.substr(0, eqpos), stream.getloc());
                    Str data = property_tree::detail::trim(
                        line.substr(eqpos + 1, Str::npos), stream.getloc());
                    if (container.find(key) != container.not_found())
                        BOOST_PROPERTY_TREE_THROW(ini_parser_error(
                            "duplicate key name", "", line_no));
                    container.push_back(std::make_pair(key, Ptree(data)));
                }
            }
        }
        // If the last section was empty, drop it again.
        if (section && section->empty())
            local.pop_back();

        // Swap local ptree with result ptree
        pt.swap(local);

    }
 void read_info(std::basic_istream<Ch> &stream, Ptree &pt)
 {
     Ptree local;
     read_info_internal(stream, local, std::string(), 0);
     pt.swap(local);
 }
    void write_xml_element(std::basic_ostream<typename Ptree::key_type::value_type> &stream, 
                           const std::basic_string<typename Ptree::key_type::value_type> &key,
                           const Ptree &pt, 
                           int indent,
                           const xml_writer_settings<typename Ptree::key_type::value_type> & settings)
    {

        typedef typename Ptree::key_type::value_type Ch;
        typedef typename Ptree::const_iterator It;

        bool want_pretty = settings.indent_count > 0;
        // Find if elements present
        bool has_elements = false;
        bool has_attrs_only = pt.data().empty();
        for (It it = pt.begin(), end = pt.end(); it != end; ++it)
        {
            if (it->first != xmlattr<Ch>() )
            {
                has_attrs_only = false;
                if (it->first != xmltext<Ch>())
                {
                    has_elements = true;
                    break;
                }
            }
        }
        
        // Write element
        if (pt.data().empty() && pt.empty())    // Empty key
        {
            if (indent >= 0)
            {
                write_xml_indent(stream,indent,settings);
                stream << Ch('<') << key << 
                          Ch('/') << Ch('>');
                if (want_pretty)
                    stream << Ch('\n');
            }
        }
        else    // Nonempty key
        {
        
            // Write opening tag, attributes and data
            if (indent >= 0)
            {
            
                // Write opening brace and key
                write_xml_indent(stream,indent,settings);
                stream << Ch('<') << key;

                // Write attributes
                if (optional<const Ptree &> attribs = pt.get_child_optional(xmlattr<Ch>()))
                    for (It it = attribs.get().begin(); it != attribs.get().end(); ++it)
                        stream << Ch(' ') << it->first << Ch('=')
                               << Ch('"')
                               << encode_char_entities(
                                    it->second.template get_value<std::basic_string<Ch> >())
                               << Ch('"');

                if ( has_attrs_only )
                {
                    // Write closing brace
                    stream << Ch('/') << Ch('>');
                    if (want_pretty)
                        stream << Ch('\n');
                }
                else
                {
                    // Write closing brace
                    stream << Ch('>');

                    // Break line if needed and if we want pretty-printing
                    if (has_elements && want_pretty)
                        stream << Ch('\n');
                }
            }

            // Write data text, if present
            if (!pt.data().empty())
                write_xml_text(stream,
                    pt.template get_value<std::basic_string<Ch> >(),
                    indent + 1, has_elements && want_pretty, settings);

            // Write elements, comments and texts
            for (It it = pt.begin(); it != pt.end(); ++it)
            {
                if (it->first == xmlattr<Ch>())
                    continue;
                else if (it->first == xmlcomment<Ch>())
                    write_xml_comment(stream,
                        it->second.template get_value<std::basic_string<Ch> >(),
                        indent + 1, want_pretty, settings);
                else if (it->first == xmltext<Ch>())
                    write_xml_text(stream,
                        it->second.template get_value<std::basic_string<Ch> >(),
                        indent + 1, has_elements && want_pretty, settings);
                else
                    write_xml_element(stream, it->first, it->second,
                        indent + 1, settings);
            }
            
            // Write closing tag
            if (indent >= 0 && !has_attrs_only)
            {
                if (has_elements)
                    write_xml_indent(stream,indent,settings);
                stream << Ch('<') << Ch('/') << key << Ch('>');
                if (want_pretty)
                    stream << Ch('\n');
            }

        }
    }