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

scoder at codespeak.net scoder at codespeak.net
Wed Sep 12 14:56:03 CEST 2007


Author: scoder
Date: Wed Sep 12 14:56:01 2007
New Revision: 46501

Modified:
   lxml/trunk/CHANGES.txt
   lxml/trunk/src/lxml/proxy.pxi
   lxml/trunk/src/lxml/serializer.pxi
Log:
work around libxml2's failure to serialise namespace declarations

Modified: lxml/trunk/CHANGES.txt
==============================================================================
--- lxml/trunk/CHANGES.txt	(original)
+++ lxml/trunk/CHANGES.txt	Wed Sep 12 14:56:01 2007
@@ -17,6 +17,9 @@
 Bugs fixed
 ----------
 
+* lxml failed to serialise namespace declarations of elements other than the
+  root node of a tree
+
 * Race condition in XSLT where the resolver context leaked between concurrent
   XSLT calls
 

Modified: lxml/trunk/src/lxml/proxy.pxi
==============================================================================
--- lxml/trunk/src/lxml/proxy.pxi	(original)
+++ lxml/trunk/src/lxml/proxy.pxi	Wed Sep 12 14:56:01 2007
@@ -102,26 +102,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
 
@@ -182,6 +162,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/trunk/src/lxml/serializer.pxi
==============================================================================
--- lxml/trunk/src/lxml/serializer.pxi	(original)
+++ lxml/trunk/src/lxml/serializer.pxi	Wed Sep 12 14:56:01 2007
@@ -79,14 +79,33 @@
                              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)
+
+    # copy the node and add namespaces from parents 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)
+
+    # 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)


More information about the lxml-checkins mailing list