Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
F
fastkml
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Aurélien Vermylen
fastkml
Commits
6aaf8ab7
Commit
6aaf8ab7
authored
Jun 25, 2012
by
Christian Ledermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add styles, atom and (empty) gx
parent
4bb70a19
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
345 additions
and
20 deletions
+345
-20
fastkml/atom.py
fastkml/atom.py
+195
-0
fastkml/gx.py
fastkml/gx.py
+58
-0
fastkml/kml.py
fastkml/kml.py
+88
-15
fastkml/tests.py
fastkml/tests.py
+4
-5
No files found.
fastkml/atom.py
0 → 100644
View file @
6aaf8ab7
# -*- coding: utf-8 -*-
"""
KML 2.2 supports new elements for including data about the author and
related website in your KML file. This information is displayed in geo
search results, both in Earth browsers such as Google Earth, and in other
applications such as Google Maps. The ascription elements used in KML
are as follows:
atom:author element - parent element for atom:name
atom:name element - the name of the author
atom:link element - contains the href attribute
href attribute - URL of the web page containing the KML/KMZ file
These elements are defined in the Atom Syndication Format. The complete
specification is found at http://atompub.org.
"""
import
logging
logger
=
logging
.
getLogger
(
'fastkml.atom'
)
try
:
from
lxml
import
etree
LXML
=
True
except
ImportError
:
import
xml.etree.ElementTree
as
etree
LXML
=
False
class
Link
(
object
):
"""
Identifies a related Web page. The type of relation is defined by
the rel attribute. A feed is limited to one alternate per type and
hreflang.
<link> is patterned after html's link element. It has one required
attribute, href, and five optional attributes: rel, type, hreflang,
title, and length.
"""
__name__
=
'Link'
ns
=
None
href
=
None
# href is the URI of the referenced resource
rel
=
None
# rel contains a single link relationship type.
# It can be a full URI, or one of the following predefined values
# (default=alternate):
# alternate: an alternate representation
# enclosure: a related resource which is potentially large in size
# and might require special handling, for example an audio or video
# recording.
# related: an document related to the entry or feed.
# self: the feed itself.
# via: the source of the information provided in the entry.
type
=
None
# indicates the media type of the resource
hreflang
=
None
# indicates the language of the referenced resource
title
=
None
# human readable information about the link
lenght
=
None
# the length of the resource, in bytes
def
__init__
(
self
,
ns
=
None
,
href
=
None
,
rel
=
None
,
type
=
None
,
hreflang
=
None
,
title
=
None
,
lenght
=
None
):
if
ns
==
None
:
self
.
ns
=
'{http://www.w3.org/2005/Atom}'
else
:
self
.
ns
=
ns
self
.
href
=
href
self
.
rel
=
rel
self
.
type
=
type
self
.
hreflang
=
hreflang
self
.
title
=
title
self
.
lenght
=
lenght
def
from_string
(
self
,
xml_string
):
self
.
from_element
(
etree
.
XML
(
xml_string
))
def
from_element
(
self
,
element
):
if
self
.
ns
+
self
.
__name__
.
lower
()
!=
element
.
tag
:
raise
TypeError
else
:
if
element
.
get
(
'href'
):
self
.
href
=
element
.
get
(
'href'
)
else
:
logger
.
critical
(
'required attribute href missing'
)
raise
TypeError
if
element
.
get
(
'rel'
):
self
.
rel
=
element
.
get
(
'rel'
)
if
element
.
get
(
'type'
):
self
.
type
=
element
.
get
(
'type'
)
if
element
.
get
(
'hreflang'
):
self
.
hreflang
=
element
.
get
(
'hreflang'
)
if
element
.
get
(
'title'
):
self
.
title
=
element
.
get
(
'title'
)
if
element
.
get
(
'lenght'
):
self
.
rel
=
element
.
get
(
'lenght'
)
return
element
def
etree_element
(
self
):
element
=
etree
.
Element
(
self
.
ns
+
self
.
__name__
.
lower
())
if
self
.
href
:
element
.
set
(
'href'
,
self
.
href
)
else
:
logger
.
critical
(
'required attribute href missing'
)
raise
TypeError
element
.
set
(
'rel'
,
self
.
rel
)
element
.
set
(
'type'
,
self
.
type
)
element
.
set
(
'hreflang'
,
self
.
hreflang
)
element
.
set
(
'title'
,
self
.
title
)
element
.
set
(
'lenght'
,
self
.
lenght
)
class
_Person
(
object
):
"""
<author> and <contributor> describe a person, corporation, or similar
entity. It has one required element, name, and two optional elements:
uri, email.
"""
ns
=
None
name
=
None
#conveys a human-readable name for the person.
uri
=
None
#contains a home page for the person.
email
=
None
#contains an email address for the person.
def
__init__
(
self
,
ns
=
None
,
name
=
None
,
uri
=
None
,
email
=
None
):
if
ns
==
None
:
self
.
ns
=
'{http://www.w3.org/2005/Atom}'
else
:
self
.
ns
=
ns
self
.
name
=
name
self
.
uri
=
uri
self
.
email
=
email
def
etree_element
(
self
):
element
=
etree
.
Element
(
self
.
ns
+
self
.
__name__
.
lower
())
if
self
.
name
:
name
=
etree
.
SubElement
(
element
,
"%sname"
%
self
.
ns
)
name
.
text
=
self
.
name
else
:
logger
.
critical
(
'No Name for person defined'
)
raise
TypeError
if
self
.
uri
:
#XXX validate uri
uri
=
etree
.
SubElement
(
element
,
"%suri"
%
self
.
ns
)
uri
.
text
=
self
.
uri
if
self
.
email
:
#XXX validate email
email
=
etree
.
SubElement
(
element
,
"%semail"
%
self
.
ns
)
email
.
text
=
self
.
email
def
from_string
(
self
,
xml_string
):
self
.
from_element
(
etree
.
XML
(
xml_string
))
def
from_element
(
self
,
element
):
if
self
.
ns
+
self
.
__name__
.
lower
!=
element
.
tag
:
raise
TypeError
else
:
name
=
element
.
find
(
'%sname'
%
self
.
ns
)
if
name
is
not
None
:
self
.
name
=
name
.
text
uri
=
element
.
find
(
'%suri'
%
self
.
ns
)
if
uri
is
not
None
:
self
.
uri
=
uri
.
text
email
=
element
.
find
(
'%semail'
%
self
.
ns
)
if
email
is
not
None
:
self
.
email
=
email
.
text
class
Author
(
_Person
):
""" Names one author of the feed/entry. A feed/entry may have
multiple authors."""
__name__
=
"Author"
class
Contributor
(
_Person
):
""" Names one contributor to the feed/entry. A feed/entry may have
multiple contributor elements."""
__name__
=
"Contributor"
fastkml/gx.py
0 → 100644
View file @
6aaf8ab7
# -*- coding: utf-8 -*-
"""
With the launch of Google Earth 5.0, Google has provided extensions to KML
to support a number of new features. These extensions use the gx prefix
and the following namespace URI:
xmlns:gx="http://www.google.com/kml/ext/2.2"
This namespace URI must be added to the <kml> element in any KML file
using gx-prefixed elements:
<kml xmlns="http://www.opengis.net/kml/2.2"
xmlns:gx="http://www.google.com/kml/ext/2.2">
Extensions to KML may not be supported in all geo-browsers. If your
browser doesn't support particular extensions, the data in those
extensions should be silently ignored, and the rest of the KML file
should load without errors.
Elements that currently use the gx prefix are:
gx:altitudeMode
gx:altitudeOffset
gx:angles
gx:AnimatedUpdate
gx:balloonVisibility
gx:coord
gx:delayedStart
gx:drawOrder
gx:duration
gx:FlyTo
gx:flyToMode
gx:h
gx:horizFov
gx:interpolate
gx:labelVisibility
gx:LatLonQuad
gx:MultiTrack
gx:vieweroptions
gx:outerColor
gx:outerWidth
gx:physicalWidth
gx:Playlist
gx:playMode
gx:SoundCue
gx:TimeSpan
gx:TimeStamp
gx:Tour
gx:TourControl
gx:TourPrimitive
gx:Track
gx:ViewerOptions
gx:w
gx:Wait
gx:x
gx:y
The complete XML schema for elements in this extension namespace is
located at http://developers.google.com/kml/schema/kml22gx.xsd.
"""
fastkml/kml.py
View file @
6aaf8ab7
# -*- coding: utf-8 -*-
"""
KML is an open standard officially named the OpenGIS KML Encoding Standard
(OGC KML). It is maintained by the Open Geospatial Consortium, Inc. (OGC).
The complete specification for OGC KML can be found at
http://www.opengeospatial.org/standards/kml/.
The complete XML schema for KML is located at
http://schemas.opengis.net/kml/.
"""
from
shapely.geometry
import
Point
,
LineString
,
Polygon
from
shapely.geometry
import
MultiPoint
,
MultiLineString
,
MultiPolygon
from
shapely.geometry.polygon
import
LinearRing
import
logging
logger
=
logging
.
getLogger
(
'fastkml'
)
logger
=
logging
.
getLogger
(
'fastkml
.kml
'
)
try
:
...
...
@@ -14,14 +25,24 @@ except ImportError:
import
xml.etree.ElementTree
as
etree
LXML
=
False
from
styles
import
StyleUrl
,
Style
,
StyleMap
,
_StyleSelector
import
atom
import
gx
class
KML
(
object
):
""" represents a KML File """
_features
=
[]
ns
=
None
def
__init__
(
self
):
def
__init__
(
self
,
ns
=
None
):
self
.
_features
=
[]
if
ns
==
None
:
self
.
ns
=
'{http://www.opengis.net/kml/2.2}'
else
:
self
.
ns
=
ns
def
from_string
(
self
,
xml_string
):
""" create a KML object from a xml string"""
...
...
@@ -47,7 +68,7 @@ class KML(object):
raise
TypeError
def
etree_element
(
self
):
root
=
etree
.
Element
(
'
{http://www.opengis.net/kml/2.2}kml'
)
root
=
etree
.
Element
(
'
%skml'
%
self
.
ns
)
for
feature
in
self
.
features
():
root
.
append
(
feature
.
etree_element
())
return
root
...
...
@@ -59,13 +80,15 @@ class KML(object):
def
features
(
self
):
""" return a list of features """
#XXX yield feature, test if they are valid features
return
self
.
_features
def
append
(
self
,
kmlobj
):
""" append a feature """
if
isinstance
(
kmlobj
,
(
Document
,
Folder
,
Placemark
)):
self
.
_features
.
append
(
kmlobj
)
else
:
raise
TypeError
class
_Feature
(
object
):
"""
...
...
@@ -78,7 +101,7 @@ class _Feature(object):
#PhotoOverlay,
#ScreenOverlay
"""
ns
=
None
id
=
None
name
=
None
#User-defined text displayed in the 3D viewer as the label for the
...
...
@@ -99,17 +122,41 @@ class _Feature(object):
#If the style is in the same file, use a # reference.
#If the style is defined in an external file, use a full URL
#along with # referencing.
_styles
=
None
#atom_author = None
#atom_link = None
#XXX atom_author = None
#XXX atom_link = None
def
__init__
(
self
,
ns
,
id
=
None
,
name
=
None
,
description
=
None
):
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
name
=
None
,
description
=
None
,
styles
=
None
,
styleUrl
=
None
):
self
.
id
=
id
self
.
name
=
name
self
.
description
=
description
self
.
ns
=
ns
self
.
styleUrl
=
styleUrl
self
.
_styles
=
[]
if
styles
:
for
style
in
styles
:
self
.
append_style
(
style
)
if
ns
==
None
:
self
.
ns
=
'{http://www.opengis.net/kml/2.2}'
else
:
self
.
ns
=
ns
def
append_style
(
self
,
style
):
""" append a style to the feature """
if
isinstance
(
style
,
_StyleSelector
):
self
.
_styles
.
append
(
style
)
else
:
raise
TypeError
def
styles
(
self
):
""" iterate over the styles of this feature """
for
style
in
self
.
_styles
:
if
isinstance
(
style
,
_StyleSelector
):
yield
style
else
:
raise
TypeError
def
etree_element
(
self
):
if
self
.
__name__
:
...
...
@@ -126,6 +173,11 @@ class _Feature(object):
visibility
.
text
=
str
(
self
.
visibility
)
isopen
=
etree
.
SubElement
(
element
,
"%sopen"
%
self
.
ns
)
isopen
.
text
=
str
(
self
.
isopen
)
if
self
.
styleUrl
:
styleUrl
=
StyleUrl
(
self
.
ns
,
self
.
styleUrl
)
element
.
append
(
styleUrl
.
etree_element
())
for
style
in
self
.
styles
():
element
.
append
(
style
.
etree_element
())
else
:
raise
NotImplementedError
return
element
...
...
@@ -148,10 +200,22 @@ class _Feature(object):
self
.
description
=
description
.
text
visibility
=
element
.
find
(
'%svisibility'
%
self
.
ns
)
if
visibility
is
not
None
:
self
.
visibility
=
visibility
.
text
self
.
visibility
=
int
(
visibility
.
text
)
isopen
=
element
.
find
(
'%sopen'
%
self
.
ns
)
if
isopen
is
not
None
:
self
.
isopen
=
isopen
.
text
self
.
isopen
=
int
(
isopen
.
text
)
styles
=
element
.
findall
(
'%sStyle'
%
self
.
ns
)
for
style
in
styles
:
s
=
Style
(
self
.
ns
)
s
.
from_element
(
style
)
self
.
append_style
(
s
)
styles
=
element
.
findall
(
'%sStyleMap'
%
self
.
ns
)
for
style
in
styles
:
s
=
StyleMap
(
self
.
ns
)
s
.
from_element
(
style
)
self
.
append_style
(
s
)
class
_Container
(
_Feature
):
"""
...
...
@@ -165,9 +229,13 @@ class _Container(_Feature):
_features
=
[]
def
__init__
(
self
,
ns
,
id
=
None
,
name
=
None
,
description
=
None
):
def
__init__
(
self
,
ns
=
None
,
id
=
None
,
name
=
None
,
description
=
None
):
super
(
_Container
,
self
).
__init__
(
ns
,
id
,
name
,
description
)
self
.
_features
=
[]
if
ns
==
None
:
self
.
ns
=
'{http://www.opengis.net/kml/2.2}'
else
:
self
.
ns
=
ns
def
features
(
self
):
""" return a list of features """
...
...
@@ -230,6 +298,12 @@ class Folder(_Container):
self
.
append
(
feature
)
class
Placemark
(
_Feature
):
"""
A Placemark is a Feature with associated Geometry.
In Google Earth, a Placemark appears as a list item in the Places
panel. A Placemark with a Point has an icon associated with it that
marks a point on the Earth in the 3D viewer.
"""
__name__
=
"Placemark"
geometry
=
None
...
...
@@ -401,4 +475,3 @@ class Placemark(_Feature):
fastkml/tests.py
View file @
6aaf8ab7
...
...
@@ -42,9 +42,9 @@ class BuildKmlTestCase(unittest.TestCase):
k
=
kml
.
KML
()
ns
=
'{http://www.opengis.net/kml/2.2}'
p
=
kml
.
Placemark
(
ns
,
'id'
,
'name'
,
'description'
)
p
.
geometry
=
Point
(
0.0
,
0.0
)
p
.
geometry
=
Point
(
0.0
,
0.0
,
0.0
)
p2
=
kml
.
Placemark
(
ns
,
'id2'
,
'name2'
,
'description2'
)
p2
.
geometry
=
LineString
([(
0
,
0
),
(
1
,
1
)])
p2
.
geometry
=
LineString
([(
0
,
0
,
0
),
(
1
,
1
,
1
)])
k
.
append
(
p
)
k
.
append
(
p2
)
self
.
assertEqual
(
len
(
k
.
features
()),
2
)
...
...
@@ -65,7 +65,7 @@ class BuildKmlTestCase(unittest.TestCase):
f2
=
kml
.
Folder
(
ns
,
'id2'
,
'name2'
,
'description2'
)
d
.
append
(
f2
)
p
=
kml
.
Placemark
(
ns
,
'id'
,
'name'
,
'description'
)
p
.
geometry
=
Polygon
([(
0
,
0
),
(
1
,
1
),
(
1
,
0
)])
p
.
geometry
=
Polygon
([(
0
,
0
,
0
),
(
1
,
1
,
0
),
(
1
,
0
,
1
)])
p2
=
kml
.
Placemark
(
ns
,
'id2'
,
'name2'
,
'description2'
)
#p2 does not have a geometry!
f2
.
append
(
p
)
...
...
@@ -302,8 +302,7 @@ class KmlFromStringTestCase( unittest.TestCase ):
k2
=
kml
.
KML
()
k2
.
from_string
(
k
.
to_string
())
self
.
assertEqual
(
k
.
to_string
(),
k2
.
to_string
())
print
k
.
to_string
()
print
def
test_suite
():
suite
=
unittest
.
TestSuite
()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment