NAME
XML::Object - Methodical XML Configuration
SYNOPSIS
XML
<config>
<run name="John Doe">
<port>4321</port>
<user>bar</user>
</run>
<foo>
<port>1234</port>
<bar>
<baz>Luhrmann</baz>
</bar>
<list>alpha</list>
<list>
<beta>gamma</beta>
</list>
<list>vlissides</list>
<email>foo@bar.com</email>
<address>1 Foo Street, Bar FB1 1FB</address>
</foo>
<user>foo</user>
</config>
XML::Simple
{
run => {
name => 'John Doe',
port => '4321',
user => 'bar'
},
foo => {
port => '1234',
bar => {
baz => 'Luhrmann'
},
list => [
'alpha',
{
'beta' => 'gamma'
},
'vlissides'
],
email => 'foo@bar.com',
address => '1 Foo Street, Bar FB1 1FB'
},
user => 'foo'
}
main.pl
use Foo;
# call from a subroutine to demonstrate caller_test() / caller_demand()
sub run {
my $foo = Foo->new($config_file, %optional_xml_simple_options);
$foo->foo();
}
run();
Foo.pm
package Foo;
use base qw(XML::Object);
# package can now configure itself via XML
# optional constructor
sub new {
my $class = shift;
my $self = $class->SUPER(@_);
# ...
}
sub foo {
my $self = shift;
# optional: test() returns undef if the value isn't found
# equivalent to $self->config()->{foo}->{port}
my $port = $self->test('port') || 8080;
# compulsory: demand() throws an exception if the value isn't found
# equivalent to $self->config()->{foo}->{email}
my $email = $self->demand('email');
# arbitrarily deep path expressions
# equivalent to $self->config()->{foo}->{list}->[1]->{beta}
my $leaf = $self->demand('list', 1, 'beta');
# provide an explicit key: $self->config()->{user}
my $user = $self->key_test('user');
# use the name of the function that called this function as the root
# equivalent to $self->config()->{run}->{name}
my $name = $self->caller_demand('name');
# equivalent to $self->key_demand('foo') i.e. $self->config()->{foo}
my $foo = $self->demand();
# supply your own configuration HASH or ARRAY ref
my $alpha = $self->key_test($array_or_hash_ref, 'alpha');
my $beta = $self->key_demand($array_or_hash_ref, 'beta');
}
DESCRIPTION
XML::Object allows easy (XML) configuration of a Perl script/module by associating methods with elements. Because each method has its own configuration 'namespace', the structure of the XML reflects that of the object and vice-versa. This partitioning leads to a simple and intuitive organisation of the configuration space.
XML::Object::DBI adds a database accessor (get) and mutator (set) to the mix. These shield the user from DBI housekeeping while freeing them to manage the SQL in an intuitive and flexible way.
METHODS
test
usage
sub example {
my $self = shift;
# i.e. $self->key_test('example', 'port');
my $optional1 = $self->test('port') || 8080;
# or
# i.e. $self->key_test($hash_or_array_ref, 'example', 'port');
my $optional2 = $self->test($hash_or_array_ref, 'port');
}
summary
test()
looks up a scalar, ARRAY ref or HASH ref using the name of the current subroutine and any supplied arguments as the root (i.e. first HASH key or ARRAY index) of the path into the configuration HASH or ARRAY ref.
Numbers and strings in the path are interpreted according to the context discovered during the course of the lookup. Thus in the following example:
sub foo {
my $self = shift;
my $test = $self->test('list', 1, 'beta');
}
That path is first translated into the equivalent of:
$self->key_test('foo', 'list', 1, 'beta');
Which in turn becomes:
$self->config()->{foo}->{list}->[1]->{beta}
test()
, demand()
, caller_test()
, caller_demand()
, key_test()
and key_demand()
can be passed a HASH or ARRAY ref as the first argument. The lookup is then performed against this structure rather than the object's configuration HASH/ARRAY ref.
e.g.
my $login = $self->demand('login'); # grab the login HASH
my $user = $self->key_demand($login, 'username'); # compulsory username
my $password = $self->key_test($login, 'password'); # optional password
demand
usage
sub example {
my $self = shift;
# i.e. $self->key_demand('example', 'user');
my $compulsory1 = $self->demand('user');
# or
# i.e. $self->key_demand($array_or_hash_ref, 'example', 'user');
my $compulsory2 = $self->demand($array_or_hash_ref, 'user');
}
summary
demand()
works the same as test()
, but raises an exception if the specified value is not defined or the path is invalid.
caller_test
usage
sub run {
my $self = shift;
$self->example();
}
sub example {
my $self = shift;
# i.e. $self->key_test('run', 'port');
my $optional1 = $self->caller_test('port') || 8080;
# or
# i.e. $self->key_test($array_or_hash_ref, 'run', 'port');
my $optional2 = $self->caller_test($array_or_hash_ref, 'port') || 8080;
}
summary
caller_test()
uses the name of the subroutine that called the current subroutine as the root of the path. Otherwise its use is the same as test()
.
caller_demand
usage
sub run {
my $self = shift;
$self->example();
}
sub example {
my $self = shift;
# i.e. $self->key_demand('run', 'user');
my $compulsory1 = $self->caller_demand('user');
# or
# i.e. $self->key_demand($array_or_hash_ref, 'run', 'user');
my $compulsory2 = $self->caller_demand($array_or_hash_ref, 'user');
}
summary
caller_demand()
uses the name of the subroutine that called the current subroutine as the root of the path. Otherwise its use is the same as demand()
.
key_test
usage
sub example {
my $self = shift;
my $optional = $self->key_test('port') || 8080;
# or
my $optional = $self->key_test($array_or_hash_ref, 'port') || 8080;
}
summary
key_test()
uses only the explicitly specified key(s) to index into the default or supplied configuration ARRAY or HASH ref. The other flavours of test()
are implemented as wrappers of key_test()
.
key_demand
usage
sub example {
my $self = shift;
my $compulsory1 = $self->key_demand('user');
# or
my $compulsory2 = $self->key_demand($array_or_hash_ref, 'user');
}
summary
key_demand()
uses only the explicitly specified key(s) to index into the default or supplied configuration ARRAY or HASH ref. The other flavours of demand()
are implemented as wrappers of key_demand()
.
configure
usage
my $path = $self->configure();
# or
my ($path, $xml_simple_options) = $self->configure();
# or
$self->configure($path, %optional_xml_simple_args);
summary
When called with no arguments configure()
returns a) the path to the configuration file in scalar context, or b) the path and a reference to the (possibly empty) HASH of XML::Simple::XMLin()
options in list context.
When called with a path argument and an optional HASH of arguments to be supplied to XML::Simple's XMLin()
, a new configuration HASH or ARRAY ref is initialized in the object and returned.
config
usage
my $config = $self->config();
# or
$self->config($array_or_hash_ref);
summary
When called with no arguments config()
returns the configuration HASH ref or ARRAY ref associated with the object.
When called with an argument that value is assigned as the object's new configuration.
parent
usage
my $caller = $self->parent();
summary
Returns the name (minus namespace) of the subroutine that called the current subroutine. Throws an exception unless that value is defined.
grandparent
usage
my $caller_caller = $self->grandparent();
summary
Returns the name (minus namespace) of the subroutine that called the subroutine that called the current subroutine. Throws an exception unless that value is defined.
EXCEPTIONS
XOE
Superclass for all XML::Object Exceptions.
XOE::BadConfig
Thrown if an attempt is made to assign an invalid (i.e. nonexistent or zero-length) configuration file.
XOE::BadGrandparent
Thrown if a caller_get* or caller_set* method is invoked in a context in which the call stack isn't deep enough for the grandparent of the caller_* method to be identified.
XOE::BadLookup
Thrown if a demand()
fails either a) by being resolved to a value that is undefined or b) if the path is not valid within the configuration ARRAY or HASH ref.
XOE::BadParent
Thrown if a get* or set* method is invoked in a context in which the call stack isn't deep enough for the parent of the get* or set* method to be identified.
XOE::BadXML
Thrown if an error occurs during XML::Simple's XMLin()
routine, which turns the specified XML into a Perl data structure.
EXPORT
None by default.
SEE ALSO
XML::Object::DBI, XML::Simple
AUTHOR
chocolateboy <chocolate.boy@email.com>
COPYRIGHT AND LICENSE
Copyright 2003 by chocolateboy
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.