File: tutorial.rst

package info (click to toggle)
pykml 0.2.0%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 920 kB
  • sloc: python: 3,919; makefile: 108; sh: 8
file content (293 lines) | stat: -rw-r--r-- 9,563 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
pyKML Tutorial
==============

The following tutorial gives a brief overview of many of the features of pyKML. 
It is designed to run from within a Python or iPython shell, and assumes that 
pyKML has been installed and is part of your Python search path.  The tutorial 
is designed to be followed from start to finish.

For complete stand alone programs that demonstrate how to use pyKML, check out
the :doc:`examples`.

Constructing KML from scratch
-----------------------------

The pyKML library can be used to construct KML documents, using the 
:ref:`pykml-factory` module:

.. ipython::
    
    # create a factory object that can create elements in the KML namespace
    In [11]: from pykml.factory import KML_ElementMaker as KML
    
    # create an the object equivalent of a KML <name> element
    In [12]: name_object = KML.name("Hello World!")

If you are creating KML documents that utilize elements that are not part
of the default KML namespace, you will want to create an additional factory 
objects for each namespace.  
For example, the following creates factory objects that can
be used to create elements that are part of the ATOM and Google Extensions 
namespace:

.. ipython::

    In [13]: from pykml.factory import ATOM_ElementMaker as ATOM

    In [14]: from pykml.factory import GX_ElementMaker as GX

Documents with nested KML tags can be created by nesting the creation
of Python objects:

.. ipython::
    
    In [16]: pm1 = KML.Placemark(
       ....:         KML.name("Hello World!"),
       ....:         KML.Point(
       ....:           KML.coordinates("-64.5253,18.4607")
       ....:         )
       ....:       )

Once a pyKML object element has been created, a string representation can be 
generated by using the `.tostring()` method:

.. ipython::
    
    In [21]: from lxml import etree
    
    @doctest
    In [22]: etree.tostring(pm1)
    Out[22]: '<Placemark 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"><name>Hello World!</name><Point><coordinates>-64.5253,18.4607</coordinates></Point></Placemark>'

    # use the pretty_print keyword if you want something more readable
    In [23]: print etree.tostring(pm1, pretty_print=True)

pyKML creates Python objects, which  can be passed around and 
later aggregated.  The following creates a second placemark object, and then 
groups the two placemarks together in a folder.

.. ipython::
    
    # create another placemark
    In [31]: pm2 = KML.Placemark(
       ....:         KML.name("A second placemark!"),
       ....:         KML.Point(
       ....:           KML.coordinates("-64.5358,18.4486")
       ....:         )
       ....:       )
    
    # group the two placemarks in a folder
    In [32]: fld = KML.Folder(pm1,pm2)
    
    In [33]: print etree.tostring(fld, pretty_print=True)

Objects representing KML elements can also be appended into objects that have
already been created.
For example, the following appends yet another placemark to the folder.

.. ipython::
    
    # create yet another placemark
    In [41]: pm3=KML.Placemark(KML.name("A third placemark!"))
    
    # append the placemark to the series already in the folder
    In [42]: fld.append(pm3)
    
    In [43]: print etree.tostring(fld, pretty_print=True)

Similarly, you can remove elements from an existing object.  
The following removes the second of three placemarks from the folder:

.. ipython::
    
    # remove a particular placemark
    In [51]: fld.remove(pm2)
    
    In [52]: print etree.tostring(fld, pretty_print=True)

Once you have a KML document, you can access elements using object attributes:

.. ipython::

    In [55]: print fld.Placemark.name.text

This type of attribute-based access is provided by the `lxml` packages's
`objectify API`. pyKML users are encouraged to familiarize themselves with the 
`objectify API documentation`_ on the lxml website, because pyKML inherits this
functionality.

.. _objectify API documentation: http://lxml.de/objectify.html


Parsing existing KML documents
------------------------------

Sometimes instead of building a KML document from scratch, you may want to 
modify an existing KML document.  For this case, pyKML's parsing capabilities
are useful.  pyKML can parse information from a variety of sources, including
strings, local files, and remote URLs.  

The most straightforward is parsing from a string...

.. ipython::

    In [61]: from pykml import parser

    In [62]: kml_str = '<kml xmlns="http://www.opengis.net/kml/2.2">' \
       ....:             '<Document>' \
       ....:               '<Folder>' \
       ....:                 '<name>sample folder</name>' \
       ....:               '</Folder>' \
       ....:             '</Document>' \
       ....:           '</kml>'

    In [63]: root = parser.fromstring(kml_str)

    In [64]: print root.Document.Folder.name.text

You can also parse a local file...

.. ipython::

    In [71]: from os import path
    
    In [72]: kml_file = path.join( \
       ....:     '../src/pykml/test', \
       ....:     'testfiles/google_kml_developers_guide', \
       ....:     'complete_tour_example.kml')
    
    In [73]: with open(kml_file) as f:

    In [74]:     doc = parser.parse(f)
    
    In [75]: 

... or a remote URL...

.. ipython::

    In [80]: import urllib2
    
    In [81]: url = 'http://code.google.com/apis/kml/documentation/KML_Samples.kml'

    In [82]: fileobject = urllib2.urlopen(url)
        
    In [83]: root = parser.parse(fileobject).getroot()
    
    In [84]: print root.Document.name

Validation of KML documents
---------------------------

KML documents that you create can be validated against XML Schema documents,
which define the rules of which elements are acceptible and what ordering can 
be used.  Both the OGC KML schema and the Google Extension schemas are included 
with pyKML.

To validate your KML document, first create instances of the schemas:

.. ipython::

    In [100]: from pykml.parser import Schema

    In [101]: schema_ogc = Schema("ogckml22.xsd")

    In [102]: schema_gx = Schema("kml22gx.xsd")

Then use the schemas to validate your KML objects, using the `.validate()` 
or `.assertValid()` methods.  
The following code creates a small invalide KML document which
includes an element from the Google Extension namespace (`<gx_Tour>`) so 
the document does not validate against the basic OGC KML schema, but does
validate agains the Google Extensions schema. 

.. ipython::

    # create a small KML document
    In [110]: doc = KML.kml(GX.Tour())
    
    # validate it against the OGC KML schema
    In [111]: schema_ogc.validate(doc)
    
    # validate it against the Google Extension schema
    In [112]: schema_gx.validate(doc)

The `.validate()` method only returns True or False.  For invalid documents, 
it is often useful to obtain details of why the document is invalid
using the `.assertValid()` method:
    
.. ipython::

    # validate against the OGC KML schema, and generate an exception
    In [113]: schema_ogc.assertValid(doc)

You can also validate while parsing by including a schema object as a parameter.

.. ipython::

    # the following triggers an error because <eggplant> is not a valid OGC KML element
    In [62]: bad_kml_str = '<kml xmlns="http://www.opengis.net/kml/2.2">' \
       ....:             '<Document>' \
       ....:               '<Folder>' \
       ....:                 '<eggplant/>' \
       ....:               '</Folder>' \
       ....:             '</Document>' \
       ....:           '</kml>'
    
    In [63]: root = parser.fromstring(bad_kml_str, schema_ogc)



Setting the Number of Decimal Places
------------------------------------
Many KML files, especially those authored by Google Earth, contain coordinate
information with more decimal places that often is necessary.  
The `set_max_decimal_places()` function addresses this, by allowing a user
to reduce the number of decimal places used.  The example below demonstrates 
this for a previously created placemark.

.. ipython::

    In [70]: from pykml.helpers import set_max_decimal_places

    In [71]: print etree.tostring(pm1, pretty_print=True)

    # set the coordinate precision to something smaller
    In [72]: set_max_decimal_places(
       ....:            pm1, 
       ....:            max_decimals={
       ....:                'longitude': 2,
       ....:                'latitude': 1,
       ....:            }
       ....:        )

    # note that the coordinate values have changed
    In [73]: print etree.tostring(pm1, pretty_print=True)



Building pyKML Python Scripts
-----------------------------
While pyKML allows you use leverage programming to create
customized KML files, writing the initial pyKML code can be tedious.
To help with this, pyKML provides the verbosely named
`.write_python_script_for_kml_document()` function which will produce
a Python script that can serve as a starting point for further customization.

.. ipython::

    In [10]: from pykml.factory import write_python_script_for_kml_document

    In [11]: url = 'http://code.google.com/apis/kml/documentation/kmlfiles/altitudemode_reference.kml'

    In [12]: fileobject = urllib2.urlopen(url)
        
    In [13]: doc = parser.parse(fileobject).getroot()

    In [14]: script = write_python_script_for_kml_document(doc)

    In [15]: print script


That concludes the tutorial.  For further examples of how pyKML can be used, 
head on over to the :doc:`examples` section of the documentation.