日向夏特殊応援部隊

俺様向けメモ

XML::Writer

今まで使ったこと無かったけど、これは便利だ。

#!/usr/bin/perl

use strict;
use warnings;

use IO::String;
use XML::Beautify;
use XML::Writer;

my $osns   = 'http://ns.opensocial.org/2008/opensocial';
my $buffer = IO::String->new;
my $writer = XML::Writer->new(
    NAMESPACES => 1,
    ENCODING   => 'utf-8',
    OUTPUT     => $buffer,
    PREFIX_MAP => +{ $osns => '', }
);

my $response = +{
    startIndex   => 1,
    itemsPerPage => 2,
    totalResults => 100,
    entry        => [
        +{
            id     => '34KJDCSKJN2HHF0DW20394',
            name   => +{ unstructured => 'Jane Doe', },
            gender => 'female',
        },
        +{
            id     => 'VMK92BFH3DNWRYX39673DF',
            name   => +{ unstructured => 'John Smith', },
            gender => 'male',
        },
    ],
};

$writer->startTag( [ $osns, 'response' ] );

render_xml( $writer, $response );

$writer->endTag( [ $osns, 'response' ] );
$writer->end;

my $formatter = XML::Beautify->new();
$formatter->indent_str('  ');

my $xml = $formatter->beautify($buffer->string_ref);
print $xml;

$buffer->close;

sub render_xml {
    my ( $writer, $data ) = @_;

    for my $field ( keys %$data ) {
        my $val = $data->{$field};
        if ( ref $val eq 'HASH' ) {
            $writer->startTag($field);
            render_xml( $writer, $data->{$field} );
            $writer->endTag($field);
        }
        elsif ( ref $val eq 'ARRAY' ) {
            for my $entry (@$val) {
                $writer->startTag('entry');
                $writer->startTag('person');

                render_xml( $writer, $entry );

                $writer->endTag('person');
                $writer->endTag('entry');
            }
        }
        else {
            $writer->startTag($field);
            $writer->characters($val);
            $writer->endTag($field);
        }
    }
}

みたいなコードを書くと、

<response xmlns="http://ns.opensocial.org/2008/opensocial">
  <entry>
    <person>
      <name>
        <unstructured>Jane Doe</unstructured>
      </name>
      <id>34KJDCSKJN2HHF0DW20394</id>
      <gender>female</gender>
    </person>
  </entry>
  <entry>
    <person>
      <name>
        <unstructured>John Smith</unstructured>
      </name>
      <id>VMK92BFH3DNWRYX39673DF</id>
      <gender>male</gender>
    </person>
  </entry>
  <startIndex>1</startIndex>
  <itemsPerPage>2</itemsPerPage>
  <totalResults>100</totalResults>
</response>

って感じで出力される。