1import unittest
2from os import path
3try:  # Python2 support
4    import urllib2
5    URLError = urllib2.URLError
6except ImportError:  # Python3 support
7    import urllib.request as urllib2
8    from urllib.error import URLError
9try:  # Python2 support
10    from StringIO import StringIO
11except ImportError:  # Python3 support
12    from io import StringIO
13
14from lxml import etree
15from pykml.parser import Schema
16from pykml.parser import fromstring
17from pykml.parser import parse
18
19
20class ValidatorTestCase(unittest.TestCase):
21
22    def test_initialize_schema(self):
23        """Tests the creation Schema instance"""
24        schema = Schema("ogckml22.xsd")
25        self.assertTrue(isinstance(schema.schema, etree.XMLSchema))
26
27    def test_initialize_schema_remote_url(self):
28        schema = Schema("http://code.google.com/apis/kml/schema/kml22gx.xsd")
29        self.assertTrue(isinstance(schema.schema, etree.XMLSchema))
30
31
32class ParseKmlOgcTestCase(unittest.TestCase):
33    "A collection of tests related to parsing KML OGC documents"
34
35    def test_fromstring_kml_document(self):
36        "Tests the parsing of an valid KML string"
37        test_kml = '<kml xmlns="http://www.opengis.net/kml/2.2"/>'
38        tree = fromstring(test_kml, schema=Schema("ogckml22.xsd"))
39        self.assertEqual(etree.tostring(tree).decode(), test_kml)
40        tree = fromstring(test_kml)
41        self.assertEqual(etree.tostring(tree).decode(), test_kml)
42
43    def test_fromstring_invalid_kml_document(self):
44        "Tests the parsing of an invalid KML string"
45        test_kml = '<bad_element />'
46        try:
47            tree = fromstring(test_kml, schema=Schema("ogckml22.xsd"))
48            self.assertTrue(False)
49        except etree.XMLSyntaxError:
50            self.assertTrue(True)
51        except:
52            self.assertTrue(False)
53
54    def test_parse_kml_document(self):
55        "Tests the parsing of an valid KML file object"
56        test_kml = '<kml xmlns="http://www.opengis.net/kml/2.2"/>'
57        fileobject = StringIO(test_kml)
58        schema = Schema("ogckml22.xsd")
59        tree = parse(fileobject, schema=schema)
60        self.assertEqual(etree.tostring(tree).decode(), test_kml)
61        tree = parse(fileobject, schema=schema)
62        self.assertEqual(etree.tostring(tree).decode(), test_kml)
63
64    def test_parse_invalid_kml_document(self):
65        "Tests the parsing of an invalid KML document"
66        fileobject = StringIO('<bad_element />')
67        try:
68            tree = parse(fileobject, schema=Schema("ogckml22.xsd"))
69            self.assertTrue(False)
70        except etree.XMLSyntaxError:
71            self.assertTrue(True)
72        except:
73            self.assertTrue(False)
74
75    def test_parse_kml_url(self):
76        "Tests the parsing of a KML URL"
77        url = 'http://code.google.com/apis/kml/documentation/KML_Samples.kml'
78        #url = 'http://kml-samples.googlecode.com/svn/trunk/kml/Document/doc-with-id.kml'
79        #url = 'http://code.google.com/apis/kml/documentation/kmlfiles/altitudemode_reference.kml'
80        #url = 'http://code.google.com/apis/kml/documentation/kmlfiles/animatedupdate_example.kml'
81        try:
82            fileobject = urllib2.urlopen(url)
83            tree = parse(fileobject, schema=Schema("ogckml22.xsd"))
84            self.assertEqual(
85                etree.tostring(tree)[:78].decode(),
86                '<kml xmlns="http://www.opengis.net/kml/2.2">'
87                  '<Document>'
88                    '<name>KML Samples</name>'
89            )
90        except URLError:
91            print('Unable to access the URL. Skipping test...')
92
93    def test_parse_kml_file_with_cdata(self):
94        "Tests the parsing of a local KML file, with a CDATA description string"
95        test_datafile = path.join(
96            path.dirname(__file__),
97            'testfiles',
98            'google_kml_tutorial/using_the_cdata_element.kml'
99        )
100        # parse with validation
101        with open(test_datafile) as f:
102            doc = parse(f, schema=Schema('ogckml22.xsd'))
103        self.assertEqual(
104            etree.tostring(doc).decode(),
105            '<kml xmlns="http://www.opengis.net/kml/2.2">'
106              '<Document>'
107                '<Placemark>'
108                  '<name>CDATA example</name>'
109                  '<description>'
110                    '<![CDATA[\n'
111                    '          <h1>CDATA Tags are useful!</h1>\n'
112                    '          <p><font color="red">Text is <i>more readable</i> and \n'
113                    '          <b>easier to write</b> when you can avoid using entity \n'
114                    '          references.</font></p>\n'
115                    '        ]]>'
116                  '</description>'
117                '<Point>'
118                  '<coordinates>102.595626,14.996729</coordinates>'
119                '</Point>'
120              '</Placemark>'
121            '</Document>'
122          '</kml>'
123        )
124        # parse without validation
125        with open(test_datafile) as f:
126            doc2 = parse(f)
127        self.assertEqual(
128            etree.tostring(doc2).decode(),
129            '<kml xmlns="http://www.opengis.net/kml/2.2">'
130              '<Document>'
131                '<Placemark>'
132                  '<name>CDATA example</name>'
133                  '<description>'
134                    '<![CDATA[\n'
135                    '          <h1>CDATA Tags are useful!</h1>\n'
136                    '          <p><font color="red">Text is <i>more readable</i> and \n'
137                    '          <b>easier to write</b> when you can avoid using entity \n'
138                    '          references.</font></p>\n'
139                    '        ]]>'
140                  '</description>'
141                '<Point>'
142                  '<coordinates>102.595626,14.996729</coordinates>'
143                '</Point>'
144              '</Placemark>'
145            '</Document>'
146          '</kml>'
147        )
148
149    def test_parse_invalid_ogc_kml_document(self):
150        """Tests the parsing of an invalid KML document.  Note that this KML
151        document uses elements that are not in the OGC KML spec.
152        """
153        url = 'http://code.google.com/apis/kml/documentation/kmlfiles/altitudemode_reference.kml'
154        try:
155            fileobject = urllib2.urlopen(url)
156            tree = parse(fileobject, schema=Schema("ogckml22.xsd"))
157            self.assertTrue(False)
158        except URLError:
159            print('Unable to access the URL. Skipping test...')
160        except etree.XMLSyntaxError:
161            self.assertTrue(True)
162        except:
163            self.assertTrue(False)
164
165
166class ParseKmlGxTestCase(unittest.TestCase):
167    "A collection of tests related to parsing KML Google Extension documents"
168
169    def test_parse_kml_url(self):
170        "Tests the parsing of a KML URL"
171        url = 'http://code.google.com/apis/kml/documentation/kmlfiles/altitudemode_reference.kml'
172        try:
173            fileobject = urllib2.urlopen(url)
174            tree = parse(fileobject, schema=Schema('kml22gx.xsd'))
175            self.assertEqual(
176                etree.tostring(tree)[:185].decode(),
177                '<kml xmlns="http://www.opengis.net/kml/2.2" '
178                     'xmlns:gx="http://www.google.com/kml/ext/2.2">'
179                    '<!-- required when using gx-prefixed elements -->'
180                    '<Placemark>'
181                      '<name>gx:altitudeMode Example</name>'
182            )
183        except URLError:
184            print('Unable to access the URL. Skipping test...')
185
186    def test_parse_kml_file(self):
187        "Tests the parsing of a local KML file, with validation"
188        test_datafile = path.join(
189            path.dirname(__file__),
190            'testfiles',
191            'google_kml_developers_guide/complete_tour_example.kml'
192        )
193        # parse without validation
194        with open(test_datafile) as f:
195            doc = parse(f)
196        # parse with validation (local schema file)
197        with open(test_datafile) as f:
198            doc = parse(f, schema=Schema('kml22gx.xsd'))
199        # parse with validation (remote schema file)
200        with open(test_datafile) as f:
201            doc = parse(f, schema=Schema('http://code.google.com/apis/kml/schema/kml22gx.xsd'))
202        self.assertTrue(True)
203
204    def test_parse_kml_url_2(self):
205        "Tests the parsing of a KML URL"
206        url = 'http://code.google.com/apis/kml/documentation/kmlfiles/animatedupdate_example.kml'
207        try:
208            fileobject = urllib2.urlopen(url)
209            tree = parse(fileobject, schema=Schema('kml22gx.xsd'))
210            self.assertEqual(
211                etree.tostring(tree)[:137].decode(),
212                '<kml xmlns="http://www.opengis.net/kml/2.2" '
213                     'xmlns:gx="http://www.google.com/kml/ext/2.2">'
214                    '<Document>'
215                      '<name>gx:AnimatedUpdate example</name>'
216            )
217        except URLError:
218            print('Unable to access the URL. Skipping test...')
219
220if __name__ == '__main__':
221    unittest.main()
222