[Lxml-checkins] r54340 - in lxml/trunk: . src/lxml

scoder at codespeak.net scoder at codespeak.net
Fri May 2 19:14:58 CEST 2008


Author: scoder
Date: Fri May  2 19:14:57 2008
New Revision: 54340

Modified:
   lxml/trunk/   (props changed)
   lxml/trunk/src/lxml/apihelpers.pxi
   lxml/trunk/src/lxml/lxml.etree.pyx
   lxml/trunk/src/lxml/proxy.pxi
   lxml/trunk/src/lxml/tree.pxd
Log:
 r4119 at delle:  sbehnel | 2008-05-02 18:10:34 +0200
 re-assign all node name pointers from the target dictionary when moving an element to a new tree of a different thread


Modified: lxml/trunk/src/lxml/apihelpers.pxi
==============================================================================
--- lxml/trunk/src/lxml/apihelpers.pxi	(original)
+++ lxml/trunk/src/lxml/apihelpers.pxi	Fri May  2 19:14:57 2008
@@ -716,7 +716,7 @@
     _moveTail(c_next, c_node)
     if not attemptDeallocation(c_node):
         # make namespaces absolute
-        moveNodeToDocument(doc, c_node)
+        moveNodeToDocument(doc, c_node.doc, c_node)
     return 0
 
 cdef void _moveTail(xmlNode* c_tail, xmlNode* c_target):
@@ -782,6 +782,7 @@
     """
     cdef xmlNode* c_orig_neighbour
     cdef xmlNode* c_next
+    cdef xmlDoc*  c_source_doc
     cdef _Element element
     cdef Py_ssize_t seqlength, i, c
     cdef _node_to_node_function next_element
@@ -864,12 +865,13 @@
         for element in elements:
             assert element is not None, "Node must not be None"
             # move element and tail over
+            c_source_doc = element._c_node.doc
             c_next = element._c_node.next
             tree.xmlAddPrevSibling(c_node, element._c_node)
             _moveTail(c_next, element._c_node)
 
             # integrate element into new document
-            moveNodeToDocument(parent._doc, element._c_node)
+            moveNodeToDocument(parent._doc, c_source_doc, element._c_node)
 
             # stop at the end of the slice
             if slicelength > 0:
@@ -899,7 +901,9 @@
     """
     cdef xmlNode* c_next
     cdef xmlNode* c_node
+    cdef xmlDoc* c_source_doc
     c_node = child._c_node
+    c_source_doc = c_node.doc
     # store possible text node
     c_next = c_node.next
     # move node itself
@@ -908,7 +912,7 @@
     _moveTail(c_next, c_node)
     # uh oh, elements may be pointing to different doc when
     # parent element has moved; change them too..
-    moveNodeToDocument(parent._doc, c_node)
+    moveNodeToDocument(parent._doc, c_source_doc, c_node)
 
 cdef int _prependChild(_Element parent, _Element child) except -1:
     """Prepend a new child to a parent element.
@@ -916,7 +920,9 @@
     cdef xmlNode* c_next
     cdef xmlNode* c_child
     cdef xmlNode* c_node
+    cdef xmlDoc* c_source_doc
     c_node = child._c_node
+    c_source_doc = c_node.doc
     # store possible text node
     c_next = c_node.next
     # move node itself
@@ -929,14 +935,16 @@
     _moveTail(c_next, c_node)
     # uh oh, elements may be pointing to different doc when
     # parent element has moved; change them too..
-    moveNodeToDocument(parent._doc, c_node)
+    moveNodeToDocument(parent._doc, c_source_doc, c_node)
 
 cdef int _appendSibling(_Element element, _Element sibling) except -1:
     """Append a new child to a parent element.
     """
     cdef xmlNode* c_next
     cdef xmlNode* c_node
+    cdef xmlDoc* c_source_doc
     c_node = sibling._c_node
+    c_source_doc = c_node.doc
     # store possible text node
     c_next = c_node.next
     # move node itself
@@ -944,14 +952,16 @@
     _moveTail(c_next, c_node)
     # uh oh, elements may be pointing to different doc when
     # parent element has moved; change them too..
-    moveNodeToDocument(element._doc, c_node)
+    moveNodeToDocument(element._doc, c_source_doc, c_node)
 
 cdef int _prependSibling(_Element element, _Element sibling) except -1:
     """Append a new child to a parent element.
     """
     cdef xmlNode* c_next
     cdef xmlNode* c_node
+    cdef xmlDoc* c_source_doc
     c_node = sibling._c_node
+    c_source_doc = c_node.doc
     # store possible text node
     c_next = c_node.next
     # move node itself
@@ -959,7 +969,7 @@
     _moveTail(c_next, c_node)
     # uh oh, elements may be pointing to different doc when
     # parent element has moved; change them too..
-    moveNodeToDocument(element._doc, c_node)
+    moveNodeToDocument(element._doc, c_source_doc, c_node)
 
 cdef inline int isutf8(char* s):
     cdef char c

Modified: lxml/trunk/src/lxml/lxml.etree.pyx
==============================================================================
--- lxml/trunk/src/lxml/lxml.etree.pyx	(original)
+++ lxml/trunk/src/lxml/lxml.etree.pyx	Fri May  2 19:14:57 2008
@@ -533,6 +533,7 @@
         """
         cdef xmlNode* c_node
         cdef xmlNode* c_next
+        cdef xmlDoc* c_source_doc
         cdef _Element element
         cdef bint left_to_right
         cdef Py_ssize_t slicelength, step
@@ -554,13 +555,14 @@
             c_node = _findChild(self._c_node, x)
             if c_node is NULL:
                 raise IndexError, "list index out of range"
+            c_source_doc = element._c_node.doc
             c_next = element._c_node.next
             _removeText(c_node.next)
             tree.xmlReplaceNode(c_node, element._c_node)
             _moveTail(c_next, element._c_node)
-            moveNodeToDocument(self._doc, element._c_node)
+            moveNodeToDocument(self._doc, c_source_doc, element._c_node)
             if not attemptDeallocation(c_node):
-                moveNodeToDocument(self._doc, c_node)
+                moveNodeToDocument(self._doc, c_node.doc, c_node)
 
     def __delitem__(self, x):
         """__delitem__(self, x)
@@ -707,14 +709,16 @@
         """
         cdef xmlNode* c_node
         cdef xmlNode* c_next
+        cdef xmlDoc* c_source_doc
         c_node = _findChild(self._c_node, index)
         if c_node is NULL:
             _appendChild(self, element)
             return
+        c_source_doc = c_node.doc
         c_next = element._c_node.next
         tree.xmlAddPrevSibling(c_node, element._c_node)
         _moveTail(c_next, element._c_node)
-        moveNodeToDocument(self._doc, element._c_node)
+        moveNodeToDocument(self._doc, c_source_doc, element._c_node)
 
     def remove(self, _Element element not None):
         """remove(self, element)
@@ -732,7 +736,7 @@
         tree.xmlUnlinkNode(c_node)
         _moveTail(c_next, c_node)
         # fix namespace declarations
-        moveNodeToDocument(self._doc, c_node)
+        moveNodeToDocument(self._doc, c_node.doc, c_node)
 
     def replace(self, _Element old_element not None,
                 _Element new_element not None):
@@ -744,18 +748,20 @@
         cdef xmlNode* c_old_next
         cdef xmlNode* c_new_node
         cdef xmlNode* c_new_next
+        cdef xmlDoc* c_source_doc
         c_old_node = old_element._c_node
         if c_old_node.parent is not self._c_node:
             raise ValueError, "Element is not a child of this node."
         c_old_next = c_old_node.next
         c_new_node = new_element._c_node
         c_new_next = c_new_node.next
+        c_source_doc = c_new_next.doc
         tree.xmlReplaceNode(c_old_node, c_new_node)
         _moveTail(c_new_next, c_new_node)
         _moveTail(c_old_next, c_old_node)
-        moveNodeToDocument(self._doc, c_new_node)
+        moveNodeToDocument(self._doc, c_source_doc, c_new_node)
         # fix namespace declarations
-        moveNodeToDocument(self._doc, c_old_node)
+        moveNodeToDocument(self._doc, c_old_node.doc, c_old_node)
         
     # PROPERTIES
     property tag:

Modified: lxml/trunk/src/lxml/proxy.pxi
==============================================================================
--- lxml/trunk/src/lxml/proxy.pxi	(original)
+++ lxml/trunk/src/lxml/proxy.pxi	Fri May  2 19:14:57 2008
@@ -276,7 +276,8 @@
             c_nsdef[0] = c_ns_next
     return 0
 
-cdef int moveNodeToDocument(_Document doc, xmlNode* c_element) except -1:
+cdef int moveNodeToDocument(_Document doc, xmlDoc* c_source_doc,
+                            xmlNode* c_element) except -1:
     """Fix the xmlNs pointers of a node and its subtree that were moved.
 
     Mainly copied from libxml2's xmlReconciliateNs().  Expects libxml2 doc
@@ -293,7 +294,11 @@
        prefix).  If a namespace is unknown, declare a new one on the
        node.
 
-    3) Set the Document reference to the new Document (if different).
+    3) Reassign the names of tags and attribute from the dict of the
+       target document *iff* it is different from the dict used in the
+       source subtree.
+
+    4) Set the Document reference to the new Document (if different).
        This is done on backtracking to keep the original Document
        alive as long as possible, until all its elements are updated.
 
@@ -303,16 +308,26 @@
     """
     cdef xmlNode* c_start_node
     cdef xmlNode* c_node
+    cdef char* c_name
     cdef _nscache c_ns_cache
     cdef xmlNs* c_ns
     cdef xmlNs* c_ns_next
     cdef xmlNs* c_nsdef
     cdef xmlNs* c_del_ns_list
     cdef cstd.size_t i
+    cdef tree.xmlDict* c_dict
 
     if not tree._isElementOrXInclude(c_element):
         return 0
 
+    # we need to copy the names of tags and attributes iff the element
+    # is based on a different libxml2 tag name dictionary
+    if doc._c_doc.dict is not c_source_doc.dict and \
+            doc._c_doc.dict is not NULL and c_source_doc.dict is not NULL:
+        c_dict = doc._c_doc.dict
+    else:
+        c_dict = NULL
+
     c_start_node = c_element
     c_del_ns_list = NULL
 
@@ -343,6 +358,13 @@
                         c_element, c_node.ns.href, c_node.ns.prefix)
                     _appendToNsCache(&c_ns_cache, c_node.ns, c_ns)
                     c_node.ns = c_ns
+
+            # 3) re-assign names from the target dict
+            if c_dict is not NULL:
+                c_name = tree.xmlDictLookup(c_dict, c_node.name, -1)
+                if c_name is not NULL:
+                    c_element.name = c_name
+
             if c_node is c_element:
                 # after the element, continue with its attributes
                 c_node = <xmlNode*>c_element.properties
@@ -358,7 +380,7 @@
         if c_node is NULL:
             # no children => back off and continue with siblings and parents
 
-            # 3) fix _Document reference (may dealloc the original document!)
+            # 4) fix _Document reference (may dealloc the original document!)
             if c_element._private is not NULL:
                 _updateProxyDocument(c_element, doc)
 
@@ -376,7 +398,7 @@
                 if c_element is NULL or not tree._isElementOrXInclude(c_element):
                     break
 
-                # 3) fix _Document reference (may dealloc the original document!)
+                # 4) fix _Document reference (may dealloc the original document!)
                 if c_element._private is not NULL:
                     _updateProxyDocument(c_element, doc)
 

Modified: lxml/trunk/src/lxml/tree.pxd
==============================================================================
--- lxml/trunk/src/lxml/tree.pxd	(original)
+++ lxml/trunk/src/lxml/tree.pxd	Fri May  2 19:14:57 2008
@@ -52,12 +52,12 @@
     void xmlHashScan(xmlHashTable* table, xmlHashScanner f, void* data) nogil
     void* xmlHashLookup(xmlHashTable* table, char* name) nogil
 
-cdef extern from "libxml/tree.h":
-
-    # for some reason need to define this in this section;
+cdef extern from *: # actually "libxml/dict.h"
     # libxml/dict.h appears to be broken to include in C
     ctypedef struct xmlDict
-    
+    cdef char* xmlDictLookup(xmlDict* dict, char* name, int len)
+
+cdef extern from "libxml/tree.h":
     ctypedef struct xmlDoc
     ctypedef struct xmlAttr
     ctypedef struct xmlNotationTable


More information about the lxml-checkins mailing list