[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