c++ boost::property_tree XML漂亮打印

tyg4sfes  于 2023-01-06  发布在  其他
关注(0)|答案(4)|浏览(120)

我使用boost::property_tree在我的应用程序中读写XML配置文件。但是当我编写文件时,输出看起来有点难看,文件中有很多空行。问题是它也应该由人类编辑,所以我希望得到更好的输出。
作为一个例子,我写了一个小测试程序:

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

int main( void )
{
    using boost::property_tree::ptree;
    ptree pt;

    // reading file.xml
    read_xml("file.xml", pt);

    // writing the unchanged ptree in file2.xml
    boost::property_tree::xml_writer_settings<char> settings('\t', 1);
    write_xml("file2.xml", pt, std::locale(), settings);

    return 0;
}

文件. xml包含:

<?xml version="1.0" ?>
<config>
    <net>
        <listenPort>10420</listenPort>
    </net>
</config>

运行程序后,file2.xml包含:

<?xml version="1.0" encoding="utf-8"?>
<config>


    <net>


        <listenPort>10420</listenPort>
    </net>
</config>

除了手动检查输出并删除空行之外,是否有其他方法可以获得更好的输出?

pdkcd3nj

pdkcd3nj1#

解决方案是将trim_whitespace标志添加到对read_xml的调用中:

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>

int main( void )
{
    // Create an empty property tree object
    using boost::property_tree::ptree;
    ptree pt;

    // reading file.xml
    read_xml("file.xml", pt, boost::property_tree::xml_parser::trim_whitespace );

    // writing the unchanged ptree in file2.xml
    boost::property_tree::xml_writer_settings<char> settings('\t', 1);
    write_xml("file2.xml", pt, std::locale(), settings);

    return 0;
}

这个标志被记录在here中,但是库的当前维护者(Sebastien Redl)非常友好地回答了我并指出了它。

olqngx59

olqngx592#

这个问题已经很老了,但是最近我再次研究了您的问题,因为现在property_tree将换行符转换为

&#10;

在我看来这是一个bug,因为只包含空格的元素--换行符、空格和制表符,被视为文本元素。trim_whitespace只是一个创可贴,它规范化了property_tree中的所有空格。
我在这里报告了这个bug,并附加了一个.diff来修复Boost 1.59中未使用trim_whitespace时的这种行为:https://svn.boost.org/trac/boost/ticket/11600

5lhxktic

5lhxktic3#

对于那些尝试:

boost::property_tree::xml_writer_settings<char> settings('\t', 1);

在VisualStudio 2013中使用boost-1.60.0编译,您可能会获得:

vmtknetworktest.cpp(259) : see reference to class template instantiation 'boost::property_tree::xml_parser::xml_writer_settings<char>' being compiled
install\include\boost-1_60\boost/property_tree/detail/xml_parser_writer_settings.hpp(38): error C2039: 'value_type' : is not a member of '`global namespace''
install\include\boost-1_60\boost/property_tree/detail/xml_parser_writer_settings.hpp(38): error C2146: syntax error : missing ';' before identifier 'Ch'
install\include\boost-1_60\boost/property_tree/detail/xml_parser_writer_settings.hpp(38): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
install\include\boost-1_60\boost/property_tree/detail/xml_parser_writer_settings.hpp(40): error C2061: syntax error : identifier 'Ch'
install\include\boost-1_60\boost/property_tree/detail/xml_parser_writer_settings.hpp(49): error C2146: syntax error : missing ';' before identifier 'indent_char'
install\include\boost-1_60\boost/property_tree/detail/xml_parser_writer_settings.hpp(49): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
install\include\boost-1_60\boost/property_tree/detail/xml_parser_writer_settings.hpp(50): error C2825: 'Str': must be a class or namespace when followed by '::'
install\include\boost-1_60\boost/property_tree/detail/xml_parser_writer_settings.hpp(50): error C2039: 'size_type' : is not a member of '`global namespace''
install\include\boost-1_60\boost/property_tree/detail/xml_parser_writer_settings.hpp(50): error C2146: syntax error : missing ';' before identifier 'indent_count'
install\include\boost-1_60\boost/property_tree/detail/xml_parser_writer_settings.hpp(50): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
vmtknetworktest.cpp(259): error C2661: 'boost::property_tree::xml_parser::xml_writer_settings<char>::xml_writer_settings' : no overloaded function takes 3 arguments

然后在这里结束:
https://svn.boost.org/trac/boost/ticket/10272
解决方案是在模板中使用std::string。

pt::write_xml(file_name, params, std::locale(), pt::xml_writer_make_settings< std::string >(' ', 4));

如下所述:
https://stackoverflow.com/a/35043551/7170333

vql8enpb

vql8enpb4#

设置为"trim_whitespace"不是正确答案。如果您不能修剪数据项(在读取时发生),则在读取时修剪空白没有任何用处。
我觉得问题出在这里,在:https://www.boost.org/doc/libs/1_81_0/boost/property_tree/detail/xml_parser_write.hpp
而不是:

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

也许可以这样说:

// Write data text, if not empty/white-space only
            auto d = pt.data();
            bool is_empty = d.erase(d.find_last_not_of(" \n\r\t")+1).empty();
            if (!is_empty)
                write_xml_text(stream,
                    pt.template get_value<Str>(),
                    indent + 1, has_elements && want_pretty, settings);

这似乎修复了IMO上面看到的"奇怪"行为--作者没有添加空行或"仅空格"行。
或者,读取器在读取节点时可以跳过此空"文本",例如:

// Parse contents of the node - children, data etc.
        template<int Flags>
        void parse_node_contents(Ch *&text, xml_node<Ch> *node)
        {
            // For all children and text
            while (1)
            {
                // Skip whitespace between > and node contents
                Ch *contents_start = text;      // Store start of node contents before whitespace is skipped
                // ****--***-> here - unconditonally (always) skip the WS
                // if (Flags & parse_trim_whitespace)
                    skip<whitespace_pred, Flags>(text);
                Ch next_char = *text;

相关问题