【问题标题】:How to use Boost XML Parser如何使用 Boost XML 解析器
【发布时间】:2017-12-28 11:59:03
【问题描述】:

我编写了一个 XML 解析器,用于读取 XML 文件并将其转换为我的“Position”类的对象。它工作正常。请看下面的代码。

XML 文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="15">
<position class_id="0" tracking_level="0" version="0">
    <Degrees>1</Degrees>
    <Minutes>2</Minutes>
    <Seconds>3</Seconds>
    <data class_id="1" tracking_level="0" version="0">
        <Degrees>1</Degrees>
        <Minutes>2</Minutes>
        <Seconds>3</Seconds>
    </data>
</position>
</boost_serialization>

职位类别:

#ifndef XMLMANAGER_POSITION_H
#define XMLMANAGER_POSITION_H

#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>

class Data
{
public:
    int Degrees;
    int Minutes;
    float Seconds;
private:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int version){
        ar & BOOST_SERIALIZATION_NVP(Degrees);
        ar & BOOST_SERIALIZATION_NVP(Minutes);
        ar & BOOST_SERIALIZATION_NVP(Seconds);
    }
};
class Position
{

public:
    // every serializable class needs a constructor
    Position() {
        Degrees = 0;
        Minutes = 0;
        Seconds = 0;
    };
    Position(int degrees, int minutes, float seconds){
        Degrees = degrees;
        Minutes = minutes;
        Seconds = seconds;
    };
    int Degrees;
    int Minutes;
    float Seconds;
    Data data;

private:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int version){
        ar & BOOST_SERIALIZATION_NVP(Degrees);
        ar & BOOST_SERIALIZATION_NVP(Minutes);
        ar & BOOST_SERIALIZATION_NVP(Seconds);
        ar & BOOST_SERIALIZATION_NVP(data);
    }
};

#endif //XMLMANAGER_POSITION_H

主要功能:

    // Load an Object from XML
    std::ifstream ifs("/tests/r.karimi/XmlManager/data/Output.xml");
    boost::archive::xml_iarchive ixa(ifs);
    Position newPosition;
    try
    {
        ixa >> BOOST_SERIALIZATION_NVP(newPosition);
    }
    catch (std::exception const &ex)
    {
        std::cerr << ex.what() << std::endl;
    }
    std::cout << "Degree " << newPosition.Degrees <<
              " Minutes " << newPosition.Minutes <<
              " Seconds " << newPosition.Seconds << std::endl;
    std::cout << "Degree " << newPosition.data.Degrees <<
              " Minutes " << newPosition.data.Minutes <<
              " Seconds " << newPosition.data.Seconds << std::endl;

现在,我想解析以下 XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="15">
<position class_id="0" tracking_level="0" version="0">
    <Degrees>0</Degrees>
    <Minutes>0</Minutes>
    <Seconds>0.000000000e+00</Seconds>
    <data class_id="1" tracking_level="0" version="0">
        <Degrees>1</Degrees>
        <Minutes>2</Minutes>
        <Seconds>3</Seconds>
    </data>
    <data class_id="1" tracking_level="0" version="0">
        <Degrees>4</Degrees>
        <Minutes>5</Minutes>
        <Seconds>6</Seconds>
    </data>
</position>
</boost_serialization>

我该怎么办?我尝试了不同的解决方案,例如在“位置”类中获取“数据”类的数组,但它不起作用。我更喜欢在我的项目中使用 Boost 库。 (除非不可能!!!)

【问题讨论】:

  • 问。 “如何使用 Boost XML 解析器?” A.“首先,你写一个;然后,你提出它;然后它被接受;然后你使用它”

标签: c++ xml boost


【解决方案1】:

Boost没有有 XML 库。

Boost 序列化不读取一般的 XML(类似)文档。它读取 XML 档案。也就是说,您无法控制 XML。

总而言之,您可以简单地使用另一个 Data 成员扩展该类,并且它会意外地导致非常相似的 XML 存档。也许这对你来说已经足够了:

Live On Coliru

#include <boost/archive/xml_oarchive.hpp>

class Data
{
public:
    int Degrees;
    int Minutes;
    float Seconds;
private:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int /*version*/){
        ar & BOOST_SERIALIZATION_NVP(Degrees);
        ar & BOOST_SERIALIZATION_NVP(Minutes);
        ar & BOOST_SERIALIZATION_NVP(Seconds);
    }
};

class Position
{

public:
    // every serializable class needs a constructor
    Position() {
        Degrees = 0;
        Minutes = 0;
        Seconds = 0;
    };
    Position(int degrees, int minutes, float seconds){
        Degrees = degrees;
        Minutes = minutes;
        Seconds = seconds;
    };
    int Degrees;
    int Minutes;
    float Seconds;
    Data data;
    Data data2;

private:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int /*version*/){
        ar & BOOST_SERIALIZATION_NVP(Degrees);
        ar & BOOST_SERIALIZATION_NVP(Minutes);
        ar & BOOST_SERIALIZATION_NVP(Seconds);
        ar & boost::serialization::make_nvp("data", data);
        ar & boost::serialization::make_nvp("data", data2);
    }
};

#include <fstream>

int main() {
    Position position;
    position.Degrees = 1;
    position.Minutes = 2;
    position.Seconds = 3;
    position.data = {1,2,3};
    position.data2 = {4,5,6};

    {
        std::ofstream ofs("output.xml");
        boost::archive::xml_oarchive oa(ofs);

        oa << BOOST_SERIALIZATION_NVP(position);
    }
}

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="14">
<position class_id="0" tracking_level="0" version="0">
    <Degrees>1</Degrees>
    <Minutes>2</Minutes>
    <Seconds>3.000000000e+00</Seconds>
    <data class_id="1" tracking_level="0" version="0">
        <Degrees>1</Degrees>
        <Minutes>2</Minutes>
        <Seconds>3.000000000e+00</Seconds>
    </data>
    <data>
        <Degrees>4</Degrees>
        <Minutes>5</Minutes>
        <Seconds>6.000000000e+00</Seconds>
    </data>
</position>
</boost_serialization>

更新

如果您不想控制 XML,那就更好了。让图书馆做你想做的事:

Live On Coliru

#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/serialization/vector.hpp>

class Data
{
public:
    int Degrees;
    int Minutes;
    float Seconds;
private:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int /*version*/){
        ar & BOOST_SERIALIZATION_NVP(Degrees);
        ar & BOOST_SERIALIZATION_NVP(Minutes);
        ar & BOOST_SERIALIZATION_NVP(Seconds);
    }
};

class Position
{

public:
    // every serializable class needs a constructor
    Position() {
        Degrees = 0;
        Minutes = 0;
        Seconds = 0;
    };
    Position(int degrees, int minutes, float seconds){
        Degrees = degrees;
        Minutes = minutes;
        Seconds = seconds;
    };
    int Degrees;
    int Minutes;
    float Seconds;
    std::vector<Data> data;

private:
    friend class boost::serialization::access;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int /*version*/){
        ar & BOOST_SERIALIZATION_NVP(Degrees);
        ar & BOOST_SERIALIZATION_NVP(Minutes);
        ar & BOOST_SERIALIZATION_NVP(Seconds);
        ar & boost::serialization::make_nvp("data", data);
    }
};

#include <fstream>

int main() {
    {
        Position position;
        position.Degrees = 1;
        position.Minutes = 2;
        position.Seconds = 3;
        position.data = { {1,2,3}, {4,5,6 } };

        std::ofstream ofs("output.xml");
        boost::archive::xml_oarchive oa(ofs);

        oa << BOOST_SERIALIZATION_NVP(position);
    }
    {
        std::ifstream ifs("output.xml");
        boost::archive::xml_iarchive ia(ifs);

        Position position;
        ia >> BOOST_SERIALIZATION_NVP(position);
    }
}

在这种情况下,XML 恰好看起来像:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="14">
<position class_id="0" tracking_level="0" version="0">
    <Degrees>1</Degrees>
    <Minutes>2</Minutes>
    <Seconds>3.000000000e+00</Seconds>
    <data class_id="1" tracking_level="0" version="0">
        <count>2</count>
        <item_version>0</item_version>
        <item class_id="2" tracking_level="0" version="0">
            <Degrees>1</Degrees>
            <Minutes>2</Minutes>
            <Seconds>3.000000000e+00</Seconds>
        </item>
        <item>
            <Degrees>4</Degrees>
            <Minutes>5</Minutes>
            <Seconds>6.000000000e+00</Seconds>
        </item>
    </data>
</position>
</boost_serialization>

【讨论】:

  • 感谢您的精彩而全面的回答。但是从 XML 读取对我来说更重要。如何将其加载到我的对象中?
  • 我可以定义两个成员还是一个数组?如果没有,我该怎么办?
  • 呃。也许我错过了什么:coliru.stacked-crooked.com/a/6d612ca1776785ce
  • 如果你想序列化你的类,你应该使用 Boost 序列化。如果要序列化包含数据数组的类,请执行此操作。如果您想序列化包含数据的向量、列表或映射的类,请执行那个。不要考虑 XML,因为这是 Boost Serialization 的工作。这是一个实现细节
  • 我告诉过你我的意思。请参阅paste.ubuntu.com/25154490 (sudo apt-get install libpugixml-dev; g++ -std=c++11 main.cpp -lpugixml -o test)。见output
猜你喜欢
  • 1970-01-01
  • 2012-12-10
  • 2011-06-17
  • 2013-01-31
  • 2016-10-30
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多