Creating extension functions PreviousNext

This chapter describes how to create your own library of XPath extension functions which can be called within your XSLT transformations.

Creating your extension functions

The first step is to write the Eiffel code for your extension functions. You do this by writing at least one Eiffel class. Usually you should create a separate class for each function, but if several functions are variations on a theme, it might be simpler for them all to share one class, and just use a different creation procedure for each implemented function. An example of this approach is the implementation of the core XPath functions fn:encode-for-uri(), fn:iri-to-uri() and fn:escape-html-uri(), which all share the same implementation code in XM_XPATH_ESCAPE_URI, the only difference between them being the set of reserved characters.

Your Eiffel class should be a descendant of XM_XPATH_SYSTEM_FUNCTION (if it is possible for your function to always be evaluated when the transformation is compiled, then it is more efficient to inherit fron XM_XPATH_COMPILE_TIME_FUNCTION instead).

Writing extension functions as descendants of XM_XPATH_SYSTEM_FUNCTION probably requires some understanding of how the XPath library works. This is not properly documented yet. If in doubt ask for help on one of the Gobo mailing lists.

You will usually want to redefine either evaluate_item or create_iterator, or both (if your function ever returns sequences of more than one item, then you will need to redefine create_iterator).

You may also need to redefine other routines. These routines are likely candidates:

pre_evaluate
By default, the library will attempt to pre-evaluate your function at compile time, if it can determine that all the arguments are fixed values. If for some reason that is unsuitable behaviour, then you should redefine this routine to do nothing.
simplify
This performs optimizations that do not depend upon the XPath static context. By default it just simplifies all the other arguments. This is a suitable point for setting optimization flags that depend upon the number of arguments actually passed.
check_arguments
This routine checks the number and type of arguments. This is a suitable place for performing additional checks or optimizations on particular arguments.
calculate_effective_boolean_value
This routine evaluates the function as a boolean.
check_static_type
This routine performs static type checking on the function.
optimize
This routine performs optimizations at compile time. By default it optimizes all the arguments.
evaluate_as_string
This routine evaluates the function when it is known to return a single string.
compute_special_properties
This routine sets flags for the optimization process.
compute_intrinsic_dependencies
This routine sets flags for the optimization process.

You will also need to implement the following routines:

item_type
This routine tells the static type checker and optimizer what type of items might be returned by the function. Be as specific as you can, so that more optimizations can be performed.
required_type
This routine tells the static type checker what type and length of sequence is allowed for each argument.
compute_cardinality
This routine tells the static type checker and optimizer now many items might be returned by the function.

You must also implement a creation routine with zero arguments. This must perform the following operations:

Creating an extension function library

Next you should create a descendant of XM_XPATH_FUNCTION_LIBRARY. You need to implement two routines:

is_function_available
If a_fingerprint is equal to the value of fingerprint for your function, then you should return True if an_arity is -1, or if it lies (inclusively) between the values that you set for minimum_argument_count and maximum_argument_count for your function.
bind_function
You should create the function that matches a_fingerprint. Then call set_arguments (some_arguments). Then you should set last_bound_function to the created function.

If the argument is_restricted is True, then your function is being bound within an [xsl:]use-when context. If it is sensible for your function to be callable in such a context, then by all means ignore this argument. Otherwise you should create an instance of XM_XSLT_DEFERRED_ERROR. See XM_XSLT_BUILTIN_EXTENSION_FUNCTIONS for an example.

Informing the XSLT library of your extension function library

There is one last step to take, you have to tell the library about the existence of your function library.

Just pass your library as the sole argument to add_extension_function_library of XM_XSLT_CONFIGURATION. After this call, your library will be searched whenever a transformation is compiled.


Copyright 2005, Colin Adams and others
mailto:colin@colina.demon.co.uk
http://www.gobosoft.com
Last Updated: Monday, November 21st, 2005
HomeTocPreviousNext