{"id":38599172,"url":"https://github.com/jenetics/jpx","last_synced_at":"2026-01-18T09:31:40.420Z","repository":{"id":37451362,"uuid":"76488267","full_name":"jenetics/jpx","owner":"jenetics","description":"JPX - Java GPX library","archived":false,"fork":false,"pushed_at":"2025-08-24T20:01:19.000Z","size":14761,"stargazers_count":219,"open_issues_count":13,"forks_count":33,"subscribers_count":8,"default_branch":"master","last_synced_at":"2026-01-17T17:59:32.579Z","etag":null,"topics":["geocoding","geolocation","gps","gpx","gpx-files","gpx-parser","gpx-reader","gpx-writer","iso6709"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jenetics.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-12-14T18:59:35.000Z","updated_at":"2025-12-04T15:20:47.000Z","dependencies_parsed_at":"2024-11-11T20:29:28.114Z","dependency_job_id":null,"html_url":"https://github.com/jenetics/jpx","commit_stats":{"total_commits":878,"total_committers":10,"mean_commits":87.8,"dds":0.03986332574031892,"last_synced_commit":"e6357d229c4f6fd3a7171d5da0667aa632921f31"},"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/jenetics/jpx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenetics%2Fjpx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenetics%2Fjpx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenetics%2Fjpx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenetics%2Fjpx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jenetics","download_url":"https://codeload.github.com/jenetics/jpx/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenetics%2Fjpx/sbom","scorecard":{"id":514881,"data":{"date":"2025-08-11","repo":{"name":"github.com/jenetics/jpx","commit":"d14c86706f43695354097e36baf7d89590443cdc"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.5,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":3,"reason":"Found 2/6 approved changesets -- score normalized to 3","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/gradle.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":8,"reason":"binaries present in source code","details":["Warn: binary detected: buildSrc/lib/java2html.jar:1","Warn: binary detected: gradle/wrapper/gradle-wrapper.jar:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/gradle.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/jenetics/jpx/gradle.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/gradle.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/jenetics/jpx/gradle.yml/master?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.txt:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 29 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T01:33:52.745Z","repository_id":37451362,"created_at":"2025-08-20T01:33:52.745Z","updated_at":"2025-08-20T01:33:52.745Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28534159,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T00:39:45.795Z","status":"online","status_checked_at":"2026-01-18T02:00:07.578Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["geocoding","geolocation","gps","gpx","gpx-files","gpx-parser","gpx-reader","gpx-writer","iso6709"],"created_at":"2026-01-17T08:31:54.652Z","updated_at":"2026-01-18T09:31:40.399Z","avatar_url":"https://github.com/jenetics.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# JPX\n\n![Build Status](https://github.com/jenetics/jpx/actions/workflows/gradle.yml/badge.svg)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.jenetics/jpx/badge.svg)](http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22jpx%22)\n[![Javadoc](https://www.javadoc.io/badge/io.jenetics/jpx.svg)](http://www.javadoc.io/doc/io.jenetics/jpx)\n\n**JPX** is a Java library for creating, reading and writing [GPS](https://en.wikipedia.org/wiki/Global_Positioning_System) data in [GPX](https://en.wikipedia.org/wiki/GPS_Exchange_Format) format. It is a *full* implementation of version [1.1](http://www.topografix.com/GPX/1/1/) and version [1.0](http://www.topografix.com/gpx_manual.asp) of the GPX format. The data classes are completely immutable and allows a functional programming style. They are working also nicely with the Java [Stream](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/stream/Stream.html) API. It is also possible to convert the location information into strings which are compatible to the [ISO 6709](http://en.wikipedia.org/wiki/ISO_6709) standard.\n\nBesides the basic functionality of reading and writing GPX files, the library also allows manipulating the read GPX object in a functional way.\n\n\n## Dependencies\n\nThe _JPX_ library needs no external dependencies. It only needs **Java 17** to compile and run. It also runs and compiles with **Java 21** and **Java 23**.\n\n\n## Building JPX\n\nFor building the JPX library, you have to check out the `master` branch from GitHub.\n\n    $ git clone https://github.com/jenetics/jpx.git\n    \n*Executing the tests:*\n    \n    $ cd jpx\n    $ ./gradlew test\n\n*Building the library:*\n\n    $ ./gradlew jar\n    \n\n## Examples\n\n### Creating a new GPX object with 3 track-points\n\n```java\nfinal GPX gpx = GPX.builder()\n    .addTrack(track -\u003e track\n        .addSegment(segment -\u003e segment\n            .addPoint(p -\u003e p.lat(48.20100).lon(16.31651).ele(283))\n            .addPoint(p -\u003e p.lat(48.20112).lon(16.31639).ele(278))\n            .addPoint(p -\u003e p.lat(48.20126).lon(16.31601).ele(274))))\n    .build();\n```\n\n**Writing GPX object to a file**\n\n```java\nGPX.write(gpx, Path.of(\"track.gpx\"));\n```\n\n*GPX output*\n\n```xml\n\u003cgpx version=\"1.1\" creator=\"JPX - https://github.com/jenetics/jpx\" xmlns=\"http://www.topografix.com/GPX/1/1\"\u003e\n    \u003ctrk\u003e\n        \u003ctrkseg\u003e\n            \u003ctrkpt lat=\"48.201\" lon=\"16.31651\"\u003e\n                \u003cele\u003e283\u003c/ele\u003e\n            \u003c/trkpt\u003e\n            \u003ctrkpt lat=\"48.20112\" lon=\"16.31639\"\u003e\n                \u003cele\u003e278\u003c/ele\u003e\n            \u003c/trkpt\u003e\n            \u003ctrkpt lat=\"48.20126\" lon=\"16.31601\"\u003e\n                \u003cele\u003e274\u003c/ele\u003e\n            \u003c/trkpt\u003e\n        \u003c/trkseg\u003e\n    \u003c/trk\u003e\n\u003c/gpx\u003e\n```\n\n### Reading GPX object from file\n\nThis example writes a given `GPX` object to a file, reads it again and prints the `WayPoint`s of all tracks and all track-segments to the console.\n\n```java\nGPX.write(gpx, Path.of(\"track.gpx\"));\nGPX.read(\"gpx.xml\").tracks()\n    .flatMap(Track::segments)\n    .flatMap(TrackSegment::points)\n    .forEach(System.out::println);\n\n```\n\n*Console output*\n\n```bash\n$ [lat=48.201, lon=16.31651, ele=283]\n$ [lat=48.20112, lon=16.31639, ele=278]\n$ [lat=48.20126, lon=16.31601, ele=274]\n\n```\n\n### Reading GPX extensions\n\nThe library is also able to read arbitrary GPX _extensions_.\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003cgpx version=\"1.1\" creator=\"JPX - Java GPX library\" xmlns=\"http://www.topografix.com/GPX/1/1\"\u003e\n    ...\n    \u003cextensions\u003e\n        \u003cgpxdata:lap xmlns:gpxdata=\"http://www.cluetrust.com/XML/GPXDATA/1/0\"\u003e\n            \u003cgpxdata:index\u003e1\u003c/gpxdata:index\u003e\n            \u003cgpxdata:startPoint lat=\"51.219983\" lon=\"6.765224\"/\u003e\n            \u003cgpxdata:endPoint lat=\"51.220137\" lon=\"6.765098\" /\u003e\n        \u003c/gpxdata:lap\u003e\n    \u003c/extensions\u003e\n\u003c/gpx\u003e\n\n```\n\nThe extensions are available via a `org.w3c.dom.Document` object, with an `extensions` root element.\n\n```java\nfinal Optional\u003cDocument\u003e extensions = gpx.getExtensions();\n```\n\n### Converting a `GPX` object into an `org.w3c.dom.Document`\n\n```java\nfinal GPX gpx = ...;\n\nfinal Document doc = XMLProvider.provider()\n    .documentBuilderFactory()\n    .newDocumentBuilder()\n    .newDocument();\n\n// The GPX data are written to the empty `doc` object.\nGPX.Writer.DEFAULT.write(gpx, new DOMResult(doc));\n```\n\n### Reading GPX 1.0 and writing GPX 1.1\n\nBy default, JPX is reading and writing the GPX files in version 1.1. But it is possible to read and write GPX files in version 1.0 as well.\n\n```java\n// Reading GPX 1.0 file.\nfinal GPX gpx10 = GPX.reader(GPX.Version.V10).read(\"track-v10.gpx\");\n\n// Changing GPX version to 1.1.\nfinal GPX gpx11 = gpx10.toBuilder()\n    .version(GPX.Version.V11)\n    .build();\n\n// Writing GPX to file.\nGPX.write(gpx11, Path.of(\"track-v11.gpx\"));\n```\n\n### ISO 6709 location strings\n\nWith the `LocationFormatter` class it is possible to create ISO 6709 compatible strings.\n\n```java\nfinal Point p = WayPoint.of(...);\nfinal Location loc = Location.of(p);\nfinal LocationFormatter format = LocationFormatter.ISO_HUMAN_LONG;\nSystem.out.println(format.format(loc));\n```\nThe printed location will look like this\n\n    24°59'15.486\"N 65°14'03.390\"W 65.23m\n\nIt is also possible to define your own formatter from a given pattern string,\n\n```java\nfinal LocationFormatter format = \n    LocationFormatter.ofPattern(\"DD°MMSS dd°mmss\");\n```\nwhich leads to the following output\n\n    24°5915 65°1403\n\nThis string can then also be parsed to a _location_.\n\n```java\nfinal Location location = format.parse(\"24°5915 65°1403\");\n```\n\n### Geodetic calculations\n\n#### Distance between two points\n\n```java\nfinal Point start = WayPoint.of(47.2692124, 11.4041024);\nfinal Point end = WayPoint.of(47.3502, 11.70584);\nfinal Length distance = Geoid.WGS84.distance(start, end);\nSystem.out.println(distance);\n```\n\n*Console output*\n\n```bash\n$ 24528.356073554987 m\n```\n\n#### Path length \n\nCalculate the path length of the first track-segment.\n\n```java\nfinal Length length = gpx.tracks()\n    .flatMap(Track::segments)\n    .findFirst()\n    .map(TrackSegment::points).orElse(Stream.empty())\n    .collect(Geoid.WGS84.toPathLength());\n```\n\n### GPX manipulation/filtering\n\n#### Filtering\n\nThe following example filters empty tracks and track-segments from an existing `GPX` object.\n    \n```java\nfinal GPX gpx = GPX.read(\"track.gpx\");\n\n// Filtering empty tracks.\nfinal GPX gpx1 = gpx.toBuilder()\n    .trackFilter()\n        .filter(Track::nonEmpty)\n        .build()\n    .build();\n\n// Filtering empty track-segments.\nfinal GPX gpx2 = gpx.toBuilder()\n    .trackFilter()\n        .map(track -\u003e track.toBuilder()\n            .filter(TrackSegment::nonEmpty)\n            .build())\n        .build()\n    .build();\n\n// Filtering empty tracks and track-segments.\nfinal GPX gpx3 = gpx.toBuilder()\n    .trackFilter()\n        .map(track -\u003e track.toBuilder()\n            .filter(TrackSegment::nonEmpty)\n            .build())\n        .filter(Track::nonEmpty)\n        .build()\n    .build();\n```\n\n#### Changing GPX object\n\n*Fixing* the time of all track way-points by adding one hour.\n\n```java\nfinal GPX gpx = GPX.read(\"track.gpx\");\n\nfinal GPX gpx1 = gpx.toBuilder()\n    .trackFilter()\n        .map(track -\u003e track.toBuilder()\n            .map(segment -\u003e segment.toBuilder()\n                .map(wp -\u003e wp.toBuilder()\n                    .time(wp.getTime()\n                        .map(t -\u003e t.plusHours(1))\n                        .orElse(null))\n                    .build())\n                .build())\n            .build())\n        .build()\n    .build();\n```\n\nDoing the same only for the GPX way-points.\n\n```java\nfinal GPX gpx = GPX.read(\"track.gpx\");\n\nfinal GPX gpx1 = gpx.toBuilder()\n    .wayPointFilter()\n        .map(wp -\u003e wp.toBuilder()\n            .time(wp.getTime()\n                .map(t -\u003e t.plusHours(1))\n                .orElse(null))\n            .build())\n        .build()\n    .build();\n```\n\n### XML configuration\n\nThe _JPX_ library uses the XML classes available in the Java [`java.xml`](https://docs.oracle.com/en/java/javase/11/docs/api/java.xml/module-summary.html) module. This API is highly configurable, and it is possible to replace the underlying implementation. Especially for Android, using different XML implementation is a necessity. _JPX_ uses three _factory_ classes for reading/writing GPX files:\n\n1. [`XMLInputFactory`](https://docs.oracle.com/en/java/javase/11/docs/api/java.xml/javax/xml/stream/XMLInputFactory.html): This class is needed for reading GPX files.\n1. [`XMLOutputFactory`](https://docs.oracle.com/en/java/javase/11/docs/api/java.xml/javax/xml/stream/XMLOutputFactory.html): This class is needed for writing GPX files.\n1. [`DocumentBuilderFactory`](https://docs.oracle.com/en/java/javase/11/docs/api/java.xml/javax/xml/parsers/DocumentBuilderFactory.html): This class is used for creating XML-documents for the GPX `extensions` data.\n\nYou can change the used classes by implementing and registering a different `XMLProvider` class. The following code show how to change the configuration of the `DocumentBuilderFactory` class.\n\n```java\npackage org.acme;\nfinal class ValidatingDocumentBuilder extends XMLProvider { \n    @Override\n    public DocumentBuilderFactory documentBuilderFactory() { \n        final DocumentBuilderFactory factory = \n            DocumentBuilderFactory.newInstance();\n        factory.setValidating(true);\n        factory.setNamespaceAware(true);\n        return factory; \n    }\n}\n```\nAnd remember to create a `META-INF/services/io.jenetics.jpx.XMLProvider` file with the following content:\n\n```\norg.acme.NonValidatingDocumentBuilder\n```\n\n## License\n\nThe library is licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html).\n\n    Copyright 2016-2025 Franz Wilhelmstötter\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n## Release notes\n\n### [3.2.1](https://github.com/jenetics/jpx/releases/tag/v3.2.1)\n\n#### Improvements\n\n* [#186](https://github.com/jenetics/jpx/issues/186): LENIENT mode allows GPX tags without creator attributes.\n\n### [3.2.0](https://github.com/jenetics/jpx/releases/tag/v3.2.0)\n\n#### Improvements\n\n* [#183](https://github.com/jenetics/jpx/issues/183): Update Gradle to 8.11 and improve build scripts.\n* [#181](https://github.com/jenetics/jpx/pull/181): Update code examples in README.\n\n### [3.1.0](https://github.com/jenetics/jpx/releases/tag/v3.1.0)\n\n#### Improvements\n\n* [#170](https://github.com/jenetics/jpx/issues/170): GPX files with invalid version number are now readable in _LENIENT_ mode.\n```java\nfinal GPX gpx;\ntry (InputStream in = new FileInputStream(resource)) {\n\tgpx = GPX.Reader.of(Mode.LENIENT).read(in);\n}\n```\n\n#### Bugs\n\n* [#167](https://github.com/jenetics/jpx/issues/167): Fixing a test case for Windows.\n\n### [3.0.1](https://github.com/jenetics/jpx/releases/tag/v3.0.1)\n\n#### Bugs\n\n* [#162](https://github.com/jenetics/jpx/issues/162): Elevation serialization for values \u003e 1000m is incompatible with deserialization.\n\n### [3.0.0](https://github.com/jenetics/jpx/releases/tag/v3.0.0)\n\n#### Improvements\n\n* [#125](https://github.com/jenetics/jpx/issues/125): **Breaking change** - Use `Instant` instead of `ZonedDateTime` for `Point.time` property.\n* [#148](https://github.com/jenetics/jpx/issues/148): **Breaking change** - Update to Java17.\n* [#155](https://github.com/jenetics/jpx/issues/155): Improved `GPX.Reader` and `GPX.Writer` classes.\n* [#158](https://github.com/jenetics/jpx/issues/158): Add XML `Document` reader/writer methods.\n```java\nfinal GPX gpx = ...;\n\nfinal Document doc = XMLProvider.provider()\n    .documentBuilderFactory()\n    .newDocumentBuilder()\n    .newDocument();\n\n// The GPX data are written to the empty `doc` object.\nGPX.Writer.DEFAULT.write(gpx, new DOMResult(doc));\n```\n\n#### Bugs\n\n* [#151](https://github.com/jenetics/jpx/issues/151): `Double`'s being written as exponents in GPX file.\n* [#152](https://github.com/jenetics/jpx/issues/152): `LocationFormatter::parse` method is not thread-safe.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjenetics%2Fjpx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjenetics%2Fjpx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjenetics%2Fjpx/lists"}