<divclass="focus">Historically, defining Python expressions with pod was done via text inserted in 'track changes' mode (with LibreOffice, in the Edit menu, enable/disable this mode by clicking on Modifications->Record). This page still shows examples with track-changed text, although conditional fields (as explained <ahref="pod.html">here</a>) have become the preferred way to insert Python expressions.</div>
<h1><aname="fromClause"></a>Inserting arbitrary content: the <spanclass="code">from</span> clause</h1>
<p>In the section <ahref="podWritingTemplates.html">"Writing templates"</a>, you've learned how to write pod statements (<spanclass="code">if</span>, <spanclass="code">for</span>). Every pod statement is linked to a given part of the pod template (a text paragraph, a title, a table, a table row, etc) and conditions how this part is rendered in the result (the <spanclass="code">if</span> statement, for example, renders the part only if the related condition is <spanclass="code">True</span>). This way to work has its limits. Indeed, you can't insert what you want into the result: you are forced to use the part of the document that is the target of the statement. Of course, in this part, you can still write funny things like Python expressions and statements, but it may not be sufficient.</p>
<p>This is why a special <spanclass="code">from</span> clause may be added to every pod statement. A statement containing such a clause will replace the content of the targeted document part by the result of the <spanclass="code">from</span> clause. This clause must specify a Python expression that must produce a valid chunk of ODT content.</p>
<p>In the example below, the statement has a <spanclass="code">from</span> clause that produces a simple paragraph containing 'Hello'.</p>
<p>In the result, the targeted paragraph has been replaced by the chunk of odt content specified in the <spanclass="code">from</span> expression. Note that the <spanclass="code">from</span> clause MUST start on a new line in the note. Else, it will be considered as part of statement and will probably produce an error.</p>
<p>Surprise! This statement is neither a 'if' not a 'for' statement... It is a "null" statement whose sole objective is to replace the target by the content of the <spanclass="code">from</span> expression. But you can also add <spanclass="code">from</span> clauses to 'if' and 'for' statements. Here is an example with a 'for' statement.</p>
<p>Here's the result. Note that within the <spanclass="code">from</span> clause you may use the iterator variable (<spanclass="code">i</span>, in this case) defined by the <spanclass="code">for</span> statement.</p>
<p>Actually, when you don't specify a <spanclass="code">from</span> clause in a statement, pod generates an implicit <spanclass="code">from</span> clause whose result comes from the odt chunk that is the target of the statement.</p>
<p>I agree with you: these examples are not very useful. Moreover, it requires you to have some knowledge of the ODF syntax. You also have to take care about the namespaces you specify (text:, style:, fo:, etc): they must match the ones used in your pod template. But these examples illustrate how <spanclass="code">from</span> clauses work and how you may go further by yourself if pod does not implement (yet ;-)) what you need.</p>
<p>The remaining of this page presents much more useful use cases, in the form of built-in pod functions that you may use within <spanclass="code">from</span> clauses. Indeed, a bunch of functions is inserted by default to every context given to the pod renderer.</p>
<h1><aname="xhtml"></a>Managing XHTML input: the <spanclass="code">xhtml</span> function</h1>
<p>One of these functions is the <spanclass="code">xhtml</span> function, that allows to convert chunks of XHTML documents (given as strings in the context) into chunks of OpenDocument within the resulting OpenDocument. This functionality is useful, for example, when using pod with systems like Plone, that maintain a part of their data in XHTML format (Kupu fields, for example).</p>
<p>Suppose you want to render this chunk of XHTML code at some place in your pod result:</p>
<p>In this example, the name <spanclass="code">dummy</span> is available in the context, and <spanclass="code">dummy.getAt1()</span> produces a Python string that contains the XHTML chunk shown above. This string is given as paremeter of the built-in pod <spanclass="code">xhtml</span> function.</p>
<p>Note that if you specify a key "xhtml" in the context given to the pod renderer, the default "xhtml" function will be overridden by the value specified in the context.</p>
<p>The OpenDocument rendering is a bit different than the XHTML rendering shown above. This is because pod uses the styles found in the pod template and tries to make a correspondence between style information in the XHTML chunk and styles present in the pod template. By default, when pod encounters a XHTML element:</p>
<ul>
<li>it checks if a "class" attribute is defined on this element. If yes, and if a style with the same "display name" is found in the OpenDocument template, this style will be used. The "display name" of an OpenDocument style is the name of the style as it appears in OpenOffice, for example;</li>
<li>if no "class" attribute is present, and if the XHTML element is a heading (h1 to h6), pod tries to find an OpenDocument style which has the same "outline level". For example, "h1" may be mapped to "Heading 1". This is what happened in the example above;
</li>
<li>else, no style at all is applied.
</li>
</ul>
<p>You have the possibility to customize this behaviour by defining styles mappings (see below).</p>
<h2>Defining styles mappings</h2>
<p>You can define styles mappings at two different levels. First, when you create a renderer instance, you may give a styles mapping to the parameter <spanclass="code">stylesMapping</span>, which is the <i>global style mapping</i> (The renderer's constructor is defined <ahref="podRenderingTemplates.html">here</a>). A styles mapping is a Python dictionary whose keys are either CSS class names or XHTML element names, and whose values are "display names" of OpenDocument styles that must be present in the pod template. Every time you invoke the <spanclass="code">xhtml</span> function in a pod template, the global styles mapping comes into play.</p>
<p>Note that in an OpenDocument document, OpenOffice stores only the styles that are used in the document (I don't know how others OpenDocument-compliant word processors behave). The styles names ("Heading 1", "Standard"...) that appear when opening your template with OpenOffice, for example, are thus a super-set of the styles that are really recorded into your document. You may consult the list of available styles in your pod template programmatically by calling your pod renderer's <spanclass="code">getStyles</span> method.</p>
<p>In a styles mapping you can also define a special key, <spanclass="code">h*</span>, and define a positive or negative integer as value. When pod tries to establish a style correspondance based on outline level, it will use this number. For example, if you specify a styles mapping = <spanclass="code">{'h*' : -1}</span>, when encountering element <spanclass="code">h2</span> (that does not define a "class" attribute), if an OpenDocument with an outlevel of 2-1 is found (ie "Heading 1"), it will be used.</p>
<p>Second, each time you invoke the <spanclass="code">xhtml</span> function in a pod template, you may specify a local styles mapping in the parameter named <spanclass="code">stylesMapping</span>, like shown below.</p>
<p>Local styles mappings override what you have (potentially) defined in the global styles mapping.</p>
<p>At present, the XHTML elements listed below may not be "styled-mapped" (they may not be present in styles mappings) because pod uses it own automatically-generated OpenDocument styles:</p>
<ul>
<liclass="code">ol</li>
<liclass="code">ul</li>
<liclass="code">li</li>
<liclass="code">a</li>
</ul>
<p>This can be problematic if, for instance, you want to use special style-related attributes, specially for <spanclass="code">li</span> elements that correspond to paragraphs. This is why any pod template includes some predefined styles that may apply to these elements. The following table shows them, grouped by element type.</p>
<td>No pod-specific style is proposed at present. The unique default pod style of this element will always be used.</td>
</tr>
<tr>
<tdclass="code">ul</td>
<td>The default pod style only.</td>
<td>No pod-specific style is proposed at present. The unique default pod style of this element will always be used.</td>
</tr>
<tr>
<tdclass="code">li</td>
<td>podItemKeepWithNext</td>
<td>This specific style adds the characteristic "Keep with next" to the target <spanclass="code">li</span> paragraph. This way, the paragraph will always be present. This works for <spanclass="code">li</span>s inside <spanclass="code">ul</span>s or <spanclass="code">ol</span>s.</td>
</tr>
<tr>
<tdclass="code">a</td>
<td>The default pod style only.</td>
<td>No pod-specific style is proposed at present. The unique default pod style of this element will be used.</td>
<p>In order to use one of those styles, you can specify its name in the "class" attribute of the target element, or you can go through a global or local styles mapping. For example, if you need a <spanclass="code">li</span> element that will always stay on the same page as the paragraph below him, you can write <spanclass="code"><li class="podItemKeepWithNext"></li></span>.</p>
<h2>Managing XHTML entities</h2>
<p>By default, the <spanclass="code">xhtml</span> function uses a standard XML parser (the Python "expatreader" parser) for parsing the XHTML code. This parser knows only about the 5 legal XML entities: <spanclass="code">&amp;</span> (&), <spanclass="code">&quote;</span> ("), <spanclass="code">&apos;</span> ('), <spanclass="code">&lt;</span> (<) and <spanclass="code">&gt;</span> (>). If an XHTML entity is encountered (like <spanclass="code">&eacute;</span>), the XML parser produces an error (numeric entities like <spanclass="code">&#234</span>; seem to be supported). For solving this problem, pod may use another parser that comes with PyXML and resides in <spanclass="code">xml.sax.drivers2</span>. If this parser is available in your Python interpreter, pod will use it and configure it: XHTML entities will then be supported and correctly converted. Type <spanclass="code"><b>import</b> xml.sax.drivers2</span> in your Python shell; if no exception is raised, the parser is installed and will be used by pod.</p>
<h1><aname="document"></a>Integrating external files or images into the result: the <spanclass="code">document</span> function</h1>
<p>The <spanclass="code">document</span> function allows you to integrate, into the ODT result, images or files that come from external sources. Here is the function signature; the table below explains each parameter. Examples follow.</p>
<td>If you have the image or file content available in memory or via a file handler, use this parameter. <spanclass="code">content</span> may hold the whole (binary) image or file content, or be an (opened) Python <spanclass="code">file</span> instance (a Python <spanclass="code">file</span> instance is obtained by calling the built-in Python method <spanclass="code">file</span> or <spanclass="code">open</span> (<spanclass="code">open</span> being an alias for <spanclass="code">file</span>).</td>
</tr>
<tr>
<tdclass="code">at</td>
<td>If your image or file is available on disk, do not use the previous parameter and specify the file path in this parameter.</td>
</tr>
<tr>
<tdclass="code">format</td>
<td>When using parameter <spanclass="code">at</span>, pod guesses the file format based on file extension. But if you use parameter <spanclass="code">content</span>, you must specify the file format here. The format may be a file extension (without the leading dot) or a MIME type. The currently supported formats are:<br/><br/>
<table>
<tr>
<th>Parameter value</th>
<th>Description</th>
</tr>
<tr>
<td><spanclass="code">odt</span> or <spanclass="code">application/vnd.oasis.opendocument.text</span> </td>
<td>An OpenDocument Text document.</td>
</tr>
<tr>
<td><spanclass="code">pdf</span> or <spanclass="code">application/pdf</span></td>
<td>Adobe PDF document. Note that pod needs Ghostscript installed for integrating PDFs into a pod result. It means that the program <spanclass="code">gs</span> must be installed and available in the path. pod integrates a PDF file into the ODT result like this: (1) pod calls gs to split the PDF into images (one image per page); (2) pod uses internally function <spanclass="code">document</span> to integrate every image into the pod result.</td>
</tr>
<tr>
<td><spanclass="code">png</span> or <spanclass="code">image/png</span></td>
<td>An image in PNG format.</td>
</tr>
<tr>
<td><spanclass="code">jpeg</span>, <spanclass="code">jpg</span> or <spanclass="code">image/jpeg</span></td>
<td>An image in JPEG format.</td>
</tr>
<tr>
<td><spanclass="code">gif</span> or <spanclass="code">image/gif</span></td>
<td>An image in GIF format.</td>
</tr>
</table>
</td>
</tr>
<tr>
<tdclass="code">anchor</td>
<td>This parameter is used for images only. It determines the way to anchor the image in the result. Possible values are:<br/><br/>
<p>For those who know Plone, <spanclass="code">annex</span> is an instance of <spanclass="code">ATFile</span>: <spanclass="code">annex.data</span> returns its binary content, while <spanclass="code">annex.getContentType()</span> returns is MIME type.</p>
<p>In future Appy releases:</p>
<ul>
<li>more formats will be supported (mainly, the Microsoft formats: doc, xls, etc);</li>
<li>more "protocols" will be supported for accessing the external file or image (HTTP, FTP, etc);</li>
<li>images or documents referenced in XHTML code that is imported through function <spanclass="code">xhtml</span> will be integrated into the POD result.</li>
</ul>
<h1><aname="notInExpressions"></a>Do not use built-in pod functions in pod expressions !</h1>
<p>Pod built-in functions are designed to be used within pod statements (<spanclass="code">from</span> clauses). If you try to use them in pod expressions, you will get strange results. The example below uses the <spanclass="code">xhtml</span> function in a pod expression.</p>
<p>If <spanclass="code">dummy.getAt1()</span> produces the XHTML chunk <spanclass="code"><p>Test1<br/></p></span>, the result will look like this:</p>