[Lxml-checkins] r33266 - in lxml/trunk: . src/lxml
scoder at codespeak.net
scoder at codespeak.net
Fri Oct 13 17:51:47 CEST 2006
Author: scoder
Date: Fri Oct 13 17:51:44 2006
New Revision: 33266
Modified:
lxml/trunk/CHANGES.txt
lxml/trunk/src/lxml/apihelpers.pxi
lxml/trunk/src/lxml/etree.pyx
lxml/trunk/src/lxml/etreepublic.pxd
lxml/trunk/src/lxml/parser.pxi
lxml/trunk/src/lxml/public-api.pxi
Log:
public C-API function makeElement() to create a new _Element with text, tail, attributes and namespaces
Modified: lxml/trunk/CHANGES.txt
==============================================================================
--- lxml/trunk/CHANGES.txt (original)
+++ lxml/trunk/CHANGES.txt Fri Oct 13 17:51:44 2006
@@ -8,6 +8,9 @@
Features added
--------------
+* New C-API function makeElement() to create new elements with text,
+ tail, attributes and namespaces
+
* Reuse original parser flags for XInclude
* Simplified support for handling XSLT processing instructions
Modified: lxml/trunk/src/lxml/apihelpers.pxi
==============================================================================
--- lxml/trunk/src/lxml/apihelpers.pxi (original)
+++ lxml/trunk/src/lxml/apihelpers.pxi Fri Oct 13 17:51:44 2006
@@ -81,8 +81,10 @@
return None
cdef _Element _makeElement(tag, xmlDoc* c_doc, _Document doc,
- _BaseParser parser, attrib, nsmap, extra_attrs):
- """Create a new element and initialize namespaces and attributes.
+ _BaseParser parser, text, tail, attrib, nsmap,
+ extra_attrs):
+ """Create a new element and initialize text content, namespaces and
+ attributes.
This helper function will reuse as much of the existing document as
possible:
@@ -102,13 +104,52 @@
elif c_doc is NULL:
c_doc = _newDoc()
c_node = _createElement(c_doc, name_utf)
- if doc is None:
- tree.xmlDocSetRootElement(c_doc, c_node)
- doc = _documentFactory(c_doc, parser)
- # add namespaces to node if necessary
- doc._setNodeNamespaces(c_node, ns_utf, nsmap)
- _initNodeAttributes(c_node, doc, attrib, extra_attrs)
- return _elementFactory(doc, c_node)
+ try:
+ if text is not None:
+ _setNodeText(c_node, text)
+ if tail is not None:
+ _setTailText(c_node, tail)
+ if doc is None:
+ tree.xmlDocSetRootElement(c_doc, c_node)
+ doc = _documentFactory(c_doc, parser)
+ # add namespaces to node if necessary
+ doc._setNodeNamespaces(c_node, ns_utf, nsmap)
+ _initNodeAttributes(c_node, doc, attrib, extra_attrs)
+ return _elementFactory(doc, c_node)
+ except:
+ # free allocated c_node/c_doc unless Python does it for us
+ if c_node.doc is not c_doc:
+ # node not yet in document => will not be freed by document
+ if tail is not None:
+ _removeText(c_node.next) # tail
+ tree.xmlFreeNode(c_node)
+ if doc is None:
+ # c_doc will not be freed by doc
+ tree.xmlFreeDoc(c_doc)
+ raise
+
+cdef _initNodeAttributes(xmlNode* c_node, _Document doc, attrib, extra):
+ """Initialise the attributes of an element node.
+ """
+ cdef xmlNs* c_ns
+ # 'extra' is not checked here (expected to be a keyword dict)
+ if attrib is not None and not hasattr(attrib, 'items'):
+ raise TypeError, "Invalid attribute dictionary: %s" % type(attrib)
+ if extra is not None and extra:
+ if attrib is None:
+ attrib = extra
+ else:
+ attrib.update(extra)
+ if attrib:
+ for name, value in attrib.items():
+ attr_ns_utf, attr_name_utf = _getNsTag(name)
+ value_utf = _utf8(value)
+ if attr_ns_utf is None:
+ tree.xmlNewProp(c_node, _cstr(attr_name_utf), _cstr(value_utf))
+ else:
+ c_ns = doc._findOrBuildNodeNs(c_node, _cstr(attr_ns_utf))
+ tree.xmlNewNsProp(c_node, c_ns,
+ _cstr(attr_name_utf), _cstr(value_utf))
cdef object _attributeValue(xmlNode* c_element, xmlAttr* c_attrib_node):
cdef char* value
Modified: lxml/trunk/src/lxml/etree.pyx
==============================================================================
--- lxml/trunk/src/lxml/etree.pyx (original)
+++ lxml/trunk/src/lxml/etree.pyx Fri Oct 13 17:51:44 2006
@@ -1153,7 +1153,8 @@
def makeelement(self, _tag, attrib=None, nsmap=None, **_extra):
"""Creates a new element associated with the same document.
"""
- return _makeElement(_tag, NULL, self._doc, None, attrib, nsmap, _extra)
+ return _makeElement(_tag, NULL, self._doc, None, None, None,
+ attrib, nsmap, _extra)
def find(self, path):
"""Finds the first matching subelement, by tag name or path.
@@ -1565,35 +1566,15 @@
c_node = tree.xmlNewDocPI(c_doc, target, text)
return c_node
-cdef _initNodeAttributes(xmlNode* c_node, _Document doc, attrib, extra):
- cdef xmlNs* c_ns
- # 'extra' is not checked here (expected to be a keyword dict)
- if attrib is not None and not hasattr(attrib, 'items'):
- raise TypeError, "Invalid attribute dictionary: %s" % type(attrib)
- if extra:
- if attrib is None:
- attrib = extra
- else:
- attrib.update(extra)
- if attrib:
- for name, value in attrib.items():
- attr_ns_utf, attr_name_utf = _getNsTag(name)
- value_utf = _utf8(value)
- if attr_ns_utf is None:
- tree.xmlNewProp(c_node, _cstr(attr_name_utf), _cstr(value_utf))
- else:
- c_ns = doc._findOrBuildNodeNs(c_node, _cstr(attr_ns_utf))
- tree.xmlNewNsProp(c_node, c_ns,
- _cstr(attr_name_utf), _cstr(value_utf))
-
-
# module-level API for ElementTree
def Element(_tag, attrib=None, nsmap=None, **_extra):
- """Element factory. This function returns an object implementing the Element interface.
+ """Element factory. This function returns an object implementing the
+ Element interface.
"""
### also look at _Element.makeelement() and _BaseParser.makeelement() ###
- return _makeElement(_tag, NULL, None, None, attrib, nsmap, _extra)
+ return _makeElement(_tag, NULL, None, None, None, None,
+ attrib, nsmap, _extra)
def Comment(text=None):
"""Comment element factory. This factory function creates a special element that will
Modified: lxml/trunk/src/lxml/etreepublic.pxd
==============================================================================
--- lxml/trunk/src/lxml/etreepublic.pxd (original)
+++ lxml/trunk/src/lxml/etreepublic.pxd Fri Oct 13 17:51:44 2006
@@ -61,7 +61,12 @@
# create an ElementTree subclass for an Element
cdef _ElementTree newElementTree(_NodeBase context_node, object subclass)
- # deep copy a node to include in in the Document
+ # create a new Element for an existing or new document (doc = None)
+ # builds Python object after setting text, tail, namespaces and attributes
+ cdef _Element makeElement(tag, _Document doc, parser,
+ text, tail, attrib, nsmap)
+
+ # deep copy a node to include it in the Document
cdef _Element deepcopyNodeToDocument(_Document doc, tree.xmlNode* c_root)
# set the internal lookup function for Element/Comment/PI classes
Modified: lxml/trunk/src/lxml/parser.pxi
==============================================================================
--- lxml/trunk/src/lxml/parser.pxi (original)
+++ lxml/trunk/src/lxml/parser.pxi Fri Oct 13 17:51:44 2006
@@ -420,7 +420,8 @@
def makeelement(self, _tag, attrib=None, nsmap=None, **_extra):
"""Creates a new element associated with this parser.
"""
- return _makeElement(_tag, NULL, None, self, attrib, nsmap, _extra)
+ return _makeElement(_tag, NULL, None, self, None, None,
+ attrib, nsmap, _extra)
cdef xmlDoc* _parseUnicodeDoc(self, utext, char* c_filename) except NULL:
"""Parse unicode document, share dictionary if possible.
Modified: lxml/trunk/src/lxml/public-api.pxi
==============================================================================
--- lxml/trunk/src/lxml/public-api.pxi (original)
+++ lxml/trunk/src/lxml/public-api.pxi Fri Oct 13 17:51:44 2006
@@ -21,6 +21,10 @@
raise TypeError
return _elementFactory(doc, c_node)
+cdef public _Element makeElement(tag, _Document doc, parser,
+ text, tail, attrib, nsmap):
+ return _makeElement(tag, NULL, doc, parser, text, tail, attrib, nsmap, None)
+
cdef public void setElementClassLookupFunction(
_element_class_lookup_function function, state):
_setElementClassLookupFunction(function, state)
More information about the lxml-checkins
mailing list