4XSLT Processor


Built-in Extension Elements

4XSLT supports user-defined extension elements as specified by the XSLT Recommendation. There are several extension elements built in, which are documented here.


<ft:apply-templates
  select = node-set-expression 
  mode = string-expression>
  <!-- Content: (xsl:sort | xsl:with-param)* -->
</ft:apply-templates>

This is just like , except that you can set the mode using an XPath expression which resolves to a string qhich must be a qname. This qname is then used to select the mode as described in section 5.7 of the XSLT spec.


<ft:write-file
  name = { string-expression }
  overwrite = { string expression }>
  <!-- Content: (ft:output, template) -->
</ft:write-file>

This redirects a portion of the output to a file. The attribute is interpreted as an attribute value template. The string resulting from the AVT is the name of the output file. The attribute is interpreted as an attribute value template. If the resulting string is "yes", then the file is overwritten, otherwise the output is appended to the file, if it exists.

The body of the element is a template, with all output generated by this templatemredirected to the file. The template may have embedded one or more elements as immediate children of . ft:output are empty elements with the same range of attributes as and the same semantics and defaulting for each attribute. All elements are combined, and the output parameters determined by each attribute is applied to the redirect file.

For example, this means that a 4XSLT transform can use the XML output method, but it can redirect sub-sections of its output to separate files using the HTML method for redirected output.


<ft:message-output
  file = { string-expression }
  overwrite = { string-expression }
  disable = { string-expression } />

ft:message-output allows redirection of messages generated by xsl:message instructions to a file. The attribute is interpreted as an attribute value template. The string resulting from the AVT is the name of the output file. The attribute is interpreted as an attribute value template. If the resulting string is "yes", then the file is overwritten, otherwise the output is appended to the file, if it exists. The attribute is interpreted as an attribute value template. If the resulting string is "yes", then output from is disabled altogether.

User-Defined Extension Elements

To define your own extension element, define an element derived from xml.xslt.XsltElement. The module in which it is defined must have global dictionary named "ExtElements" mapping element qualified names to element class objects. The element qnames are in the form of a tuple of two strings, the first being the namespace URI for the element, and the second being the local name. The namespace URI must be a valid, identifying (but not necessarily addressable) URI, and in particular, it cannot be an empty string.

Finally, modules containing any extension elements used must be indicated as such to the processor in one of two ways. (1) They are listed in the environment variable "EXTMODULES". "EXTMODULES" is a colon-separated list of modules. (2) They are registered with the processor using the registerExtensionModule() method, which takes a list of module names. In either case, all extension modules must should be in the "PYTHONPATH". Note that extension modules will automatically be searched for XPath extension functions as well as Extension elements.

For example:


#extelement.py

import string, os
import xml.dom.ext
from xml.xslt import XsltElement, XSL_NAMESPACE, AttributeValueTemplate

class SystemElement(XsltElement):
    def __init__(self, doc, uri='http://foo.org/namespaces/ext-xslt', localName='system', prefix='xsl', baseUri=''):
        XsltElement.__init__(self, doc, uri, localName, prefix, baseUri)

    def setup(self):
        self.__dict__['_nss'] = xml.dom.ext.GetAllNs(self)
        self.__dict__['_command'] = AttributeValueTemplate.AttributeValueTemplate(self.getAttributeNS('', 'command'))
        return

    def instantiate(self, context, processor):
        origState = context.copy()
        context.setNamespaces(self._nss)
        command = self._command.evaluate(context)
        os.system(command)
        context.set(origState)
        return (context,)

ExtElements = {
    ('http://foo.org/namespaces/ext-xslt', 'system'): SystemElement
    }


#useext.py

sheet = """<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:ext="http://foo.org/namespaces/ext-xslt"
  extension-element-prefixes="ext"
  version="1.0">

  <xsl:template match="execute-command">
    <ext:system command="{@cmd}"/>
  </xsl:template>

</xsl:stylesheet>
"""

source = """<execute-command cmd="dir"/>"""

from xml.xslt import Processor
processor = Processor.Processor()
processor.registerExtensionModules(['extelement'])
processor.appendStylesheetString(sheet)
result = processor.runString(source, ignorePis=1)
print result

This example is somewhat involved, and shows how to allow an extension element use attribute value templates. If you don't need AVTs, you can just use an attribute's value directly.

Note the call to

registerExtensionModules
in useext. This can be omitted if "extelement" (the module name where the extension element is defined) is in the EXTMODULES environment variable. This call should precede the appending of any stylesheet that uses the extension elements.

Note that 4XSLT supports fallback through the standard XSLT fallback mechanism. It also supports the element-available extension function.

Extension Element API

Context

Most likely, the processing you'll do in extension code will reference the current XSLT context, which is passed into the instantiate method of all XSLT elements. This class is defined at xml.xslt.XsltContext.

As mentioned, XSLT Extension Elements should be derived from xml.xslt.XsltElement (or at least follow its protocol).

Module xml.xslt

Module Summary

Classes

Class Summary
XsltElement  

 

Class XsltElement

Method Summary
__init__ Called as the stylesheet is being built. The DOM tree structure is not guarenteed to be set up in the initializer, so be careful of using node operations on self. 
setup Called after the stylesheet DOM structure has been set up, but before the processor has begun a run on any XML source. All node operations on self should have the expected result. 
instantiate  

 

Method Details

__init__

__init__(doc, uri, localName, prefix)
      

Called as the stylesheet is being built. The DOM tree structure is not guarenteed to be set up in the initializer, so be careful of using node operations on self.

Parameters
doc of type xml.dom.Document.Document

The stylesheet document node

uri of type xml.dom.Document.Document

The element namespace URI

localName of type xml.dom.Document.Document

The local element node name

prefix of type xml.dom.Document.Document

The namespace prefix from the element qualified name

Return Value
None


setup

setup()
      

Called after the stylesheet DOM structure has been set up, but before the processor has begun a run on any XML source. All node operations on self should have the expected result.

Parameters
None
Return Value
None


instantiate

instantiate(context, processor)
      

Parameters
context of type xml.xslt.XsltContext

The current context, not yet updated with the namespace nodes defined on self.

processor of type xml.xslt.Processor.Processor

The processor instance, used for output handler calls.

Return Value
tuple with the passed-on context as the first entry

This tuple is typically processed by the parent element. The only requirement is that the first argument be an XsltContext object, which can be the same as was passed in unless your element is intended to change any data in the context. Other items can be added to the tuple as needed to return data.