読者です 読者をやめる 読者になる 読者になる

Boost.PropertyTree XMLの読み込みフラグ

C++

reference - boost::property::xml_parser::read_xml

// In header: <boost/property_tree/xml_parser.hpp>


template<typename Ptree> 
  void read_xml(const std::string & filename, Ptree & pt, int flags = 0, 
                const std::locale & loc = std::locale());

Parameters:
  ...

  flags
    Flags controlling the bahviour of the parser. The following flags are supported:

    ・no_concat_text -- Prevents concatenation of text nodes into datastring of property tree. Puts them in separate strings instead.
    ・no_comments -- Skip XML comments.

デフォルトでコメントもパースするのか・・・。
コメントはいらないのでXML読むときはno_comments指定する。

#include <boost/property_tree/xml_parser.hpp>

void read(const std::string& path)
{
    using namespace boost::property_tree;

    ptree pt;
    const int flag = xml_parser::no_comments;
    read_xml(path, pt, flag);

    ...
}

それと、読み込みフラグが定義されている
<boost/property_tree/detail/xml_parser_flag.hpp>
を見たら

namespace boost { namespace property_tree { namespace xml_parser
{
    ...

    /// Whitespace should be collapsed and trimmed.
    static const int trim_whitespace = 0x4;

    ...
} } }

なんていうのもあった。スペース除去。
これはアンドキュメント。


というわけで、trim_whitespaceのテスト。


読み込むXML:test.xml
(123の後ろに2スペース入ってます)

<root>
  <elem attr="  abc  ">
    123  
  </elem>
</root>


コード:

#include <iostream>
#include <string>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/foreach.hpp>
#include <boost/optional.hpp>

using namespace boost::property_tree;

inline boost::optional<const ptree&> find_attr(const ptree& pt)
{
    ptree::const_assoc_iterator p = pt.find("<xmlattr>");
    return p != pt.not_found() ?
        p->second : boost::optional<const ptree&>();
}

inline std::string get_attr(const ptree& pt, const std::string& name)
{
    return pt.find(name)->second.data();
}

int main()
{
    ptree pt;
    const int flag = xml_parser::trim_whitespace;
    read_xml("C:\\test.xml", pt, flag);

    // 要素
    if (boost::optional<std::string> elem = pt.get_optional<std::string>("root.elem"))
        std::cout << "[" << elem.get() << "]" << std::endl;
    else {
        std::cout << "value not found" << std::endl;
        return 0;
    }

    // 属性
    if (boost::optional<const ptree&> attrs = find_attr(pt.get_child("root").begin()->second)) {
        if (boost::optional<std::string> attr = attrs.get().get_optional<std::string>("attr"))
            std::cout << "[" << attr.get() << "]" << std::endl;
        else
            std::cout << "attr attribute not found" << std::endl;
    }
    else {
        std::cout << "attribute not found" << std::endl;
    }
}
[123]
[  abc  ]

要素のみスペース除去されたのが確認できました。