Skip to content

Commit

Permalink
Merge d3e85f3 into 3d9c9c3
Browse files Browse the repository at this point in the history
  • Loading branch information
Denis Krienbühl committed Aug 20, 2013
2 parents 3d9c9c3 + d3e85f3 commit 59b362a
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 3 deletions.
36 changes: 36 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
*.py[cod]

# C extensions
*.so

# Packages
*.egg
*.egg-info
dist
build
eggs
parts
bin
var
sdist
develop-eggs
.installed.cfg
lib
lib64
__pycache__

# Installer logs
pip-log.txt

# Unit test / coverage reports
.coverage
.tox
nosetests.xml

# Translations
*.mo

# Mr Developer
.mr.developer.cfg
.project
.pydevproject
5 changes: 5 additions & 0 deletions docs/HISTORY.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
Changelog
=========

0.4 (unreleased)
----------------

- adds the ability to add untyped extended data / named value pairs

0.3 (2012/11/15)
-----------------

Expand Down
88 changes: 86 additions & 2 deletions fastkml/kml.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,13 @@ class _Feature(_BaseObject):
# A given KML Feature can contain a combination of these types of
# custom data.
#
# (2) is already implemented, see UntypedExtendedData
#
# <Metadata> (deprecated in KML 2.2; use <ExtendedData> instead)
extended_data = None

def __init__(self, ns=None, id=None, name=None, description=None,
styles=None, styleUrl=None):
styles=None, styleUrl=None, extended_data=None):
super(_Feature, self).__init__(ns, id)
self.name=name
self.description=description
Expand All @@ -243,6 +246,7 @@ def __init__(self, ns=None, id=None, name=None, description=None,
if styles:
for style in styles:
self.append_style(style)
self.extended_data = extended_data

@property
def styleUrl(self):
Expand Down Expand Up @@ -366,7 +370,6 @@ def styles(self):
else:
raise TypeError


def etree_element(self):
element = super(_Feature, self).etree_element()
if self.name:
Expand Down Expand Up @@ -403,6 +406,8 @@ def etree_element(self):
element.append(self._atom_link.etree_element())
if self._atom_author is not None:
element.append(self._atom_author.etree_element())
if self.extended_data is not None:
element.append(self.extended_data.etree_element())
return element


Expand Down Expand Up @@ -460,6 +465,16 @@ def from_element(self, element):
s = atom.Author()
s.from_element(atom_author)
self._atom_author = s
extended_data = element.find('%sExtendedData' % self.ns)
if extended_data is not None:
if extended_data.find('%sData' % self.ns):
x = UntypedExtendedData(self.ns)
x.from_element(extended_data)
self.extended_data = x
else:
logger.warn(
'arbitrary or typed extended data is not yet supported'
)



Expand Down Expand Up @@ -765,3 +780,72 @@ def etree_element(self):
raise ValueError("Either begin, end or both must be set")
#TODO test if end > begin
return element


class UntypedExtendedData(_BaseObject):
""" Represents a list of untyped name/value pairs. See docs:
-> 'Adding Untyped Name/Value Pairs'
https://developers.google.com/kml/documentation/extendeddata
"""
__name__ = 'ExtendedData'

def __init__(self, ns=None, id=None, elements=None):
super(UntypedExtendedData, self).__init__(ns, id)
self.elements = elements or []

def etree_element(self):
element = super(UntypedExtendedData, self).etree_element()

for subelement in self.elements:
element.append(subelement.etree_element())

return element

def from_element(self, element):
super(UntypedExtendedData, self).from_element(element)
self.elements = []

for subelement in element:
el = UntypedExtendedDataElement(self.ns)
el.from_element(subelement)

self.elements.append(el)


class UntypedExtendedDataElement(_BaseObject):
""" Represents an untyped name/value pair with optional display name. """

__name__ = 'Data'

def __init__(self, ns=None, id=None, name=None, value=None, display_name=None):
super(UntypedExtendedDataElement, self).__init__(ns, id)

self.name = name
self.value = value
self.display_name = display_name

def etree_element(self):
element = super(UntypedExtendedDataElement, self).etree_element()

element.set('name', self.name)

value = etree.SubElement(element, "%svalue" % self.ns)
value.text = self.value

if self.display_name:
display_name = etree.SubElement(element, "%sdisplayName" % self.ns)
display_name.text = self.display_name

return element

def from_element(self, element):
super(UntypedExtendedDataElement, self).from_element(element)

self.name = element.get('name')
self.value = element.find('%svalue' % self.ns).text

display_name = element.find('%sdisplayName' % self.ns)
if display_name is not None:
self.display_name = display_name.text
104 changes: 104 additions & 0 deletions fastkml/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,69 @@ def test_placemark(self):
self.assertEqual(k.to_string(), k2.to_string())


def test_untyped_extended_data(self):
ns = '{http://www.opengis.net/kml/2.2}'
k = kml.KML(ns=ns)

p = kml.Placemark(ns, 'id', 'name', 'description')
p.geometry = Point(0.0, 0.0, 0.0)
p.extended_data = kml.UntypedExtendedData(elements=[
kml.UntypedExtendedDataElement(
name='info', value='so much to see'
),
kml.UntypedExtendedDataElement(
name='weather', display_name='Weather', value='blue skies'
)
])

self.assertEqual(len(p.extended_data.elements), 2)
k.append(p)

k2 = kml.KML()
k2.from_string(k.to_string(prettyprint=True))
k.to_string()

extended_data = list(k2.features())[0].extended_data
self.assertTrue(extended_data is not None)
self.assertTrue(len(extended_data.elements), 2)
self.assertEqual(extended_data.elements[0].name, 'info')
self.assertEqual(extended_data.elements[0].value, 'so much to see')
self.assertEqual(extended_data.elements[0].display_name, None)
self.assertEqual(extended_data.elements[1].name, 'weather')
self.assertEqual(extended_data.elements[1].value, 'blue skies')
self.assertEqual(extended_data.elements[1].display_name, 'Weather')


def test_untyped_extended_data_nested(self):
ns = '{http://www.opengis.net/kml/2.2}'
k = kml.KML(ns=ns)

d = kml.Document(ns, 'docid', 'doc name', 'doc description')
d.extended_data = kml.UntypedExtendedData(elements=[
kml.UntypedExtendedDataElement(name='type', value='Document')
])

f = kml.Folder(ns, 'fid', 'f name', 'f description')
f.extended_data = kml.UntypedExtendedData(elements=[
kml.UntypedExtendedDataElement(name='type', value='Folder')
])

k.append(d)
d.append(f)

k2 = kml.KML()
k2.from_string(k.to_string())

document_data = list(k2.features())[0].extended_data
folder_data = list(list(k2.features())[0].features())[0].extended_data

self.assertEqual(document_data.elements[0].name, 'type')
self.assertEqual(document_data.elements[0].value, 'Document')

self.assertEqual(folder_data.elements[0].name, 'type')
self.assertEqual(folder_data.elements[0].value, 'Folder')


def test_document(self):
k = kml.KML()
ns = '{http://www.opengis.net/kml/2.2}'
Expand Down Expand Up @@ -326,6 +389,47 @@ def test_placemark(self):
self.assertEqual(k.to_string(), k2.to_string())


def test_extended_data(self):
doc="""<kml xmlns="http://www.opengis.net/kml/2.2">
<Placemark>
<name>Simple placemark</name>
<description></description>
<Point>
<coordinates>-122.0822035425683,37.42228990140251,0</coordinates>
</Point>
<ExtendedData>
<Data name="holeNumber">
<displayName><![CDATA[
<b>This is hole </b>
]]></displayName>
<value>1</value>
</Data>
<Data name="holePar">
<displayName><![CDATA[
<i>The par for this hole is </i>
]]></displayName>
<value>4</value>
</Data>
</ExtendedData>
</Placemark>
</kml>"""
k = kml.KML()
k.from_string(doc)

extended_data = list(k.features())[0].extended_data

self.assertEqual(extended_data.elements[0].name, 'holeNumber')
self.assertEqual(extended_data.elements[0].value, '1')
self.assertTrue(
'<b>This is hole </b>' in extended_data.elements[0].display_name
)

self.assertEqual(extended_data.elements[1].name, 'holePar')
self.assertEqual(extended_data.elements[1].value, '4')
self.assertTrue(
'<i>The par for this hole is </i>' in extended_data.elements[1].display_name
)


def test_polygon(self):
doc= """<kml xmlns="http://www.opengis.net/kml/2.2">
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def run_tests(self):
sys.exit(errno)


version = '0.3'
version = '0.4dev'

setup(name='fastkml',
version=version,
Expand Down

0 comments on commit 59b362a

Please sign in to comment.