[Lxml-checkins] r46504 - in lxml/branch/lxml-1.3: . src/lxml src/lxml/tests

scoder at codespeak.net scoder at codespeak.net
Wed Sep 12 15:25:31 CEST 2007


Author: scoder
Date: Wed Sep 12 15:25:31 2007
New Revision: 46504

Modified:
   lxml/branch/lxml-1.3/CHANGES.txt
   lxml/branch/lxml-1.3/src/lxml/proxy.pxi
   lxml/branch/lxml-1.3/src/lxml/serializer.pxi
   lxml/branch/lxml-1.3/src/lxml/tests/test_elementtree.py
Log:
merged in namespace serialisation fix from trunk

Modified: lxml/branch/lxml-1.3/CHANGES.txt
==============================================================================
--- lxml/branch/lxml-1.3/CHANGES.txt	(original)
+++ lxml/branch/lxml-1.3/CHANGES.txt	Wed Sep 12 15:25:31 2007
@@ -2,6 +2,19 @@
 lxml changelog
 ==============
 
+Under development
+=================
+
+Features added
+--------------
+
+Bugs fixed
+----------
+
+* lxml failed to serialise namespace declarations of elements other than the
+  root node of a tree
+
+
 1.3.4 (2007-08-30)
 ==================
 

Modified: lxml/branch/lxml-1.3/src/lxml/proxy.pxi
==============================================================================
--- lxml/branch/lxml-1.3/src/lxml/proxy.pxi	(original)
+++ lxml/branch/lxml-1.3/src/lxml/proxy.pxi	Wed Sep 12 15:25:31 2007
@@ -97,26 +97,6 @@
         c_root.children = c_root.last = NULL
         tree.xmlFreeDoc(c_doc)
 
-cdef void _copyParentNamespaces(xmlNode* c_from_node, xmlNode* c_to_node):
-    """Copy the namespaces of all ancestors of c_from_node to c_to_node.
-
-    This is used in _fakeRootDoc() to avoid loosing namespace declarations.
-    """
-    cdef xmlNode* c_parent
-    cdef xmlNs* c_ns
-    cdef xmlNs* c_new_ns
-    cdef int prefix_known
-    c_parent = c_from_node.parent
-    while c_parent is not NULL and tree._isElementOrXInclude(c_parent):
-        c_new_ns = c_parent.nsDef
-        while c_new_ns is not NULL:
-            # check if prefix is already defined
-            c_ns = tree.xmlSearchNs(c_to_node.doc, c_to_node, c_new_ns.prefix)
-            if c_ns is NULL:
-                tree.xmlNewNs(c_to_node, c_new_ns.href, c_new_ns.prefix)
-            c_new_ns = c_new_ns.next
-        c_parent = c_parent.parent
-
 ################################################################################
 # support for freeing tree elements when proxy objects are destroyed
 
@@ -177,6 +157,25 @@
 ################################################################################
 # fix _Document references and namespaces when a node changes documents
 
+cdef void _copyParentNamespaces(xmlNode* c_from_node, xmlNode* c_to_node):
+    """Copy the namespaces of all ancestors of c_from_node to c_to_node.
+    """
+    cdef xmlNode* c_parent
+    cdef xmlNs* c_ns
+    cdef xmlNs* c_new_ns
+    cdef int prefix_known
+    c_parent = c_from_node.parent
+    while c_parent is not NULL and (tree._isElementOrXInclude(c_parent) or
+                                    c_parent.type == tree.XML_DOCUMENT_NODE):
+        c_new_ns = c_parent.nsDef
+        while c_new_ns is not NULL:
+            # check if prefix is already defined
+            c_ns = tree.xmlSearchNs(c_to_node.doc, c_to_node, c_new_ns.prefix)
+            if c_ns is NULL:
+                tree.xmlNewNs(c_to_node, c_new_ns.href, c_new_ns.prefix)
+            c_new_ns = c_new_ns.next
+        c_parent = c_parent.parent
+
 cdef void moveNodeToDocument(_Document doc, xmlNode* c_element):
     """Fix the xmlNs pointers of a node and its subtree that were moved.
 

Modified: lxml/branch/lxml-1.3/src/lxml/serializer.pxi
==============================================================================
--- lxml/branch/lxml-1.3/src/lxml/serializer.pxi	(original)
+++ lxml/branch/lxml-1.3/src/lxml/serializer.pxi	Wed Sep 12 15:25:31 2007
@@ -79,14 +79,37 @@
                              int write_complete_document,
                              int pretty_print):
     cdef xmlDoc* c_doc
+    cdef xmlNode* c_nsdecl_node
     c_doc = c_node.doc
     if write_xml_declaration:
         _writeDeclarationToBuffer(c_buffer, c_doc.version, encoding)
 
+    # write internal DTD subset, preceding PIs/comments, etc.
     if write_complete_document:
         _writeDtdToBuffer(c_buffer, c_doc, c_node.name, encoding)
         _writePrevSiblings(c_buffer, c_node, encoding, pretty_print)
-    tree.xmlNodeDumpOutput(c_buffer, c_doc, c_node, 0, pretty_print, encoding)
+
+    c_nsdecl_node = c_node
+    if c_node.parent is NULL or c_node.parent.type != tree.XML_DOCUMENT_NODE:
+        # copy the node and add namespaces from parents
+        # this is required to make libxml write them
+        c_nsdecl_node = tree.xmlCopyNode(c_node, 2)
+        _copyParentNamespaces(c_node, c_nsdecl_node)
+
+        c_nsdecl_node.parent = c_node.parent
+        c_nsdecl_node.children = c_node.children
+        c_nsdecl_node.last = c_node.last
+
+    # write node
+    tree.xmlNodeDumpOutput(c_buffer, c_doc, c_nsdecl_node, 0,
+                           pretty_print, encoding)
+
+    if c_nsdecl_node is not c_node:
+        # clean up
+        c_nsdecl_node.children = c_nsdecl_node.last = NULL
+        tree.xmlFreeNode(c_nsdecl_node)
+
+    # write tail, trailing comments, etc.
     _writeTail(c_buffer, c_node, encoding, pretty_print)
     if write_complete_document:
         _writeNextSiblings(c_buffer, c_node, encoding, pretty_print)

Modified: lxml/branch/lxml-1.3/src/lxml/tests/test_elementtree.py
==============================================================================
--- lxml/branch/lxml-1.3/src/lxml/tests/test_elementtree.py	(original)
+++ lxml/branch/lxml-1.3/src/lxml/tests/test_elementtree.py	Wed Sep 12 15:25:31 2007
@@ -1969,6 +1969,37 @@
         del one
         self.assertEquals('{http://a.b.c}baz', baz.tag)
 
+    def test_ns_decl(self):
+        tostring = self.etree.tostring
+        root = self.etree.XML(
+            '<foo><bar xmlns:ns="http://a.b.c"><ns:baz/></bar></foo>')
+        baz = root[0][0]
+
+        nsdecl = re.findall("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']",
+                            tostring(baz))
+        self.assertEquals(["http://a.b.c"], nsdecl)
+
+    def test_ns_decl_default(self):
+        tostring = self.etree.tostring
+        root = self.etree.XML(
+            '<foo><bar xmlns="http://a.b.c"><baz/></bar></foo>')
+        baz = root[0][0]
+
+        nsdecl = re.findall("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']",
+                            tostring(baz))
+        self.assertEquals(["http://a.b.c"], nsdecl)
+        
+    def test_ns_decl_root(self):
+        tostring = self.etree.tostring
+        root = self.etree.XML(
+            '<foo xmlns:ns="http://a.b.c"><bar><ns:baz/></bar></foo>')
+        baz = root[0][0]
+
+        nsdecl = re.findall("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']",
+                            tostring(baz))
+
+        self.assertEquals(["http://a.b.c"], nsdecl)
+
     def test_attribute_xmlns_move(self):
         Element = self.etree.Element
 


More information about the lxml-checkins mailing list