获取Tag [Boost Porperty_tree XML]的SubTag详细信息

时间:2015-05-12 07:46:46

标签: c++ xml boost

我正在尝试获取" subchapter"的详细信息。标签。我不知道如何获取标签内的信息。

我的XML看起来像这样:

<xml>
    <chapter>
        <name>First Chapter</name>
        <link>xyz1</link>
        <chapter>
            <name>First Sub-Chapter</name>
            <link>xyz2</link>
        </chapter>
    </chapter>
</xml>

现在我想获得第二章标签的信息...... 我的c ++看起来像这样:

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

BOOST_FOREACH(const boost::property_tree::ptree::value_type& node, pt.get_child("xml"))
{
    if( node.first == "chapter" )
    {
        chapter chp;
        chp.name = node.second.get<std::string>("name");
        chp.link = node.second.get<std::string>("link");

        //boost::property_tree::ptree::value_type test = node.second.get<boost::property_tree::ptree::value_type>("chapter");
        //chapter chp2;
        //chp2.name = test.second.get<std::string>("name");
        //chp2.link = test.second.get<std::string>("link");

        //chp.sub_chapters.push_back( chp2 );

        m_chapters.push_back( chp );
    }
}

我试过就像你可以看到评论的行。我还尝试使用另一个BOOST_FOREACH。有没有办法达到我的目标?

感谢您的帮助! 格尔茨!

1 个答案:

答案 0 :(得分:0)

我使用简单的递归查找算法:

template <typename Tree, typename Out>
Out find_all_chapters(Tree const& pt, Out out) {
    using namespace boost::property_tree;
    BOOST_FOREACH(typename Tree::value_type const& ch, pt) {
        if (ch.first == "chapter") {
            *out++ = chapter { 
                    ch.second.template get<std::string>("name"),
                    ch.second.template get<std::string>("link")
                };

            out = find_all_chapters(ch.second, out);
        }
    }
    return out;
}

这假设嵌套的章节总是出现在其他章节中(否则将递归调用移出if()条件块。)

您可以像

一样使用它
int main() {
    boost::property_tree::ptree pt;
    boost::property_tree::xml_parser::read_xml("file.xml", pt, boost::property_tree::xml_parser::trim_whitespace );

    std::vector<chapter> m_chapters;
    find_all_chapters(pt.get_child("xml"), back_inserter(m_chapters));

    for (auto& ch : m_chapters)
        std::cout << "Chapter '" << ch.name << "', link: '" << ch.link << "'\n";
}

打印

Chapter 'First Chapter', link: 'xyz1'
Chapter 'First Sub-Chapter', link: 'xyz2'

完整列表

<强> Live On Coliru

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

struct chapter {
    std::string name, link;
};

template <typename Tree, typename Out>
Out find_all_chapters(Tree const& pt, Out out) {
    using namespace boost::property_tree;
    BOOST_FOREACH(typename Tree::value_type const& ch, pt) {
        if (ch.first == "chapter") {
            *out++ = chapter { 
                    ch.second.template get<std::string>("name"),
                    ch.second.template get<std::string>("link")
                };

            out = find_all_chapters(ch.second, out);
        }
    }
    return out;
}

int main() {
    boost::property_tree::ptree pt;
    boost::property_tree::xml_parser::read_xml("file.xml", pt, boost::property_tree::xml_parser::trim_whitespace );

    std::vector<chapter> m_chapters;
    find_all_chapters(pt.get_child("xml"), back_inserter(m_chapters));

    for (auto& ch : m_chapters)
        std::cout << "Chapter '" << ch.name << "', link: '" << ch.link << "'\n";
}

更新

对于评论,这是我如何做的:

<强> Live On Coliru

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

struct chapter {
    std::string name, link;
    std::vector<chapter> sub_chapters;
};

void find_all_chapters(boost::property_tree::ptree const& pt, chapter& into) {
    for(auto& ch : pt) {
        if (ch.first == "chapter") {
            into.sub_chapters.push_back({ 
                    ch.second.template get<std::string>("name"),
                    ch.second.template get<std::string>("link"),
                    {}
                });

            find_all_chapters(ch.second, into.sub_chapters.back());
        }
    }
}

void print(chapter const& book_or_chapter, std::string const& indent = "") 
{
    for (auto& ch : book_or_chapter.sub_chapters) {
        std::cout << indent << " - Chapter '" << ch.name << "', link: '" << ch.link << "'\n";
        print(ch, "    " + indent);
    }
}

int main() {
    boost::property_tree::ptree pt;
    boost::property_tree::xml_parser::read_xml(std::cin, pt, boost::property_tree::xml_parser::trim_whitespace );

    chapter book;
    find_all_chapters(pt.get_child("xml"), book);

    print(book);
}

输入xml,如

<xml>
    <chapter>
        <name>First Chapter</name>
        <link>xyz1</link>
        <chapter>
            <name>First Sub-Chapter</name>
            <link>xyz2</link>
            <chapter>
                <name>Sub Sub</name>
                <link>xyz3</link>
                <chapter>
                    <name>Sub Sub Sib</name>
                    <link>xyz4</link>
                </chapter>
            </chapter>
        </chapter>
    </chapter>
    <chapter>
        <name>Second Chapter</name>
        <link>abc1</link>
        <chapter>
            <name>First Sub-Chapter</name>
            <link>abc2</link>
        </chapter>
    </chapter>
</xml>

打印

 - Chapter 'First Chapter', link: 'xyz1'
     - Chapter 'First Sub-Chapter', link: 'xyz2'
         - Chapter 'Sub Sub', link: 'xyz3'
             - Chapter 'Sub Sub Sib', link: 'xyz4'
 - Chapter 'Second Chapter', link: 'abc1'
     - Chapter 'First Sub-Chapter', link: 'abc2'