summaryrefslogtreecommitdiff
path: root/src/lxml
diff options
context:
space:
mode:
authorOlli Pottonen <olli.pottonen@iki.fi>2015-02-18 16:53:41 +1000
committerOlli Pottonen <olli.pottonen@iki.fi>2015-02-18 16:51:43 +1000
commitfdd2f237fb1945fde323b9e8987d7c28a769a4d0 (patch)
tree12d59cd52fff0d3e2d108807fd6e20f68e7d4df0 /src/lxml
parent6095a09e3f9d8e44d111c36aa813aea23885ec9a (diff)
downloadpython-lxml-fdd2f237fb1945fde323b9e8987d7c28a769a4d0.tar.gz
Make _ElementTree.deepcopy() properly handle comments/PI's before doctype.
Diffstat (limited to 'src/lxml')
-rw-r--r--src/lxml/apihelpers.pxi18
-rw-r--r--src/lxml/lxml.etree.pyx6
-rw-r--r--src/lxml/tests/test_etree.py11
3 files changed, 24 insertions, 11 deletions
diff --git a/src/lxml/apihelpers.pxi b/src/lxml/apihelpers.pxi
index 0492b0be..c529384a 100644
--- a/src/lxml/apihelpers.pxi
+++ b/src/lxml/apihelpers.pxi
@@ -1069,13 +1069,21 @@ cdef int _copyNonElementSiblings(xmlNode* c_node, xmlNode* c_target) except -1:
cdef xmlNode* c_copy
cdef xmlNode* c_sibling = c_node
while c_sibling.prev != NULL and \
- (c_sibling.prev.type == tree.XML_PI_NODE or \
- c_sibling.prev.type == tree.XML_COMMENT_NODE):
+ (c_sibling.prev.type == tree.XML_PI_NODE or
+ c_sibling.prev.type == tree.XML_COMMENT_NODE or
+ c_sibling.prev.type == tree.XML_DTD_NODE):
c_sibling = c_sibling.prev
while c_sibling != c_node:
- c_copy = tree.xmlDocCopyNode(c_sibling, c_target.doc, 1)
- if c_copy is NULL:
- raise MemoryError()
+ if c_sibling.type == tree.XML_DTD_NODE:
+ c_copy = <xmlNode*>_copyDtd(<tree.xmlDtd*>c_sibling)
+ if c_sibling == <xmlNode*>c_node.doc.intSubset:
+ c_target.doc.intSubset = <tree.xmlDtd*>c_copy
+ else: # c_sibling == c_node.doc.extSubset
+ c_target.doc.extSubset = <tree.xmlDtd*>c_copy
+ else:
+ c_copy = tree.xmlDocCopyNode(c_sibling, c_target.doc, 1)
+ if c_copy is NULL:
+ raise MemoryError()
tree.xmlAddPrevSibling(c_target, c_copy)
c_sibling = c_sibling.next
while c_sibling.next != NULL and \
diff --git a/src/lxml/lxml.etree.pyx b/src/lxml/lxml.etree.pyx
index d5f43f67..74e7e93a 100644
--- a/src/lxml/lxml.etree.pyx
+++ b/src/lxml/lxml.etree.pyx
@@ -1903,12 +1903,6 @@ cdef public class _ElementTree [ type LxmlElementTreeType,
assert root is not None
_assertValidNode(root)
_copyNonElementSiblings(self._context_node._c_node, root._c_node)
- doc = root._doc
- c_doc = self._context_node._doc._c_doc
- if c_doc.intSubset is not NULL and doc._c_doc.intSubset is NULL:
- doc._c_doc.intSubset = _copyDtd(c_doc.intSubset)
- if c_doc.extSubset is not NULL and not doc._c_doc.extSubset is NULL:
- doc._c_doc.extSubset = _copyDtd(c_doc.extSubset)
return _elementTreeFactory(None, root)
elif self._doc is not None:
_assertValidDoc(self._doc)
diff --git a/src/lxml/tests/test_etree.py b/src/lxml/tests/test_etree.py
index 25ad998b..8131881e 100644
--- a/src/lxml/tests/test_etree.py
+++ b/src/lxml/tests/test_etree.py
@@ -576,6 +576,17 @@ class ETreeOnlyTestCase(HelperTestCase):
self.assertEqual(_bytes("<test/>"),
tostring(root2))
+ def test_deepcopy_pi_dtd(self):
+ XML = self.etree.XML
+ tostring = self.etree.tostring
+ xml = _bytes('<!-- comment --><!DOCTYPE test [\n<!ENTITY entity "tasty">\n]>\n<test/>')
+ root = XML(xml)
+ tree1 = self.etree.ElementTree(root)
+ self.assertEqual(xml, tostring(tree1))
+
+ tree2 = copy.deepcopy(tree1)
+ self.assertEqual(xml, tostring(tree2))
+
def test_parse_remove_comments(self):
fromstring = self.etree.fromstring
tostring = self.etree.tostring