Search code examples
pythonlxmlkmlelementtreepykml

PyKML : appending a Placemark to more than one KML document


I am using PyKML to create several KML files and am running into some strange behavior that I hope someone can explain. The following reproduces the problem:

from lxml import etree
from pykml.factory import KML_ElementMaker as KML

doc1 = KML.kml(KML.Document())
doc2 = KML.kml(KML.Document())

p = KML.Placemark()

doc1.Document.append(p)
doc2.Document.append(p)

print etree.tostring(etree.ElementTree(doc1),pretty_print=True)
print etree.tostring(etree.ElementTree(doc2),pretty_print=True)

and here is the output :

<kml xmlns:gx="http://www.google.com/kml/ext/2.2"    xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://www.opengis.net/kml/2.2">
  <Document/>
</kml>

<kml xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://www.opengis.net/kml/2.2">
  <Document>
    <Placemark/>
  </Document>
</kml>

The place mark shows up in the second document, but not in the first. It is as if the Placemark can only be appended to one file at a time.

If I rearrange the last few lines as follows, things work.

doc1.Document.append(p)
print etree.tostring(etree.ElementTree(doc1),pretty_print=True)

doc2.Document.append(p)
print etree.tostring(etree.ElementTree(doc2),pretty_print=True)

and the output :

<kml xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://www.opengis.net/kml/2.2">
  <Document>
    <Placemark/>
  </Document>
</kml>

<kml xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://www.opengis.net/kml/2.2">
  <Document>
    <Placemark/>
  </Document>
</kml>

But this would require major restructuring of my code, which I am hoping to avoid.

I suspect I am missing something fundamental about how PyKML, lxml, elementtree or even Python works. Can someone please explain what might be happening here?


Solution

  • (partial answer - still hoping for an explanation!)

    If I do :

    from copy import deepcopy
    doc1.Document.append(deepcopy(p))
    doc2.Document.append(deepcopy(p))
    

    things work. But still, what is etree.tostring doing to the input objects doc1 and doc2? It is as if they are being altered somehow.