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.
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
registerExtensionModulesin 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.
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 Summary
Class Summary | |
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__(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.
ParametersReturn Value
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
None
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.
ParametersNoneReturn ValueNone
instantiate(context, processor)
ParametersReturn Value
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.
- 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.