14. Реализация etbuilder¶
Вот авторский модуль etbuilder.py с описанием.
14.1. Особенности, отличные от оригинала Лунда¶
Версия автора отличается от версии Лунда в этом отношении:
- Для этого требуется пакет lxml. Версия Lundh не использовала lxml; он использует cElementTree или elementtree, если первый недоступен.
- Для этого требуется Python 2.5 или новее. Версия Lundh будет работать с более ранними версиями, возможно, вернется, по крайней мере, к 2.2.
- Версия автора также допускает значения int в вызове экземпляра E.
14.2. Пролог¶
Модуль начинается с комментария, указывающего на эту документацию, и подтверждения работы Фредрика Лунда.
"""etbuilder.py: An element builder for lxml.etree
================================================================
$Revision: 1.55 $ $Date: 2012/08/11 21:44:19 $
================================================================
For documentation, see:
http://www.nmt.edu/tcc/help/pubs/pylxml/
Borrows heavily from the work of Fredrik Lundh; see:
http://effbot.org/zone/
"""
et в модуле lxml.etree.
#================================================================
# Imports
#----------------------------------------------------------------
from lxml import etree as et
Функция functools.partial() используется для выполнения вызова функции в разделе 14.11, «ElementMaker .__ getattr __ (): обрабатывать вызовы произвольных методов».
Однако модуль functools является новым в Python 2.5. Чтобы этот модуль работал в установке Python 2.4, мы ожидаем возможного отказа от импорта functools, предоставляя эту функциональность с помощью функции partial() substitute. Эта функция украдена непосредственно из справочника библиотеки Python.
try:
from functools import partial
except ImportError:
def partial(func, *args, **keywords):
def newfunc(*fargs, **fkeywords):
newkeywords = keywords.copy()
newkeywords.update(fkeywords)
return func(*(args + fargs), **newkeywords)
newfunc.func = func
newfunc.args = args
newfunc.keywords = keywords
return newfunc
14.3. CLASS(): вспомогательная функция для добавления атрибутов класса CSS¶
Далее идет определение вспомогательной функции CLASS(), обсуждаемой в разделе 13.2, «CLASS (): добавление атрибутов класса».
# - - - C L A S S
def CLASS(*names):
'''Helper function for adding 'class=...' attributes to tags.
[ names is a list of strings ->
return a dictionary with one key 'class' and the related
value the concatenation of (names) with one space between
them ]
'''
return {'class': ' '.join(names)}
14.4. FOR(): вспомогательная функция для добавления XHTML для атрибутов¶
# - - - F O R
def FOR(id):
'''Helper function for adding 'for=ID' attributes to tags.
'''
return {'for': id}
14.5. subElement(): добавить дочерний элемент¶
См. Раздел 13.4. subElement(): добавление дочернего элемента
# - - - s u b E l e m e n t
def subElement(parent, child):
'''Add a child node to the parent and return the child.
[ (parent is an Element) and
(child is an Element with no parent) ->
parent := parent with child added as its new last child
return child ]
'''
#-- 1 --
parent.append(child)
#-- 2 --
return child
14.6. addText(): добавление текстового содержимого в элемент¶
См. Раздел 13.5. addText(): добавление текстового содержимого в элемент. Чтобы упростить работу вызывающего, мы ничего не делаем, если s равно None, как это может быть в случае с атрибутом .text или .tail для элемента et.Element.
# - - - a d d T e x t
def addText(node, s):
'''Add text content to an element.
[ (node is an Element) and (s is a string) ->
if node has any children ->
last child's .tail +:= s
else ->
node.text +:= s ]
'''
#-- 1 --
if not s:
return
#-- 2 --
if len(node) == 0:
node.text = (node.text or "") + s
else:
lastChild = node[-1]
lastChild.tail = (lastChild.tail or "") + s
14.7. class ElementMaker: The factory class¶
# - - - - - c l a s s E l e m e n t M a k e r
class ElementMaker(object):
'''ElementTree element factory class
Exports:
ElementMaker(typeMap=None):
[ (typeMap is an optional dictionary whose keys are
type objects T, and each corresponding value is a
function with calling sequence
f(elt, item)
and generic intended function
[ (elt is an et.Element) and
(item has type T) ->
elt := elt with item added ]) ->
return a new ElementMaker instance that has
calling sequence
E(*p, **kw)
and intended function
[ p[0] exists and is a str ->
return a new et.Element instance whose name
is p[0], and remaining elements of p become
string content of that element (for types
str, unicode, and int) or attributes (for
type dict, and members of kw) or children
(for type et.Element), plus additional
handling from typeMap if it is provided ]
and allows arbitrary method calls of the form
E.tag(*p, **kw)
with intended function
[ return a new et.Element instance whose name
is (tag), and elements of p and kw have
the same effects as E(*(p[1:]), **kw) ]
'''