XSLTools

Annotated XSLOutput.py

3:e96db0ca6952
2004-12-20 paulb [project @ 2004-12-20 18:55:20 by paulb] Fixed module docstring. Added a parameter so that values which are lists of actual values may be handled. Exposed instance creation as a "public" method.
paulb@1 1
#!/usr/bin/env python
paulb@1 2
paulb@1 3
"""
paulb@1 4
XSL output classes and functions.
paulb@1 5
"""
paulb@1 6
paulb@1 7
# NOTE: Make this use other implementations, too.
paulb@1 8
paulb@1 9
import libxslt
paulb@1 10
import libxml2dom
paulb@1 11
paulb@1 12
class OutputError(Exception):
paulb@1 13
    pass
paulb@1 14
paulb@1 15
class Processor:
paulb@1 16
paulb@1 17
    """
paulb@1 18
    A handler which can prepare output for an XMLTools2 template.
paulb@1 19
    """
paulb@1 20
paulb@1 21
    def __init__(self, filenames, references=None):
paulb@1 22
paulb@1 23
        """
paulb@1 24
        Initialise the handler with the 'filenames' of stylesheets producing the
paulb@1 25
        final output, a 'references' dictionary indicating related stylesheets.
paulb@1 26
        """
paulb@1 27
paulb@1 28
        self.references = references or {}
paulb@1 29
paulb@1 30
        # Remember the stylesheet documents.
paulb@1 31
paulb@1 32
        self.stylesheets = []
paulb@1 33
        for filename in filenames:
paulb@1 34
            self.stylesheets.append(libxslt.parseStylesheetFile(filename))
paulb@1 35
paulb@1 36
    def __del__(self):
paulb@1 37
paulb@1 38
        """
paulb@1 39
        Tidy up the stylesheet documents.
paulb@1 40
        """
paulb@1 41
paulb@1 42
        for stylesheet in self.stylesheets:
paulb@1 43
            stylesheet.freeStylesheet()
paulb@1 44
paulb@1 45
    def send_output(self, stream, encoding, document):
paulb@1 46
paulb@1 47
        """
paulb@1 48
        Send output to the given 'stream' using the given output encoding for
paulb@1 49
        the given 'document'.
paulb@1 50
        """
paulb@1 51
paulb@1 52
        result = self._get_result(document)
paulb@1 53
paulb@1 54
        if result is not None:
paulb@1 55
            # Since result is a native node, use the serialize method.
paulb@1 56
            stream.write(result.serialize(encoding))
paulb@1 57
            result.freeDoc()
paulb@1 58
        else:
paulb@1 59
            raise OutputError, "Transformation failed."
paulb@1 60
paulb@1 61
    def get_result(self, document):
paulb@1 62
paulb@1 63
        """
paulb@1 64
        Return a transformed document produced from the object's stylesheets and
paulb@1 65
        the given 'document'.
paulb@1 66
        """
paulb@1 67
paulb@1 68
        result = self._get_result(document)
paulb@1 69
paulb@1 70
        if result is not None:
paulb@1 71
            return libxml2dom.Node(result)
paulb@1 72
        else:
paulb@1 73
            raise OutputError, "Transformation failed."
paulb@1 74
paulb@1 75
    def _get_result(self, document):
paulb@1 76
paulb@1 77
        """
paulb@1 78
        Return a transformation of the given 'document'.
paulb@1 79
        """
paulb@1 80
paulb@1 81
        if hasattr(document, "as_native_node"):
paulb@1 82
            document = document.as_native_node()
paulb@1 83
paulb@1 84
        # Transform the localised instance into the final output.
paulb@1 85
paulb@1 86
        parameters = {}
paulb@1 87
        for name, reference in self.references.items():
paulb@1 88
            parameters[name.encode("utf-8")] = ("document('%s')" % reference).encode("utf-8")
paulb@1 89
paulb@1 90
        last_result = document
paulb@1 91
        for stylesheet in self.stylesheets:
paulb@1 92
            result = stylesheet.applyStylesheet(last_result, parameters)
paulb@1 93
            if last_result is not None:
paulb@1 94
                if last_result != document:
paulb@1 95
                    last_result.freeDoc()
paulb@1 96
                last_result = result
paulb@1 97
            else:
paulb@1 98
                raise OutputError, "Transformation failed."
paulb@1 99
paulb@1 100
        return result
paulb@1 101
paulb@1 102
# vim: tabstop=4 expandtab shiftwidth=4