emitting HTML and XML in Python
kragen at dnaco.net
Tue Sep 26 23:12:00 CEST 2000
Hoping this little module will be useful to someone else:
# Define a little bit of XHTML-compatible XML tag syntax for Python.
# See the test() definition at the bottom for some example usage.
# I wrote this because John Klassa complained that he couldn't find an
# equivalent to CGI.pm in Python, just "a small module that'll grab
# CGI parameters for you, and then another huge one that very clumsily
# lets you emit HTML." So here's a tiny module that very agilely
# lets you emit HTML. :)
# I hereby disclaim any copyright interest in this work, my intent in
# so doing being to thereby put it in the public domain.
# Kragen Sitaker, 2000-09-26
# turn a dictionary into a string formatted with HTML/XML attribute syntax
# XXX: doesn't turn embedded quotes in values into entities
# (" or whatever) and likewise doesn't turn <>& into their
# equivalent entities. You have to do that yourself. Also won't check
# to see if you're passing it keys that aren't valid XML attribute names.
rv = ""
for key in args.keys(): rv = rv + (' %s="%s"' % (key, args[key]))
# Somewhat misnamed; put the end on a tag, given that its content is 'text'.
# Empty tags (e.g. <br />) are specified with content of None; tags with no
# content (which are equivalent from XML's point of view, but not from the
# point of view of existing HTML parsers) are specified with content of ''.
# Empty tags (e.g. <br />) have a space inserted before the slash to keep
# most HTML parsers happily ignorant of the complexities of XML.
def closetag(tagname, text):
if text is None: return ' />'
else: return ">%s</%s>" % (text, tagname)
# Call this to emit a tag with specified content and attributes.
# Doesn't encode what you pass to it in any way; do that yourself if
# you need it.
# We have to create a class rather than using a lambda so that we can
# have both keyword arguments and data from the creation context.
def __init__(self, tagname): self.tagname = tagname
def __call__(self, text=None, **args):
return ("<" + self.tagname + attributes(args) +
# Convenience class so you can say Xml().foo instead of Tag("foo").
class Xml: def __getattr__(self, name): return Tag(name)
# Convenience instance so you can say xml.foo instead of Xml().foo
xml = Xml()
# Declare an exception to signal test failure.
TestFailure = "test failure"
def stringtest(expected, got):
if expected != got: raise TestFailure, "%s != %s" % (expected, got)
# Example usage; if this routine doesn't throw an exception, it presumably
# means that this module works.
stringtest(xml.br(), '<br />')
stringtest(xml.img(src="about:logo"), '<img src="about:logo" />')
<kragen at pobox.com> Kragen Sitaker <http://www.pobox.com/~kragen/>
Perilous to all of us are the devices of an art deeper than we ourselves
-- Gandalf the Grey [J.R.R. Tolkien, "Lord of the Rings"]
More information about the Python-list