Commit 1ae05c9b authored by Christian Ledermann's avatar Christian Ledermann

Merge pull request #3 from seantis/master

 add the ability to add untyped extended data / name value pairs 
thanks :)
parents 3d9c9c3e d3e85f3b
*.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
......@@ -2,6 +2,11 @@
Changelog
=========
0.4 (unreleased)
----------------
- adds the ability to add untyped extended data / named value pairs
0.3 (2012/11/15)
-----------------
......
......@@ -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
......@@ -243,6 +246,7 @@ class _Feature(_BaseObject):
if styles:
for style in styles:
self.append_style(style)
self.extended_data = extended_data
@property
def styleUrl(self):
......@@ -366,7 +370,6 @@ class _Feature(_BaseObject):
else:
raise TypeError
def etree_element(self):
element = super(_Feature, self).etree_element()
if self.name:
......@@ -403,6 +406,8 @@ class _Feature(_BaseObject):
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
......@@ -460,6 +465,16 @@ class _Feature(_BaseObject):
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'
)
......@@ -765,3 +780,72 @@ class TimeSpan(_TimePrimitive):
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
......@@ -162,6 +162,69 @@ class BuildKmlTestCase(unittest.TestCase):
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}'
......@@ -326,6 +389,47 @@ class KmlFromStringTestCase( unittest.TestCase ):
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">
......
......@@ -14,7 +14,7 @@ class PyTest(TestCommand):
sys.exit(errno)
version = '0.3'
version = '0.4dev'
setup(name='fastkml',
version=version,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment