[XML-SIG] pydom
Greg Stein
gstein@lyra.org
Thu, 08 Oct 1998 23:55:17 -0700
This is a multi-part message in MIME format.
--------------77A2CB87277BD0D1105FC50E
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Jeff.Johnson@stn.siemens.com wrote:
>
> I use pyhtml.py, which uses pydom, to create my HTML elements because it
> saves lots of lines of code. It may not be quite so readable but I don't
> think it's that bad. In fact, I think it's more readable than having to
> read the 10 lines of code resulting from using core.py. I also miss the
> ability to specify the attribute names and values in the core
> createElement().
>
> Consider the following using pyhtml.py:
>
> html =
> HTML(HEAD(TITLE(self.title)),BODY(list,BACKGROUND=self.background))
>
> Now using core.py (maybe there is a much easier way to do this with
> core.py?):
> ... lengthy example elided ...
I saw this and got to thinking about some text (XML/HTML) generation. I
looked at pyhtml.py and saw that it only encoded a specific subset of
available tags. "There has got to be a clean way to have an open-ended
system," I thought :-)
[ I'm not familiar with HTMLgen, but I'm copying Robin in case he finds
this interesting... (and his xml-sig delivery is disabled for some
reason) ]
Anyhow, I've attached a quick pass at some code to do (XML) generation.
The above example would be written like this:
import xmlgen
f = xmlgen.Factory()
html = f.html[f.head.title(self.title),
f.body(background=self.background)[list]]
The text is retrieved using str(html).
There are two ways to create an element:
- via the factory "f". f.foo creates and returns a <foo> element
- via another element. elem.foo creates, and inserts into a self, a
<foo> element
Given an element, you can insert 0 or more items of CDATA into it:
elem('piece 1', 'piece 2')
Usually used as: elem.subelem('cdata') or as: f.elem('cdata')
Given an element, you can insert attributes into it:
elem(attr1='value 1', attr2='value 2')
Again, usually used when creating them: elem.subelem(attr1='value1')
Given a number of elements, you can insert 1 or more elements as
children of another using index notation:
elem1[elem2, elem3, elem4]
Finally, when creating a child element, the return value can create a
nested child element:
elem.subelem.subsubelem
In this last form, the return value is tricky. If you str() it, then you
get "elem" and its children. Otherwise, it acts like the "subsubelem" --
elem creation, insertion, and CDATA/attribute will operate on
subsubelem. This allows you to do things like:
body =
f.body(bgcolor='#ffffff').p.a(href='foo.html').img(src='image.gif')
html = f.html[f.head.title('title'), body]
Some relatively simple rules, some funky code, and hopefully a clear
result for assembling text. Comments welcome :-)
Cheers,
-g
--
Greg Stein (gstein@lyra.org)
--------------77A2CB87277BD0D1105FC50E
Content-Type: text/plain; charset=us-ascii; name="xmlgen.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="xmlgen.py"
#
# XML generation module
#
import string
class Element:
def __init__(self, name, *cdata, **attrs):
self.__name = name
self.__children = []
self.__cdata = cdata
self.__attrs = attrs
def __getattr__(self, name):
if name[:2] == '__':
raise AttributeError, name
child = Element(name)
self.__children.append(child)
return Intermediate(self, child)
def __call__(self, *cdata, **attrs):
self.__cdata = self.__cdata + cdata
self.__attrs.update(attrs)
return self
def __getitem__(self, items):
if type(items) == type(()) or type(items) == type([]):
self.__children = self.__children + list(items)
else:
self.__children.append(items)
return self
def __str__(self):
s = '<' + self.__name
for name, value in self.__attrs.items():
s = s + ' ' + name + '="' + str(value) + '"'
if self.__cdata or self.__children:
s = s + '>' + string.joinfields(self.__cdata, '')
for child in self.__children:
s = s + str(child)
s = s + '</' + self.__name + '>'
else:
s = s + '/>'
return s
class Factory:
def __getattr__(self, name):
if name[:2] == '__':
raise AttributeError, name
return Element(name)
class Intermediate:
def __init__(self, parent, child):
self.__parent = parent
self.__child = child
def __getattr__(self, name):
inter = getattr(self.__child, name)
return Intermediate(self.__parent, inter.__child)
def __call__(self, *cdata, **attrs):
apply(self.__child, cdata, attrs)
return self
def __getitem__(self, items):
self.__child[items]
return self
def __str__(self):
return str(self.__parent)
def test():
f = Factory()
l = f.ul[f.li('list 1'), f.li('list 2'), f.li('list 3')]
l[f.li('list 4')]
top = f.html[f.head.title.i('title'), f.body(bgcolor='#ffffff')[f.h1('heading'),f.p('text'),l]]
print top
--------------77A2CB87277BD0D1105FC50E--