5.1 Simple Renderer Example

It is possible to write a renderer with just a couple of methods: default and textDefault. The code below demonstrates how one might create a generic XML renderer that simply uses the node names as XML tag names. The text node renderer escapes the <, >, and & characters.

import string
from plasTeX.Renderers import Renderer

class Renderer(Renderer):
    
    def default(self, node):
        """ Rendering method for all non-text nodes """
        s = []

        # Handle characters like \&, \$, \%, etc.
        if len(node.nodeName) == 1 and node.nodeName not in string.letters:
            return self.textDefault(node.nodeName)

        # Start tag
        s.append('<%s>' % node.nodeName)

        # See if we have any attributes to render
        if node.hasAttributes():
            s.append('<attributes>')
            for key, value in node.attributes.items():
                # If the key is 'self', don't render it
                # these nodes are the same as the child nodes
                if key == 'self':
                    continue
                s.append('<%s>%s</%s>' % (key, unicode(value), key))
            s.append('</attributes>')

        # Invoke rendering on child nodes
        s.append(unicode(node))

        # End tag
        s.append('</%s>' % node.nodeName)

        return u'\n'.join(s)

    def textDefault(self, node):
        """ Rendering method for all text nodes """
        return node.replace('&','&amp;').replace('<','&lt;').replace('>','&gt;')

To use the renderer, simply parse a LaTeX document and apply the renderer using the render method.

# Import renderer from previous code sample
from MyRenderer import Renderer

from plasTeX.TeX import TeX

# Instantiate a TeX processor and parse the input text
tex = TeX()
tex.ownerDocument.config['files']['split-level'] = -100
tex.ownerDocument.config['files']['filename'] = 'test.xml'
tex.input(r'''
\documentclass{book}
\begin{document}

Previous paragraph.

\section{My Section}

\begin{center}
Centered text with <, >, and \& charaters.
\end{center}

Next paragraph.

\end{document}
''')
document = tex.parse()

# Render the document
renderer = Renderer()
renderer.render(document)

The output from the renderer, located in ‘test.xml’, looks like the following.

<document>
<par>
Previous paragraph.
</par><section>
    <attributes>
        <toc>None</toc>
        <*modifier*>None</*modifier*>
        <title>My Section</title>
    </attributes>
<par>
<center>
 Centered text with &lt;, &gt;, and &amp; charaters.
</center>
</par><par>
Next paragraph.
</par>
</section>
</document>