はかせのラボ

私の頭の中を書いていく雑記ブログです

RapidXml ツールの勉強は使ってみるところから始まる

あいさつ

どうも、はかせです。
前回boostのXMLの正体がRapidXmlだと言う話をしました。
ということで今回からはRapidXmlについて勉強していきます。

RapidXmlとは?

前回も軽く触れましたがもう一度
rapidxml.sourceforge.net
ネット上に公開されているXMLパーサーです。

特徴として
・rapidxml.hppを入れるだけで使える
・軽量でかつ爆速である

こんな感じですね。
配布サイトから落としてきたソースコード
プロジェクトに放り込むなりパス通すなりするだけで使えます。

そしてよくあるXMLパーサーらしくDOMなので
Web系のプログラミングになれている人であれば比較的楽に使えるかなと思います。
(私は慣れていないので微妙に使いきれてないですw)

実際に使ってみる

簡単にですがRapidXmlの説明が終わったので早速使ってみます。
読み込むデータは適当にゲームデータっぽいの作ってみました。

<?xml version="1.0" encoding="Shift-Jis" standalone="yes"?>
<TopNode>
  <GameObject>
    <Name>TitleText</Name>
    <Position>
      <x>0.0</x>
      <y>0.3</y>
      <z>0.0</z>
    </Position>
    <Rotation>
      <x>0.0</x>
      <y>0.0</y>
      <z>0.0</z>
    </Rotation>
    <Scale>
      <x>4.0</x>
      <y>4.0</y>
      <z>1.0</z>
    </Scale>
  </GameObject>
  <GameObject>
    <Name>PressEnter</Name>
    <Position>
      <x>-1.1</x>
      <y>-0.5</y>
      <z>0.0</z>
    </Position>
    <Rotation>
      <x>0.0</x>
      <y>0.0</y>
      <z>0.0</z>
    </Rotation>
    <Scale>
      <x>0.1</x>
      <y>0.1</y>
      <z>0.1</z>
    </Scale>
  </GameObject>
  <GameObject>
    <Name>PressEsc</Name>
    <Position>
      <x>-0.9</x>
      <y>-0.7</y>
      <z>0.0</z>
    </Position>
    <Rotation>
      <x>0.0</x>
      <y>0.0</y>
      <z>0.0</z>
    </Rotation>
    <Scale>
      <x>0.1</x>
      <y>0.1</y>
      <z>0.1</z>
    </Scale>
  </GameObject>
</TopNode>

実際に読み込んで表示するプログラムです。
RapidXmlの使い方は極めて簡単で
xml_documentを宣言
・parseメソッドにXMLデータを食わせる

これだけです。

そして読み込んだデータはDOMでノード単位で分かれているので
それをバラシていくわけですね。
今回データのバラシは再起処理で実装しています。

#pragma once
#include <iostream>
#include <rapidxml.hpp>
#include <rapidxml_utils.hpp>

class RapidXmlTest
{
public:
	RapidXmlTest();
	~RapidXmlTest() {};
private:
	void show_xml(rapidxml::xml_node<>* node,int indent = 0);
};
#include "pch.h"
#include "RapidXmlTest.h"

RapidXmlTest::RapidXmlTest()
{
	//Xmlを読み込むDOM
	rapidxml::xml_document<> doc;
	//RapidXmlのユーティリティクラス 読み込んだXmlファイルをオンメモリに保持してくれる
	rapidxml::file<> file("TitleSceneData.xml");
	try 
	{
		//Xmlデータをパースする
		doc.parse<0>(file.data());
	}
	catch (rapidxml::parse_error& err) 
	{
		//エラーが出たら原因と場所(ポインタ)を教えてくれる
		std::cout << err.what() << " " << err.where<char*>();
		return;
	}
	//Xmlファイルのデータを表示
	show_xml(doc.first_node());
}

void RapidXmlTest::show_xml(rapidxml::xml_node<>* node,int indent)
{
	//ノードがなければなにもしない
	if (node == nullptr) return;
	//名前があるか
	if (node->name_size() > 0) 
	{
		//インデント分タブ入れる
		for (int i = 0; i < indent; i++) std::cout << "\t";
		std::cout << "Node:" << node->name() << "\n"; 
	}
	else return;
	//値があるか
	if (node->value_size() > 0)
	{
		//インデントとノード分タブ入れる
		for (int i = 0; i < indent + 1; i++) std::cout << "\t";
		std::cout << "Value:" << node->value() << "\n";
	}
	//子ノードへ
	show_xml(node->first_node(),indent + 1);
	//弟ノードへ
	show_xml(node->next_sibling(),indent);
}

そして実行結果です。
f:id:hakase0274:20190717223732p:plain
何事もなかったかのようにきれいに表示されました。

あとがき

今回はRapidXml使ってみたでした。
使ってみた感じすごく素直に使えるなーって思いました。
特に変な癖とかもなく軽いし速いしもうこれ使えばいいんじゃね?
ってぐらい使いやすかったですw

実際軽くツール作るとか(今回の私の大本の目的)とかであれば、
ヘッダファイル放り込むだけで使えるのですごくいいなという感じです。

ただ良くも悪くも軽いパーサーなので割とレガシー臭がしました。
なのでそのレガシー臭を誤魔化すためにboostはラップしたんでしょうね。
(自分で使いやすいようなラップを作るのが一番かな)

それでは今回はこの辺でノシ