|
|
TaglibHelper - module to make it easier to write a taglib
package My::Taglib;
use Apache::AxKit::Language::XSP::TaglibHelper;
@ISA = qw( Apache::AxKit::Language::XSP::TaglibHelper );
## Edit $NS to be the namespace URI you want $NS = 'http://apache.org/xsp/testtaglib/v1';
## Edit @EXPORT_TAGLIB as needed @EXPORT_TAGLIB = ( 'func1($arg1)', 'func2($arg1,$arg2)', 'func3($arg1,$arg2;$optarg)', 'func4($arg1,*treearg)', 'func4($arg1,*treearg):listtag=mylist:itemtag=item', );
use strict;
sub func1 { my ( $arg1 ) = @_ ; ... return $scalar_or_reference; }
...
1;
the functions with the same names as listed in @EXPORT_TAGLIB
.
The TaglibHelper module is intended to make it much easier to build a taglib module than had previously existed. When you create a library that uses TaglibHelper, you need only to write ``regular'' functions that take string arguments (optional arguments are supported) and return standard Perl data structures like strings and hashrefs.
The @EXPORT_TAGLIB global variable is where you list your exported functions. It is of the format:
funcname(arguments)[:options]
The <arguments
> section contains arguments of the form:
These arguments are separated by commas, and optional args are
separated from required ones by a semicolon. For example,
$field1,$field2;$field3,$field4
has required parameters field1
and field2
, and optional parameters field3
and field4
.
The options are colon-separated and give extra hints to TaglibHelper in places where the default behavior isn't quite what you want. All options are key/value pairs, formatted as key1=value1:key2=value2, etc. Currently recognized options are:
"person($name):isreally=get_person"
allows you to have a tag <ns:person
name=``Joe''/> that will resolve to Perl code ``get_person('Joe')''.
if you had these two functions:
sub hello ($) { my ($name) = @_; return "Hello, $name!"; }
sub get_person ($) { my ($name) = @_; return { person => { name => $name, age => 25, height => 200, } } }
...and you called them with this xsp fragment:
<test:hello> <test:name>Joe</test:name> </test:hello>
<test:get-person name="Bob"/>
...you would get this XML result:
Hello, Joe! <person> <height>200</height> <age>25</age> <name>Bob</name></person>
If your function returned deeper result trees, with hashes containing hashrefs or something similar, that would be handled fine. There are some limitations with arrays, however, described in the BUGS AND LIMITATIONS section.
If you wish to send structured data (i.e. not just a scalar) to a taglib function, use ``*'' instead of ``$'' for a variable. The input to a taglib function specified as ``insert_person($pid,*extra)'' might be:
<test:insert-person pid="123"> <test:extra> <weight>123</weight> <friends> <pid>3</pid> <pid>5</pid> <pid>13</pid> </friends> </test:extra> </test:insert-person>
The function call would be the same as:
insert_function("123", { weight => 123, friends => [ 3, 5, 13 ] } );
The <friends> container holds repeating tags, notice, and TaglibHelper figured out automatically that it needs to use an arrayref instead of hashref for the values. But you'll get unexpected results if you mix repeating tags and nonrepeating ones:
<test:extra> <weight>123</weight> <friend>3</friend> <friend>5</friend> <friend>13</friend> </test:extra>
Just wrap your singular repeated tags with a plural-form tag, in this case <friends>.
If you wish to send an arbitrary number of values to a taglib function's parameter, use ``@'' instead of ``$'' for the variable in the EXPORT_TAGLIB header array (but still declare it with ``$'' in the function declaration). The parameter will end up turning into an arrayref. For example, you might have a TaglibHelper header:
listbox($name;$pretty_name,@option,$default,$multiple,$size,$required)
and a Perl declaration:
sub listbox ($$$$$$$) { my ($name, $pretty_name, $options, $default, $multiple, $size, $required) = @_; ... }
and an XSP file that calls it:
<test:listbox name="country" pretty_name="Pick a Country" default="" required="1"> <test:option name="Please choose a country" value=""/> <test:option name="United States" value="US"/> <test:option name="Canada" value="CA"/> </test:listbox>
It would turn into this function call:
listbox("country", "Pick a Country", [ { name => "Please choose a country", value => "" }, { name => "United States", value => "" }, { name => "Canada", value => "CA" }, ], "", undef, undef, 1);
Hopefully the example is clear enough.
Arrays and arrayrefs are generally difficult to work with because the items within the array have no keys other than the index value. As a result, if you want items within an array to be identified correctly, you must currently make all array items point to a hashref that contains the item's key or you must use the optional arguments to give TaglibHelper enough ``hints'' to be able to represent the XML tree the way you want.
Steve Willer, steve@willer.cc
AxKit.