XML::RSS's code is made up mostly
of accessors -- methods that read and write to predefined places
in the structure it's building. Using nothing more
complex than a few Perl hashes, XML::RSS builds
maps of what it expects to see in the document, made of nested hash
references with keys named after the elements and attributes it might
encounter, nested to match the way one might find them in a real RSS
XML document. The module defines one of these maps for each version
of RSS that it handles. Here's the simplest one,
which covers RSS Version 0.9:
my %v0_9_ok_fields = (
channel => {
title => '',
description => '',
link => '',
},
image => {
title => '',
url => '',
link => ''
},
textinput => {
title => '',
description => '',
name => '',
link => ''
},
items => [],
num_items => 0,
version => '',
encoding => ''
);
This model is not entirely made up of hash references, of course; the
top-level "items" key holds an
empty array reference, and otherwise, all the end values for all the
keys are scalars -- all empty strings. The exception is
num_items, which isn't among
RSS's elements. Instead, it serves the role of
convenience, making a small trade-off of structural elegance for the
sake of convenience (presumably so the code doesn't
have to keep explicitly dereferencing the items
array reference and then getting its value in scalar context).
On the other hand, this example risks going out of sync with reality
if what it describes changes and the programmer
doesn't remember to update the number when that
happens. However, this sort of thing often comes down to programming
style, which is far beyond the bounds of this book.
There's good reason for this arrangement, besides
the fact that hash values have to be set to something (or
undef, which is a special sort of something). Each
hash doubles as a map for the module's subroutines
to follow and a template for the structures themselves. With that in
mind, let's see what happens when an
XML::Parser item is constructed via this
module's new class method.