end0tknr's kipple - 新web写経開発

http://d.hatena.ne.jp/end0tknr/ から移転します

YAML::Syck YAML形式のデータを扱う

なぜ、YAML::Syckを使用しているか?

perlyaml形式のデータを扱うには、YAML, YAML::Syck, YAML::Tiny 等のモジュールがあります。

yamlファイルロード時のオーバヘッドの大きさは、
YAML > YAML::Syck > YAML::Tiny のようになるそうです。

http://search.cpan.org/~adamk/YAML-Tiny-1.32/lib/YAML/Tiny.pm

The original pure-Perl implementation YAML costs
just over 4 megabytes of memory to load.
Just like with Windows .ini files (3 meg to load) and CSS (3.5 meg to load)
the situation is just asking for a YAML::Tiny module,
an incomplete but correct and usable subset of the functionality,
in as little code as possible.

しかし、YAML::Tiny には日本語処理に問題があるようなので、
現在、YAML::Syckを使用しています。

http://digit.que.ne.jp/visit/index.cgi?2006%C7%AF9%B7%EE#pYAML%3a%3aTiny%282%29

Load() Dump()

yamlストリーム<->perl構造体には、Load(), Dump()を使用します。

#!perl

use strict;
use warnings;
use YAML::Syck;
use Data::Dumper;

my $yaml=<<EOF;
common:
  name: てすとyaml
stat_cols:
  - key: basic
    name: ベーシック
  - key: simple
    name: ヒーリング
EOF

my $pl = Load($yaml);
print Dumper($pl);

$yaml = Dump($pl);
print Dumper($yaml);

$pl = Load($yaml);
print Dumper($pl);
bash-3.2$ ./foo.pl 
$VAR1 = {
          'common' => {
                        'name' => 'てすとyaml'
                      },
          'stat_cols' => [
                           {
                             'name' => 'ベーシック',
                             'key' => 'basic'
                           },
                           {
                             'name' => 'ヒーリング',
                             'key' => 'simple'
                           }
                         ]
        };
$VAR1 = '--- 
common: 
  name: "\\xE3\\x81\\xA6\\xE3\\x81\\x99\\xE3\\x81\\xA8yaml"
stat_cols: 
  - 
    key: basic
    name: "\\xEF\\xBE\\x8D\\xEF\\xBE\\x9E\\xEF\\xBD\\xB0\\xEF\\xBD\\xBC\\xEF\\xBD\\xAF\\xEF\\xBD\\xB8"
  - 
    key: simple
    name: "\\xEF\\xBE\\x8B\\xEF\\xBD\\xB0\\xEF\\xBE\\x98\\xEF\\xBE\\x9D\\xEF\\xBD\\xB8\\xEF\\xBE\\x9E"
';
$VAR1 = {
          'common' => {
                        'name' => 'てすとyaml'
                      },
          'stat_cols' => [
                           {
                             'name' => 'ベーシック',
                             'key' => 'basic'
                           },
                           {
                             'name' => 'ヒーリング',
                             'key' => 'simple'
                           }
                         ]
        };

Load() Dump()時の文字化解消する

先程の例のように日本語を含んだyamlデータを
Load()→Dump()→Load()すると元のyamlを取得できますが、
Load()→Dump()後に文字化けしていることが分かります。

このような文字化けを防ぐ?為、私の場合、予めunpack()でurl encodingしています。
(どこかのサイトから引用したものですが、それがどこだったか...)

sub ConvertEncoding_unpack {
    my($self,$p) = @_;

    my $r = ref($p);

    ### if [BLESSED] HASH REFERENCE ###
    if($r eq 'HASH' || ( !$r && $p =~ /=HASH\(.+\)/o )){
	my $v;
	foreach $v (keys %{$p}){
	    $p->{$v} = $self->ConvertEncoding_unpack($p->{$v});
	}
    }
    ### if [BLESSED] ARRAY REFERENCE ###
    elsif($r eq 'ARRAY' || ( !$r && $p =~ /=ARRAY\(.+\)/o )){
	my $i=0;
	for ($i;$i <= $#{$p};$i++){
	    $p->[$i] = $self->ConvertEncoding_unpack($p->[$i]);
	}
    }
    ### if [BLESSED] CODE REFERENCE ###
    elsif($r eq 'CODE' || ( !$r && $p =~ /=CODE\(.+\)/o )){
    }
    ### if SCALAR ###
    else{
	$p =~ s/(\W)/'%' . unpack('H2', $1)/ego;
    }
    return $p;
}

LoadFile($filepath)

yamlファイルのパスから直接perl構造体を取得するにはLoadFile()を使用します。

use YAML::Syck;

my $YAML_PATH = "〜":
my $pl = LoadFile($YAML_PATH);