Skip to content

Instantly share code, notes, and snippets.

@okura3
Last active September 2, 2019 06:33
Show Gist options
  • Save okura3/7005560bc52253cf3588 to your computer and use it in GitHub Desktop.
Save okura3/7005560bc52253cf3588 to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
# Mojo::DOM を使い、
# DOM form オブジェクトのパラメータを取り出す例
use Mojo::DOM;
use Data::Dumper;
my $text = do { local $/ = undef; <DATA> };
my $dom = Mojo::DOM->new($text);
my $forms = forms($dom);
print Data::Dumper->Dump( [$forms] ), "\n";
exit;
# DOM から form パラメータを取得する
sub forms {
my $dom = shift;
my $forms = $dom->find('form[action]');
my @data = ();
foreach my $form (@$forms) {
push @data,
+{
name => $form->{name} // '',
action => $form->{action},
method => $form->{method} // 'GET',
params => +{
%{ flatten( input_hidden($form) ) },
%{ flatten( input_submit($form) ) },
%{ flatten( input_button($form) ) },
%{ flatten( input_text($form) ) },
%{ flatten( input_checkbox($form) ) },
%{ flatten( input_textarea($form) ) },
%{ flatten( input_select($form) ) },
},
};
}
return \@data;
}
# <input type="hidden" ...> のデータ取得
sub input_hidden {
my $form = shift;
return input_type( 'hidden', $form );
}
# <input type="submit" ...> のデータ取得
sub input_submit {
my $form = shift;
return input_type( 'submit', $form );
}
# <input type="button" ...> のデータ取得
sub input_button {
my $form = shift;
return input_type( 'button', $form );
}
# <input type="text" ...> のデータ取得
sub input_text {
my $form = shift;
return input_type( 'text', $form );
}
# <input type="checkbox" ...> のデータ取得
sub input_checkbox {
my $form = shift;
return input_type( 'checkbox', $form );
}
# <input type="hidden|submit|text|button|checkbox" ...> のデータ取得
sub input_type {
my $type = shift;
my $form = shift;
my %data;
$form->find("input[type=$type]")->each(
sub {
my $e = shift;
return if !defined( my $name = $e->{name} );
return if $type eq 'checkbox' and !exists $e->{checked};
$data{$name} = [] if !exists $data{$name};
push @{ $data{$name} }, $e->{value};
}
);
return \%data;
}
# <input type="textarea" ...> のデータ取得
sub input_textarea {
my $form = shift;
my %data;
$form->find('textarea')->each(
sub {
my $e = shift;
return if !defined( my $name = $e->{name} );
$data{$name} = []
if !exists $data{$name};
push @{ $data{$name} }, $e->text;
}
);
return \%data;
}
# <input type="select" ...> のデータ取得
sub input_select {
my $form = shift;
my %data;
$form->find('select')->each(
sub {
my $select = shift;
return if !defined( my $name = $select->{name} );
return +{ $name => [ $select->at('option')->{value} ], }
if !defined $select->at('option[selected]');
$data{$name} = []
if !exists $data{$name};
$select->find('option[selected]')->each(
sub {
my $e = shift;
push @{ $data{$name} }, $e->{value};
}
);
}
);
return \%data;
}
# 要素がひとつしかない配列はスカラーにする
sub flatten {
my $data = shift;
my %flatten;
foreach my $key ( keys %$data ) {
$flatten{$key}
= @{ $data->{$key} } == 1
? $data->{$key}[0]
: $data->{$key};
}
return \%flatten;
}
__DATA__
<form name="f1" action="#">
<input type="text" name="t1" value="text1">
<input type="text" name="t2" value="text2">
<input type="checkbox" name="c1" value="0">
<input type="checkbox" name="c1" value="1" checked>
<select name="s1">
<option value="s1" selected>s1</option>
<option value="s2" selected>s2</option>
</select>
<select name="s2">
<option value="s1">s1</option>
<option value="s2">s2</option>
</select>
<textarea name="a1">textarea1</textarea>
<input type="submit" name="submit1" value="submit1">
</form>
<form name="f2" action="#">
<input type="hidden" name="h1" value="hidden1">
<input type="button" name="b1" value="button1">
<input type="text" name="t1" value="text1">
<input type="text" name="t2" value="text2">
<input type="checkbox" name="c1" value="0" checked>
<input type="checkbox" name="c1" value="1">
<input type="checkbox" name="c2" value="0">
<input type="checkbox" name="c2" value="1">
<select name="s1">
<option value="s1" selected>s1</option>
<option value="s2" >s2</option>
</select>
<textarea name="a1">textarea2</textarea>
</form>
<form action="#3"></form>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment