The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Kite::XML::Node - base class for XML parser nodes

SYNOPSIS

    package Kite::XML::Node::Foo;

    use base qw( Kite::XML::Node );
    use vars qw( $ATTRIBUTES $ELEMENTS $ERROR );

    # define some attributes for the element node
    $ATTRIBUTES = {
        id    => undef,         # mandatory
        lang  => 'en',          # default value
        title => '',            # optional attribute
    };

    # define permitted child elements
    $ELEMENTS = {
        # single 'bar' child element
        bar => 'Kite::XML::Node::Bar',
        # multiple 'baz' child elements
        baz => 'Kite::XML::Node::Baz+',
        # require "Kite/XML/Node/Baz.pm"
        wiz => [ 'Kite::XML::Node::Wiz' => 1 ]
        # require some other module, accept multiple children
        waz => [ 'Kite::XML::Node::Waz+' => 'some/other/module.pm' ],
        # accept character content
        CDATA => 1,
    };

    package main;

    my $foo = Kite::XML::Node::Foo->new(id => 12345)
        || die Kite::XML::Node::Foo->error(), "\n";

    # set/get attributes via AUTOLOAD accessor methods...
    $foo->title('New Title');
    print $foo->id();           # 12345
    print $foo->lang();         # 'en'
    print $foo->title();        # 'New Title'

    # ...or using explicit attr() (or attribute()) method
    $foo->attr('title', 'New Title');
    $foo->attribute('title', 'New Title');
    print $foo->attr('title');  # 'New Title'

    # create new 'bar' child element
    $foo->child('bar', @some_bar_args)
        || die $foo->error(), "\n";

    # same, using AUTOLOAD method (_must_ pass additional args)
    $foo->bar(@some_bar_args)
        || die $foo->error(), "\n";
    
    # retrieve elements via AUTOLOAD methods (_don't_ pass any args)
    my $bar = $foo->bar();

    # ...or using explicit elem() (or element()) method
    $bar = $foo->elem('bar');
    $bar = $foo->element('bar');

    # create multiple 'baz' children
    $foo->child('baz', @some_baz_args)
        || die $foo->error(), "\n";
    $foo->child('baz', @more_baz_args)
        || die $foo->error(), "\n";

    # multiple elements returned as (possibly empty) list reference
    foreach my $baz (@{ $foo->baz() }) {
        print $baz->some_attribute();
    }

    # append/retrieve character content
    $foo->char('Character Content');
    print $foo->char();

DESCRIPTION

This module implements a base class for objects that are constructed automatically by the Kite::XML::Parser to represented parsed XML nodes (i.e. elements).

Other modules may be derived from base class to represent specific XML element nodes.

    package Kite::XML::Node::Foo;
    use base qw( Kite::XML::Node );

The base class methods examine variables in the package of the subclass to determine the permitted attributes and elements of the node. The $ERROR variable is also used for reporting class errors.

    use vars qw( $ATTRIBUTES $ELEMENTS $ERROR );

The $ATTRIBUTES package variable may be defined as hash reference containing valid attributes for the node. Default values may be provided. Any values left undefined are mandatory and must be provided to the new() constructor.

    # define some attributes for the element node
    $ATTRIBUTES = {
        id    => undef,         # mandatory
        lang  => 'en',          # default value
        title => '',            # optional attribute
    };

The $ELEMENTS package variable may also be defined as a hash reference detailing valid child elements of the node. The keys represent the element names and the relevant values should be the package names of other Kite::XML::Node subclasses. The package name may be suffixed by a '+' to indicate that multiple child elements of this type are permitted. It may also be defined as a reference to an array containing the package name as before, followed by the name of a specific module to load (via require()) before instantiating objects of that type. This value may also be specified as '1' to indicate that the relevant module for the package should be required (i.e. change '::' to '/' and append '.pm'). The CDATA key can also be specified to contain any true to indicate that the element should also accept character content.

    # define permitted child elements
    $ELEMENTS = {
        # single 'bar' child element
        bar => 'Kite::XML::Node::Bar',

        # multiple 'baz' child elements
        baz => 'Kite::XML::Node::Baz+',

        # require "Kite/XML/Node/Baz.pm"
        wiz => [ 'Kite::XML::Node::Wiz' => 1 ]

        # require some other module, accept multiple children
        waz => [ 'Kite::XML::Node::Waz+' => 'some/other/module.pm' ],

        # accept character content
        CDATA => 1,
    };

The derived class can then be used to instantiate XML node objects to represent XML elements. Any mandatory attributes (i.e. $ATTRIBUTES set to undef) must be provided to the constructor.

    package main;

    my $foo = Kite::XML::Node::Foo->new(id => 12345)
        || die Kite::XML::Node::Foo->error(), "\n";

Any optional attributes may also be provided. Any default values specified in $ATTRIBUTES will be set if otherwise undefined.

    my $foo = Kite::XML::Node::Foo->new(id => 12345, title => 'test')
        || die Kite::XML::Node::Foo->error(), "\n";

Attribute arguments may also be specified as a hash reference for convenience.

    my $foo = Kite::XML::Node::Foo->new({
        id => 12345, 
        title => 'test',
    }) || die Kite::XML::Node::Foo->error(), "\n";

The new() constructor returns undef on failure and sets the $ERROR package variable in the subclass. This can then be inspected directly or by calling error() as a class method.

    my $foo = Kite::XML::Node::Foo->new(...)
        || die $Kite::XML::Node::Foo::ERROR;

    my $foo = Kite::XML::Node::Foo->new(...)
        || die Kite::XML::Node::Foo->error();

An AUTOLOAD method is provided to allow attributes to be accessed as methods. Arguments passed to these methods will be used to set the attribute, otherwise the attribute value will be returned.

    $foo->title('New Title');
    print $foo->id();           # 12345
    print $foo->lang();         # 'en'
    print $foo->title();        # 'New Title'

The attr() method can also be used explicitly. This is also aliased to attribute().

    $foo->attr('title', 'New Title');
    $foo->attribute('title', 'New Title');
    print $foo->attr('title');  # 'New Title'

The child() method is used to create a new child element. The first argument specifies the element type and should be defined in $ELEMENTS. Any additional arguments are passed to the new() constructor method for that element. The instantiated child node is stored internally by the element name. Single elements (i.e. those that aren't suffixed by '+' in $ELEMENTS) may only be defined once and will generate an error (returning undef) if an attempt is made to redefine an existing element.

    # create new 'bar' child element
    $foo->child('bar', @some_bar_args)
        || die $foo->error(), "\n";

Multiple elements (i.e. those suffixed '+' in $ELEMENTS) may be added any number of times.

    $foo->child('baz', @some_baz_args)
        || die $foo->error(), "\n";
    $foo->child('baz', @more_baz_args)
        || die $foo->error(), "\n";

The AUTOLOAD method can be used to return element values. Single elements return a single object (or undef), multiple elements return a reference to a list which may be empty (no children defined).

    my $bar = $foo->bar();
    print $bar->some_attribute();

    foreach my $baz (@{ $foo->baz() }) {
        print $baz->some_attribute();
    }

The elem() method can also be used explicitly. This is also aliased to element().

    my $bar = $foo->elem('bar');
    my $baz = $foo->element('bar');

Additional arguments may be passed to the elem() method to create a new child element. This is then delegated to the child() method.

    $foo->elem('bar', @some_bar_args)
        || die $foo->error(), "\n";

    # same as
    $foo->child('bar', @some_bar_args)
        || die $foo->error(), "\n";

The AUTOLOAD method can be used in the same way. Note that both these uses require additional arguments to be passed to distinguish them from simple retrieval calls.

    $foo->bar(@some_bar_args)
        || die $foo->error(), "\n";

The char() method is provided to retrieve and update character content for the element. The CDATA item should be defined to any true value in $ELEMENTS for character data to be accepted. Note however, that any node which doesn't defined CDATA true will accept and ignore any character data consisting of nothing but whitespace. Any text data passed as the first argument is appended to the current character content buffer. The buffer is then returned.

    # append/retrieve character content
    $foo->char('Character Content');
    print $foo->char();

AUTHOR

Andy Wardley <abw@kfs.org>

REVISION

$Revision: 1.1 $

COPYRIGHT

Copyright (C) 2000 Andy Wardley. All Rights Reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

SEE ALSO

See also <Kite::XML::Parser>.