Skip to content

Commit

Permalink
#8 #9 Work in progress:
Browse files Browse the repository at this point in the history
-GPX schema checking correction
-KML schema checking correction

[ci skip]
  • Loading branch information
FABallemand committed Sep 3, 2023
1 parent 38b5d9a commit 6373ec3
Show file tree
Hide file tree
Showing 11 changed files with 3,423 additions and 373 deletions.
13 changes: 13 additions & 0 deletions examples/conversion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import ezgpx

# Parse GPX file
gpx = ezgpx.GPX("file.gpx")

# Convert to Pandas Dataframe
df = gpx.to_dataframe()

# Convert to CSV
gpx.to_csv("file.csv", columns=["lat", "lon", "ele"])

# Convert to KML
gpx.to_kml("file.kml")
1 change: 1 addition & 0 deletions ezgpx/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .gpx_elements import *
from .gpx_parser import *
from .gpx_writer import *
from .kml_writer import *
from .gpx import *
6 changes: 2 additions & 4 deletions ezgpx/gpx/gpx.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ def to_gpx(self, path: str, check_schemas: bool = True, extensions_schemas: bool
"""
return self.gpx_writer.write(path, check_schemas, extensions_schemas)

def to_kml(self, path: str, styles: Optional[List[Tuple[str, Dict]]] = None, check_schemas: bool = True, extensions_schemas: bool = False) -> bool:
def to_kml(self, path: str, styles: Optional[List[Tuple[str, Dict]]] = None, check_schemas: bool = True) -> bool:
"""
Write the GPX object to a .kml file.
Expand All @@ -600,15 +600,13 @@ def to_kml(self, path: str, styles: Optional[List[Tuple[str, Dict]]] = None, che
List of (style_id, style) tuples, by default None
check_schemas : bool, optional
Toggle schema verification after writting, by default True
extensions_schemas : bool, optional
Toggle extensions schema verificaton after writing. Requires internet connection and is not guaranted to work, by default False
Returns
-------
bool
Return False if written file does not follow checked schemas. Return True otherwise.
"""
return self.kml_writer.write(path, styles, check_schemas, extensions_schemas)
return self.kml_writer.write(path, styles, check_schemas)

def _matplotlib_plot_text(
self,
Expand Down
6 changes: 4 additions & 2 deletions ezgpx/gpx_elements/gpx.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from typing import Union, List, Tuple
import logging
import xmlschema
Expand Down Expand Up @@ -104,10 +105,11 @@ def check_schemas(self, file_path: str, extensions_schemas: bool = False) -> boo
return False
else:
schema = None
current_file_path = os.path.dirname(os.path.abspath(__file__))
if self.version == "1.1":
schema = xmlschema.XMLSchema("schemas/gpx_1_1/gpx.xsd")
schema = xmlschema.XMLSchema(os.path.join(current_file_path, "../schemas/gpx_1_1/gpx.xsd"))
elif self.version == "1.0":
schema = xmlschema.XMLSchema("schemas/gpx_1_0/gpx.xsd")
schema = xmlschema.XMLSchema(os.path.join(current_file_path, "../schemas/gpx_1_0/gpx.xsd"))

if schema is not None:
return schema.is_valid(file_path)
Expand Down
22 changes: 12 additions & 10 deletions ezgpx/kml_writer/kml_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import Optional, Union, List, Tuple, Dict
import logging
import xml.etree.ElementTree as ET
import xmlschema
from datetime import datetime

from ..gpx_elements import Bounds, Copyright, Email, Extensions, Gpx, Link, Metadata, Person, PointSegment, Point, Route, TrackSegment, Track, WayPoint
Expand Down Expand Up @@ -386,8 +387,7 @@ def write(
self,
path: str,
styles: Optional[List[Tuple[str, Dict]]] = None,
check_schemas: bool = False,
extensions_schemas: bool = False) -> bool:
check_schemas: bool = False) -> bool:
"""
Handle writing.
Expand All @@ -399,10 +399,6 @@ def write(
List of (style_id, style) tuples, by default None
check_schemas : bool, optional
Toggle schema verification after writting, by default False
extensions_schemas : bool, optional
Toggle extensions schema verificaton after writing.
Requires internet connection and is not guaranted to work,
by default False
Returns
-------
Expand All @@ -427,8 +423,14 @@ def write(

# Check schema
if check_schemas:
verification_gpx = Parser(path, check_schemas=False, extensions_schemas=False).gpx
if not verification_gpx.check_schemas(self.path, extensions_schemas=extensions_schemas):
logging.error("Invalid written file (does not follow schema)")
return False
# Load schema
current_file_path = os.path.dirname(os.path.abspath(__file__))
schema = xmlschema.XMLSchema(os.path.join(current_file_path, "../schemas/kml_2_2/ogckml22.xsd"))

# Check schema
if schema is not None:
return schema.is_valid(self.path)
else:
logging.error("Unable to check XML schema")
return True
return True
66 changes: 66 additions & 0 deletions ezgpx/schemas/kml_2_2/atom-author-link.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
targetNamespace="http://www.w3.org/2005/Atom"
xmlns:atom="http://www.w3.org/2005/Atom" version="1.0.0">

<annotation>
<appinfo>atom-author-link.xsd 2008-01-23</appinfo>
<documentation>There is no official atom XSD. This XSD is created based on:
http://atompub.org/2005/08/17/atom.rnc. A subset of Atom as used in the
ogckml22.xsd is defined here. </documentation>
</annotation>

<!-- Person Construct -->
<complexType name="atomPersonConstruct">
<choice minOccurs="0" maxOccurs="unbounded">
<element ref="atom:name"/>
<element ref="atom:uri"/>
<element ref="atom:email"/>
</choice>
</complexType>

<element name="name" type="string"/>
<element name="uri" type="string"/>
<element name="email" type="atom:atomEmailAddress"/>

<!-- atom:author -->
<element name="author" type="atom:atomPersonConstruct"/>

<!-- atom:link -->
<element name="link">
<complexType>

<attribute name="href" use="required"/>
<attribute name="rel"/>
<attribute name="type" type="atom:atomMediaType"/>
<attribute name="hreflang" type="atom:atomLanguageTag"/>
<attribute name="title"/>
<attribute name="length"/>

</complexType>

</element>

<!-- Whatever a media type is, it contains at least one slash -->
<simpleType name="atomMediaType">
<restriction base="string">
<pattern value=".+/.+"/>
</restriction>
</simpleType>

<!-- As defined in RFC 3066 -->
<simpleType name="atomLanguageTag">
<restriction base="string">
<pattern value="[A-Za-z]{1,8}(-[A-Za-z0-9]{1,8})*"/>
</restriction>
</simpleType>

<!-- Whatever an email address is, it contains at least one @ -->
<simpleType name="atomEmailAddress">
<restriction base="string">
<pattern value=".+@.+"/>
</restriction>
</simpleType>

</schema>
Loading

0 comments on commit 6373ec3

Please sign in to comment.