2005
Colin Adams and others
Colin
Adams
colin@colina.demon.co.uk Monday, November 21st, 2005

# Creating extension functions

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:

- Set the attributes name and namespace_uri to name your function.

- Set fingerprint to match name and namespace_uri.

- Set the attributes minimum_argument_count and maximum_argument_count to specify the number of permitted arguments.

- Finally create arguments and set initialized to True.

## 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.