Skip to main content

simple, elegant HTML, XHTML and XML generation

Project description

Simple, elegant HTML, XHTML and XML generation.

Constructing your HTML

To construct HTML start with an instance of html.HTML(). Add tags by accessing the tag’s attribute on that object. For example:

>>> from html import HTML
>>> h = HTML()
>>> h.p('Hello, world!')
>>> print(h)
<p>Hello, world!</p>

You may supply a tag name and some text contents when creating a HTML instance:

>>> h = HTML('html', 'text')
>>> print(h)
<html>text</html>

You may also append text content later using the tag’s .text() method or using augmented addition +=. Any HTML-specific characters (<>&") in the text will be escaped for HTML safety as appropriate unless escape=False is passed. Each of the following examples uses a new HTML instance:

>>> p = h.p('hello world!\n')
>>> p.br
>>> p.text('more &rarr; text', escape=False)
>>> p += ' ... augmented'
>>> h.p
>>> print(h)
<p>hello, world!<br>more &rarr; text ... augmented</p>
<p>

Note also that the top-level HTML object adds newlines between tags by default. Finally in the above you’ll see an empty paragraph tag - tags with no contents get no closing tag.

If the tag should have sub-tags you have two options. You may either add the sub-tags directly on the tag:

>>> l = h.ol
>>> l.li('item 1')
>>> l.li.b('item 2 > 1')
>>> print(h)
<ol>
<li>item 1</li>
<li><b>item 2 &gt; 1</b></li>
</ol>

Note that the default behavior with lists (and tables) is to add newlines between sub-tags to generate a nicer output. You can also see in that example the chaining of tags in l.li.b.

Tag attributes may be passed in as well:

>>> t = h.table(border='1')
>>> for i in range(2):
>>>   r = t.tr
>>>   r.td('column 1')
>>>   r.td('column 2')
>>> print(t)
<table border="1">
<tr><td>column 1</td><td>column 2</td></tr>
<tr><td>column 1</td><td>column 2</td></tr>
</table>

A variation on the above is to use a tag as a context variable. The following is functionally identical to the first list construction but with a slightly different sytax emphasising the HTML structure:

>>> with h.ol as l:
...   l.li('item 1')
...   l.li.b('item 2 > 1')

You may turn off/on adding newlines by passing newlines=False or True to the tag (or HTML instance) at creation time:

>>> l = h.ol(newlines=False)
>>> l.li('item 1')
>>> l.li('item 2')
>>> print(h)
<ol><li>item 1</li><li>item 2</li></ol>

Since we can’t use class as a keyword, the library recognises klass as a substitute:

>>> print(h.p(content, klass="styled"))
<p class="styled">content</p>

Unicode

HTML will work with either regular strings or unicode strings, but not both at the same time.

Obtain the final unicode string by calling unicode() on the HTML instance:

>>> h = HTML()
>>> h.p(u'Some Euro: €1.14')
>>> unicode(h)
u'<p>Some Euro: €1.14</p>'

If (under Python 2.x) you add non-unicode strings or attempt to get the resultant HTML source through any means other than unicode() then you will most likely get one of the following errors raised:

UnicodeDecodeError

Probably means you’ve added non-unicode strings to your HTML.

UnicodeEncodeError

Probably means you’re trying to get the resultant HTML using print or str() (or %s).

How generation works

The HTML document is generated when the HTML instance is “stringified”. This could be done either by invoking str() on it, or just printing it. It may also be returned directly as the “iterable content” from a WSGI app function.

You may also render any tag or sub-tag at any time by stringifying it.

Tags with no contents (either text or sub-tags) will have no closing tag. There is no “special list” of tags that must always have closing tags, so if you need to force a closing tag you’ll need to provide some content, even if it’s just a single space character.

Rendering doesn’t affect the HTML document’s state, so you can add to or otherwise manipulate the HTML after you’ve stringified it.

Creating XHTML

To construct XHTML start with an instance of html.XHTML() and use it as you would an HTML instance. Empty elements will now be rendered with the appropriate XHTML minimized tag syntax. For example:

>>> from html import XHTML
>>> h = XHTML()
>>> h.p
>>> h.br
>>> print(h)
<p></p>
<br />

Creating XML

A slight tweak to the html.XHTML() implementation allows us to generate arbitrary XML using html.XML():

>>> from html import XML
>>> h = XML('xml')
>>> h.p
>>> h.br('hi there')
>>> print(h)
<xml>
<p />
<br>hi there</br>
</xml>

Tags with difficult names

If your tag name isn’t a valid Python identifier name, or if it’s called “text” or “raw_text” you can add your tag slightly more manually:

>>> from html import XML
>>> h = XML('xml')
>>> h += XML('some-tag', 'some text')
>>> h += XML('text', 'some text')
>>> print(h)
<xml>
<some-tag>some text</some-tag>
<text>some text</text>
</xml>

Version History (in Brief)

  • 1.19 produce a universal wheel

  • 1.17 repackage it as “pml” since “html” clashes with the homonymous py3 stdlib module

  • 1.16 detect and raise a more useful error when some WSGI frameworks attempt to call HTML.read(). Also added ability to add new content using the += operator.

  • 1.15 fix Python 3 compatibility (unit tests)

  • 1.14 added plain XML support

  • 1.13 allow adding (X)HTML instances (tags) as new document content

  • 1.12 fix handling of XHTML empty tags when generating unicode output (thanks Carsten Eggers)

  • 1.11 remove setuptools dependency

  • 1.10 support plain ol’ distutils again

  • 1.9 added unicode support for Python 2.x

  • 1.8 added Python 3 compatibility

  • 1.7 added Python 2.5 compatibility and escape argument to tag construction

  • 1.6 added .raw_text() and and WSGI compatibility

  • 1.5 added XHTML support

  • 1.3 added more documentation, more tests

  • 1.2 added special-case klass / class attribute

  • 1.1 added escaping control

  • 1.0 was the initial release


This code is copyright 2009-2011 eKit.com Inc (http://www.ekit.com/) See the end of the source file for the license of use. XHTML support was contributed by Michael Haubenwallner.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

pml-1.21-py2.py3-none-any.whl (8.6 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file pml-1.21-py2.py3-none-any.whl.

File metadata

  • Download URL: pml-1.21-py2.py3-none-any.whl
  • Upload date:
  • Size: 8.6 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/42.0.2.post20191203 requests-toolbelt/0.9.1 tqdm/4.40.0 CPython/3.7.5

File hashes

Hashes for pml-1.21-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 ccce3a26c5279c07d4b1cd8fc79a8fdae17014e8de5d79d82e93efa678954eb0
MD5 166c0d8765605818ae0afd87ee74ab85
BLAKE2b-256 37b23059ef94702fc47b70aee69136cb9f6cd1093b595f272ce8c21fa39261e0

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page