OP へ: 構成形式を適切に記述していませんでした。XML フラグメントが役に立ちました。そのままでは、フォーマットに合わせて以下のソリューションを変更する必要があるでしょう。
次の形式を想定しました。
<conf>
<option><name>configuration1</name><value>string1 modified</value></option>
<option><name>configuration2</name><value>string2 re-modded</value></option>
<option><name>configuration3</name><value>string3</value></option>
</conf>
この形式を処理するコードは次のようになります。
#!/usr/bin/perl
use strict;
use warnings;
use CGI qw( -nosticky -utf8 :standard form );
use XML::LibXML;
my $CONF="/web/data/conf.xml"; # or wherever your XML is located
# dispatch table, action => code to process it
my $dispatch= { display => \&display_conf,
edit => \&display_edit_form,
save => \&save_edits,
};
# action is "what to do"
my $action= param( 'action') || 'display';
$dispatch->{$action}->() || exit_error( "wrong action");
exit;
# load the XML and build a table to display it
sub display_conf
{ my $conf= XML::LibXML->load_xml( location => $CONF);
my $content;
foreach my $option ($conf->findnodes( '/conf/option'))
{ $content .= Tr( td( $option->findvalue( './name')),
td( $option->findvalue( './value'))
);
}
$content= table( $content);
# add a link to the edit form
$content .= p( a({ href => url() . '?action=edit' }, 'edit'));
output( $content);
}
# load the XML and build a form that will let you edit it
sub display_edit_form
{ my $conf= XML::LibXML->load_xml( location => $CONF);
my $content;
foreach my $option ($conf->findnodes( '/conf/option'))
{ $content .= Tr( td( $option->findvalue( './name')),
td( input( { type => "text", size => 40,
name => $option->findvalue( 'name'),
value => $option->findvalue( './value')}
)
)
);
}
$content= table( $content);
$content= form( { action => url() },
hidden( { name => 'action', value => 'save', override => 1 }),
$content,
submit( 'Save'),
);
output( $content);
}
# load the XML, go through all options, update the value from the form,
# save the XML, display it value, from the form
sub save_edits
{ my $conf= XML::LibXML->load_xml( location => $CONF);
foreach my $option ($conf->findnodes( '/conf/option'))
{ my $new_value= param( $option->findvalue( './name'));
my( $value_node)= $option->findnodes( './value');
$value_node->removeChildNodes();
$value_node->appendText( $new_value);
}
$conf->toFile( $CONF);
display_conf();
}
# placeholder,
sub exit_error
{ my $message= shift;
print header(), p($message);
}
# output subs, load the template, inject the content and output (with header)
sub output
{ my $content= shift;
print header(), fill_in_string( template(), content => $content );
}
sub fill_in_string
{ my( $template, %param)= @_;
$template=~ s{<<(\w+)>>}{$param{$1}}g;
return $template;
}
sub template
{ return join '', <DATA>; }
# template, very simple
__DATA__
<html>
<head>
<title>Configuration Editor</title>
</head>
<body>
<h1>Configuration Editor</h1>
<h2>Configuration</h2>
<<content>>
</h2>
</body>
</html>
配置: コードを CGI として実行できる場所に配置conf.xml
し、Web サーバーで読み書きできることを確認します。Web ツリーの外に置いた方がよいでしょう。
これは、ある意味では有史以前の Perl です。CGI は古風であると広く考えられており、Perl にはより現代的で洗練されたオプションが用意されています。構成がキー/値リストよりも複雑な場合、各フィールドのカスタム ヘルプが必要な場合、または会社のルック アンド フィールに準拠するためにより複雑なテンプレートを使用する必要がある場合は、Dancer や Mojolicious などの Web フレームワーク上記の単純なソリューションよりも適しています。
OTOH は機能します。これは、少数の内部ユーザーがいて、UI に関してあまり必要としない多くの小さなツールを作成する方法です。
Perl に慣れていない人がこれを行うには複雑すぎると示唆した人たち、さすがです! これはロケット科学ではありません。これは、人々が Perl を使い始めるきっかけとなるようなコードです。なぜそれを書くのを手伝わないのでしょうか? 実際、これはThe Reluctant Perl Programmer の完璧な実例です。