【问题标题】:boost::property_tree XML pretty printingboost::property_tree XML 漂亮打印
【发布时间】:2023-03-07 12:51:01
【问题描述】:

我正在使用 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;
}

file.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>

除了手动通过输出和删除空行之外,有没有更好的输出方法?

【问题讨论】:

  • boost::property_tree 使用名为 RapidXML 的 XML 解析器 rapidxml.sourceforge.net。 boost::property_tree 和 RapidXML 都由 Marcin Kalicinski 维护。建议你直接联系他。您可以在 RapidXML 主页上找到他的邮件地址。
  • 感谢 ildjarn 的编辑,但这里的空行是有原因的!顺便问一下维护者的问题,如果有我会发布答案

标签: c++ boost boost-propertytree


【解决方案1】:

解决方案是将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) 非常友好地回答并指出了它。

【讨论】:

  • 警告:trim_whitespace 不仅会修剪 XML 中的空白,还会修剪任何不包含其他元素的元素中的空白:&lt;a&gt;xx &lt;/a&gt; 会被视为&lt;a&gt;xx&lt;/a&gt;
  • 奇怪的是,需要更改 read 设置才能获得此设置(特别是在@AndreasHaferburg 评论之后)。无论如何,在当前版本的 Boost 中,需要使用 xml_writer_settings&lt;std::string&gt;(而不是 char)。
  • 阅读时使用trim_whitespace 有一个问题:它不仅仅修剪前导和尾随空格;它还将多个空间折叠成一个空间。例如&lt;a&gt;BEGINxxxxEND&lt;/a&gt;(其中x 是一个空格字符)被折叠成BEGINxEND。这是因为在内部 trim_whitespace 在 xml_parser_read_rapidxml.hpp 中扩展为 parse_normalize_whitespace | parse_trim_whitespace。我们最终不得不破解 boost 来添加一个禁用规范化的新标志,否则它会破坏我们应用程序中数据的往返。
  • 这几乎对我有用。我使用不同的“设置”来使其工作。 const xml_writer_settings&lt; typename Ptree::key_type &gt; settings('\t', 1);.
【解决方案2】:

这个问题已经很老了,但我最近再次调查了你的问题,因为现在 property_tree 将换行符转换为更糟

&#10;    

在我看来这是一个错误,因为只包含空格的元素 - 换行符、空格和制表符被视为文本元素。 trim_whitespace 只是一个创可贴,对 property_tree 中的所有空白进行规范化。

我在这里报告了这个错误,并附上了一个 .diff 来修复 Boost 1.59 中的这种行为,以防不使用 trim_whitespace: https://svn.boost.org/trac/boost/ticket/11600

【讨论】:

    【解决方案3】:

    对于那些尝试:

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-06
      • 2020-04-28
      • 1970-01-01
      • 2017-12-19
      相关资源
      最近更新 更多