[Lxml-checkins] r39387 - in lxml/trunk: . src/lxml
scoder at codespeak.net
scoder at codespeak.net
Sun Feb 25 14:59:32 CET 2007
Author: scoder
Date: Sun Feb 25 14:59:29 2007
New Revision: 39387
Added:
lxml/trunk/src/lxml/builder.py
lxml/trunk/src/lxml/htmlbuilder.py
Modified:
lxml/trunk/CHANGES.txt
Log:
integrated element generator factory by Fredrik Lundh
Modified: lxml/trunk/CHANGES.txt
==============================================================================
--- lxml/trunk/CHANGES.txt (original)
+++ lxml/trunk/CHANGES.txt Sun Feb 25 14:59:29 2007
@@ -8,6 +8,10 @@
Features added
--------------
+* HTML generator helpers by Fredrik Lundh in ``lxml.htmlbuilder``
+
+* ``ElementMaker`` XML generator by Fredrik Lundh in ``lxml.builder.E``
+
* Support for pickeling ``objectify.ObjectifiedElement`` objects to XML
* ``update()`` method on Element.attrib
Added: lxml/trunk/src/lxml/builder.py
==============================================================================
--- (empty file)
+++ lxml/trunk/src/lxml/builder.py Sun Feb 25 14:59:29 2007
@@ -0,0 +1,161 @@
+"""
+Element generator factory by Fredrik Lundh.
+
+Source:
+ http://online.effbot.org/2006_11_01_archive.htm#et-builder
+ http://effbot.python-hosting.com/file/stuff/sandbox/elementlib/builder.py
+"""
+
+import etree as ET
+
+try:
+ from functools import partial
+except ImportError:
+ # fake it for pre-2.5 releases
+ def partial(func, tag):
+ return lambda *args, **kwargs: func(tag, *args, **kwargs)
+
+
+class _C:
+ pass
+
+class ElementMaker(object):
+ """Element generator factory.
+
+ Unlike the ordinary Element factory, the E factory allows you to pass in
+ more than just a tag and some optional attributes; you can also pass in
+ text and other elements. The text is added as either text or tail
+ attributes, and elements are inserted at the right spot. Some small
+ examples::
+
+ >>> from lxml import etree as ET
+ >>> from lxml.builder import E
+
+ >>> ET.tostring(E("tag"))
+ '<tag/>'
+ >>> ET.tostring(E("tag", "text"))
+ '<tag>text</tag>'
+ >>> ET.tostring(E("tag", "text", key="value"))
+ '<tag key="value">text</tag>'
+ >>> ET.tostring(E("tag", E("subtag", "text"), "tail"))
+ '<tag><subtag>text</subtag>tail</tag>'
+
+ For simple tags, the factory also allows you to write ``E.tag(...)`` instead
+ of ``E('tag', ...)``::
+
+ >>> ET.tostring(E.tag())
+ '<tag/>'
+ >>> ET.tostring(E.tag("text"))
+ '<tag>text</tag>'
+ >>> ET.tostring(E.tag(E.subtag("text"), "tail"))
+ '<tag><subtag>text</subtag>tail</tag>'
+
+ Here's a somewhat larger example; this shows how to generate HTML
+ documents, using a mix of prepared factory functions for inline elements,
+ nested ``E.tag`` calls, and embedded XHTML fragments::
+
+ # some common inline elements
+ A = E.a
+ I = E.i
+ B = E.b
+
+ def CLASS(v):
+ # helper function, 'class' is a reserved word
+ return {'class': v}
+
+ page = (
+ E.html(
+ E.head(
+ E.title("This is a sample document")
+ ),
+ E.body(
+ E.h1("Hello!", CLASS("title")),
+ E.p("This is a paragraph with ", B("bold"), " text in it!"),
+ E.p("This is another paragraph, with a ",
+ A("link", href="http://www.python.org"), "."),
+ E.p("Here are some reservered characters: <spam&egg>."),
+ ET.XML("<p>And finally, here is an embedded XHTML fragment.</p>"),
+ )
+ )
+ )
+
+ print ET.tostring(page)
+
+ Here's a prettyprinted version of the output from the above script::
+
+ <html>
+ <head>
+ <title>This is a sample document</title>
+ </head>
+ <body>
+ <h1 class="title">Hello!</h1>
+ <p>This is a paragraph with <b>bold</b> text in it!</p>
+ <p>This is another paragraph, with <a href="http://www.python.org">link</a>.</p>
+ <p>Here are some reservered characters: <spam&egg>.</p>
+ <p>And finally, here is an embedded XHTML fragment.</p>
+ </body>
+ </html>
+ """
+
+ def __init__(self, typemap=None):
+ # initialize type map for this element factory
+
+ if typemap:
+ typemap = typemap.copy()
+ else:
+ typemap = {}
+
+ def add_text(elem, item):
+ if len(elem):
+ elem[-1].tail = (elem[-1].tail or "") + item
+ else:
+ elem.text = (elem.text or "") + item
+ typemap[str] = typemap[unicode] = add_text
+
+ def add_dict(elem, item):
+ attrib = elem.attrib
+ for k, v in item.items():
+ if isinstance(v, basestring):
+ attrib[k] = v
+ else:
+ attrib[k] = typemap[type(v)](None, v)
+ typemap[dict] = add_dict
+
+ def add_elem(elem, item):
+ elem.append(item)
+ t = type(ET.Element("tag"))
+ if t is not type(_C()):
+ typemap[t] = add_elem
+
+ self._typemap = typemap
+
+ # print typemap
+
+ def __call__(self, tag, *children, **attrib):
+ get = self._typemap.get
+
+ elem = ET.Element(tag)
+ if attrib:
+ get(dict)(elem, attrib)
+
+ for item in children:
+ if callable(item):
+ item = item()
+ t = get(type(item))
+ if t is None:
+ if ET.iselement(item):
+ elem.append(item)
+ continue
+ raise TypeError("bad argument type: %r" % item)
+ else:
+ v = t(elem, item)
+ if v:
+ get(type(v))(elem, v)
+
+ return elem
+
+ def __getattr__(self, tag):
+ return partial(self, tag)
+
+# create factory object
+E = ElementMaker()
Added: lxml/trunk/src/lxml/htmlbuilder.py
==============================================================================
--- (empty file)
+++ lxml/trunk/src/lxml/htmlbuilder.py Sun Feb 25 14:59:29 2007
@@ -0,0 +1,125 @@
+"""
+HTML specialisation of ``builder.py`` by Fredrik Lundh
+
+Usage::
+
+ >>> from lxml.htmlbuilder import *
+ >>> html = HTML(
+ ... HEAD( TITLE("Hello World") ),
+ ... BODY( CLASS("main"),
+ ... H1("Hello World !")
+ ... )
+ ... )
+
+ >>> import lxml.etree
+ >>> print lxml.etree.tostring(html, pretty_print=True)
+ <html>
+ <head>
+ <title>Hello World</title>
+ </head>
+ <body class="main">
+ <h1>Hello World !</h1>
+ </body>
+ </html>
+
+"""
+
+from builder import E
+
+# elements
+A = E.a # anchor
+ABBR = E.abbr # abbreviated form (e.g., WWW, HTTP, etc.)
+ACRONYM = E.acronym #
+ADDRESS = E.address # information on author
+APPLET = E.applet # Java applet (DEPRECATED)
+AREA = E.area # client-side image map area
+B = E.b # bold text style
+BASE = E.base # document base URI
+BASEFONT = E.basefont # base font size (DEPRECATED)
+BDO = E.bdo # I18N BiDi over-ride
+BIG = E.big # large text style
+BLOCKQUOTE = E.blockquote # long quotation
+BODY = E.body # document body
+BR = E.br # forced line break
+BUTTON = E.button # push button
+CAPTION = E.caption # table caption
+CENTER = E.center # shorthand for DIV align=center (DEPRECATED)
+CITE = E.cite # citation
+CODE = E.code # computer code fragment
+COL = E.col # table column
+COLGROUP = E.colgroup # table column group
+DD = E.dd # definition description
+DEL = getattr(E, 'del') # deleted text
+DFN = E.dfn # instance definition
+DIR = E.dir # directory list (DEPRECATED)
+DIV = E.div # generic language/style container
+DL = E.dl # definition list
+DT = E.dt # definition term
+EM = E.em # emphasis
+FIELDSET = E.fieldset # form control group
+FONT = E.font # local change to font (DEPRECATED)
+FORM = E.form # interactive form
+FRAME = E.frame # subwindow
+FRAMESET = E.frameset # window subdivision
+H1 = E.h1 # heading
+H2 = E.h2 # heading
+H3 = E.h3 # heading
+H4 = E.h4 # heading
+H5 = E.h5 # heading
+H6 = E.h6 # heading
+HEAD = E.head # document head
+HR = E.hr # horizontal rule
+HTML = E.html # document root element
+I = E.i # italic text style
+IFRAME = E.iframe # inline subwindow
+IMG = E.img # Embedded image
+INPUT = E.input # form control
+INS = E.ins # inserted text
+ISINDEX = E.isindex # single line prompt (DEPRECATED)
+KBD = E.kbd # text to be entered by the user
+LABEL = E.label # form field label text
+LEGEND = E.legend # fieldset legend
+LI = E.li # list item
+LINK = E.link # a media-independent link
+MAP = E.map # client-side image map
+MENU = E.menu # menu list (DEPRECATED)
+META = E.meta # generic metainformation
+NOFRAMES = E.noframes # alternate content container for non frame-based rendering
+NOSCRIPT = E.noscript # alternate content container for non script-based rendering
+OBJECT = E.object # generic embedded object
+OL = E.ol # ordered list
+OPTGROUP = E.optgroup # option group
+OPTION = E.option # selectable choice
+P = E.p # paragraph
+PARAM = E.param # named property value
+PRE = E.pre # preformatted text
+Q = E.q # short inline quotation
+S = E.s # strike-through text style (DEPRECATED)
+SAMP = E.samp # sample program output, scripts, etc.
+SCRIPT = E.script # script statements
+SELECT = E.select # option selector
+SMALL = E.small # small text style
+SPAN = E.span # generic language/style container
+STRIKE = E.strike # strike-through text (DEPRECATED)
+STRONG = E.strong # strong emphasis
+STYLE = E.style # style info
+SUB = E.sub # subscript
+SUP = E.sup # superscript
+TABLE = E.table #
+TBODY = E.tbody # table body
+TD = E.td # table data cell
+TEXTAREA = E.textarea # multi-line text field
+TFOOT = E.tfoot # table footer
+TH = E.th # table header cell
+THEAD = E.thead # table header
+TITLE = E.title # document title
+TR = E.tr # table row
+TT = E.tt # teletype or monospaced text style
+U = E.u # underlined text style (DEPRECATED)
+UL = E.ul # unordered list
+VAR = E.var # instance of a variable or program argument
+
+# attributes (only reserved words are included here)
+ATTR = dict
+def CLASS(v): return {'class': v}
+def FOR(v): return {'for': v}
More information about the lxml-checkins
mailing list