XSLT output
The most common special need for XSLT extensions is to generate XSLT output. For extension elements this is easy enough to do using the API on the procssor instance that is passed to the instantiate() method of extension element classes. For example
class SpamElement(XsltElement): legalAttrs = {} def instantiate(self, context, processor): processor.output().startElement('title') processor.output().text('Life of Brian')) processor.output().endElement('title') return (context,)
Extension functions are not passed a processor instance directly, but context objects hold a reference to the processor in effect, so the following example works:
def Spam(context): context.processor.output().startElement('title') context.processor.output().text('Life of Brian')) context.processor.output().endElement('title') return
However, it is probably better design to reserve such side effects as output for extension elements rather than functions.
In the above examples the elements and text out out just use the current output parameters. In order to change output parameters or change the output stream, you can stack a new output handler:
stream = cStringIO.StringIO()
#Clone the curent outputparameters
op = processor.writers[-1]._outputParams.clone()
#Force XML output method with XML declaration
#Output method is a qualified name, so must flag null ns
#to use standard xml method
op.method = (EMPTY_NAMESPACE, 'xml')
op.omitXmlDeclaration = "yes"
#Push the new handler to the top of the writer stack
processor.addHandler(op, stream)
processor.output().startElement('title')
processor.output().text('Life of Brian'))
processor.output().endElement('title')
#Pop back to the previous handler stream.getvalue()
#now contains the new output
processor.removeHandler()
Creating result tree fragments
Another common need is to treat the body of an extension element as a template so that something can be done with the RTF that results from it. The following example demonstrates this:
#Set the output to an RTF riter, which wll create an RTF for us
processor.pushResultTree(self.baseUri)
#The template is manifested as children of the extension element
#node. Instantiate each in turn
for child in self.children:
context = child.instantiate(context, processor)[0]
#You want to be sure you re-balance the stack even in case of error
finally:
#Retrieve the resulting RTF
result_rtf = processor.popResult()
It can also be written in Python shorthand as:
processor.pushResultTree(self.baseUri)
try:
context = reduce(lambda context, child, processor=processor:
child.instantiate(context, processor)[0],
self.children, context)
finally:
result_rtf = processor.popResult()
Comunicating with the external code that invokes XSLT
You can set and communicate state information with external code by using the processor.extensionParams attribute. For example, the following sents a time stamp of precisely when the extension was instantiated, which can later be retrieved from the processor after the XSLT process, or even by later extensions. In a similar way, state can be set up by calling functions and retrieved by extensions.
#Extension parameters have fully qualified names, so you must come up #with a namespace to set them processor.extensionParams[(SPAM_NAMESPACE, 'tstamp')] = time.time()
