ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • boost::property_tree를 이용해 xml 데이터 파싱하기
    프로그래밍/c++ 2016. 1. 22. 06:47
    반응형

    서버의 설정 값들을 텍스트 파일로 두고 읽어오는 방식을 사용했으나


    좀 더 체계화된 방식이 있으면 좋겠다고 생각했다. 


    이유는 매번 텍스트 파일의 양식을 정의해야 했으므로, 


    해당 양식에서 데이터를 뽑아낼 수 있는 파서를 직접 만들어 써야 했으며, 


    값 만을 저장하는 경우 사람이 보기에 직관적이지가 않아 수정이 어려웠다.


    근데 우성이형이 그런 것들을 xml로 하면 좋다고 해서 c++에서의 이용 방법들을 알아봤고,


    역시나 boost에도 xml parser가 있었다.


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    #include <boost/property_tree/xml_parser.hpp>
     
    //...
     
    namespace property_tree = boost::property_tree;
     
     
     
    property_tree::ptree reader;
     
    // 읽을 xml 파일을 설정합니다.(xml 파일경로, 엮을 객체)
    property_tree::read_xml("config.xml", reader);
     
    // num_sessions 데이터를 int형으로 읽어 옴
    //
    //<num_sessions>10</num_sessions>
    int num_sessions = reader.get<int>("num_sessions");
     
     
    //
    // endpoint에 있는 port 데이터를 int형으로 읽어 옴
    //
    //<endpoint>
    //  <ip_version>4</ip_version>
    //  <port>6333</port>
    //</endpoint>
    //
    int port = reader.get<int>("endpoint.port"); 
     

    cs


    boost::property_tree를 이용. ptree는 데이터가 저장되는 트리 구조의 객체이다. 


    read_xml을 통해 파일을 열고, 바인딩된 객체의 get 메소드를 이용해 데이터를 뽑아오면 된다. 템플릿을 이용해 어떤 형태로 읽을지 결정도 가능하다.


    1
    2
    3
    4
     
    reader.get<int>("name"// name 속성을 int형으로 읽음
    reader.get<std::string>("name"// port 속성을 std::string형으로 읽음
     

    cs


    하부 노드에 접근을 할 때에는 객체의 멤버에 접근하듯, 점을 찍어가며 접근한다. 


    endpoint 하위, port에 접근


    1
    2
    3
     
    unsigned short port_num = reader.get<unsigned short>("endpoint.port");
     

    cs


    + 2016/01/30


    요런식으로 있는 xml 데이터 뽑기

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <blackbox_pos_samples>
     <pos x="90.173" y="20.000" z="71.250" />
     <pos x="145.540" y="20.000" z="-129.932" />
     <pos x="-270.317" y="20.000" z="-123.173" />
     <pos x="-432.268" y="20.000" z="243.703" />
     <pos x="-331.953" y="20.000" z="-423.415" />
     <pos x="213.099" y="20.00" z="-217.932" />
     <pos x="568.630" y="20.00" z="132.855" />
     <pos x="-439.231" y="20.00" z="345.763" />
     <pos x="-9.866" y="20.00" z="269.300" />
    </blackbox_pos_samples>
    cs


    데이터를 뽑아낼 태그의 자식 목록들을 가져옴


    1
    2
    3
     
      auto blackbox_pos_samples = reader.get_child("blackbox_pos_samples");
     
    cs


    목록을 순회하며 데이터를 뽑아낸다. 속성은 <xmlattr>.[이름]으로 접근.


    태그에서 x 값을 뽑는 건 다음과 같다. <xmlattr>.x


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
      for (auto& pos : blackbox_pos_samples)
      {
          const auto x = pos.second.get<double>("<xmlattr>.x");
          const auto y = pos.second.get<double>("<xmlattr>.y");
          const auto z = pos.second.get<double>("<xmlattr>.z");
     
          gameconfig_.blackbox_pos_samples_.emplace_back(x, y, z);
      }
     
    cs



    완성된 코드


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
      namespace property_tree = boost::property_tree;
      
      property_tree::ptree reader;
      property_tree::xml_parser::read_xml(configfile, reader);
     
      // 검은 상자 위치 샘플 설정
      auto blackbox_pos_samples = reader.get_child("blackbox_pos_samples");
      for (auto& pos : blackbox_pos_samples)
      {
        if (pos.first == "pos")
        {
          const auto x = pos.second.get<double>("<xmlattr>.x");
          const auto y = pos.second.get<double>("<xmlattr>.y");
          const auto z = pos.second.get<double>("<xmlattr>.z");
     
          gameconfig_.blackbox_pos_samples_.emplace_back(x, y, z);
        }
      }
     
    cs


    반응형
Designed by Tistory.