Merge branch 'release/1.2'

This commit is contained in:
bvn13 2022-09-29 19:36:29 +03:00
commit af129685c3
3 changed files with 467 additions and 422 deletions

14
pom.xml
View File

@ -6,7 +6,7 @@
<artifactId>GpxAndroidSdk</artifactId> <artifactId>GpxAndroidSdk</artifactId>
<groupId>me.bvn13.sdk.android.gpx</groupId> <groupId>me.bvn13.sdk.android.gpx</groupId>
<version>1.1</version> <version>1.2</version>
<packaging>jar</packaging> <packaging>jar</packaging>
@ -82,15 +82,9 @@
<version>${kotlin-junit.version}</version> <version>${kotlin-junit.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.kotest</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>kotest-runner-junit5-jvm</artifactId> <artifactId>junit-jupiter-api</artifactId>
<version>${kotest.version}</version> <version>${jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.kotest</groupId>
<artifactId>kotest-assertions-core-jvm</artifactId>
<version>${kotest.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -99,11 +99,11 @@ fun GpxType.toXmlString(clock: Clock?): String = """
xsi:schemaLocation="$SCHEMA_LOCATION"> xsi:schemaLocation="$SCHEMA_LOCATION">
<time>${now(clock)}</time> <time>${now(clock)}</time>
${this.metadata.toXmlString()} ${this.metadata.toXmlString()}
${this.wpt?.toXmlString()} ${this.wpt?.toXmlString() ?: ""}
${this.rte?.toXmlString()} ${this.rte?.toXmlString() ?: ""}
${this.trk?.toXmlString()} ${this.trk?.toXmlString() ?: ""}
</gpx> </gpx>
""".trim() """.trim().removeEmptyStrings()
fun MetadataType.toXmlString(): String = """ fun MetadataType.toXmlString(): String = """
<metadata> <metadata>
@ -113,16 +113,13 @@ fun MetadataType.toXmlString(): String = """
<name>${this.authorName}</name> <name>${this.authorName}</name>
</author> </author>
</metadata> </metadata>
""".trim() """.trim().removeEmptyStrings()
private fun now(clock: Clock?) = OffsetDateTime.now(clock ?: Clock.systemDefaultZone()).format(DTF) fun WptType.toXmlString(nodeName: String? = null) = if (nodeName != null) {
this.toXmlString(nodeName)
fun WptType.toXmlString(nodeName: String? = null) = } else {
if (nodeName != null) { this.toXmlString("wpt")
this.toXmlString(nodeName) }
} else {
this.toXmlString("wpt")
}
@JvmName("toXmlStringNamed") @JvmName("toXmlStringNamed")
fun WptType.toXmlString(nodeName: String) = """ fun WptType.toXmlString(nodeName: String) = """
@ -135,19 +132,19 @@ fun WptType.toXmlString(nodeName: String) = """
${toXmlString(cmt, "cmt")} ${toXmlString(cmt, "cmt")}
${toXmlString(desc, "desc")} ${toXmlString(desc, "desc")}
${toXmlString(src, "src")} ${toXmlString(src, "src")}
${link?.toXmlString()} ${link?.toXmlString() ?: ""}
${toXmlString(sym, "sym")} ${toXmlString(sym, "sym")}
${toXmlString(type, "type")} ${toXmlString(type, "type")}
${fix?.toXmlString()} ${fix?.toXmlString() ?: ""}
${toXmlString(sat, "sat")} ${toXmlString(sat, "sat")}
${toXmlString(hdop, "hdop")} ${toXmlString(hdop, "hdop")}
${toXmlString(vdop, "vdop")} ${toXmlString(vdop, "vdop")}
${toXmlString(pdop, "pdop")} ${toXmlString(pdop, "pdop")}
${toXmlString(ageofgpsdata, "ageofgpsdata")} ${toXmlString(ageofgpsdata, "ageofgpsdata")}
${toXmlString(dgpsid, "dgpsid")} ${toXmlString(dgpsid, "dgpsid")}
${extensions?.toXmlString()} ${extensions?.toXmlString() ?: ""}
</${nodeName}> </${nodeName}>
""".trim() """.trim().removeEmptyStrings()
fun RteType.toXmlString() = """ fun RteType.toXmlString() = """
<rte> <rte>
@ -155,13 +152,13 @@ fun RteType.toXmlString() = """
${toXmlString(this.cmt, "cmt")} ${toXmlString(this.cmt, "cmt")}
${toXmlString(this.desc, "desc")} ${toXmlString(this.desc, "desc")}
${toXmlString(this.src, "src")} ${toXmlString(this.src, "src")}
${this.link?.toXmlString()} ${this.link?.toXmlString() ?: ""}
${toXmlString(this.number, "number")} ${toXmlString(this.number, "number")}
${toXmlString(this.type, "type")} ${toXmlString(this.type, "type")}
${this.extensions?.toXmlString()} ${this.extensions?.toXmlString() ?: ""}
${this.rtept?.toXmlString()} ${this.rtept?.toXmlString() ?: ""}
</rte> </rte>
""".trim() """.trim().removeEmptyStrings()
fun TrkType.toXmlString() = """ fun TrkType.toXmlString() = """
<trk> <trk>
@ -169,24 +166,47 @@ fun TrkType.toXmlString() = """
${toXmlString(this.cmt, "cmt")} ${toXmlString(this.cmt, "cmt")}
${toXmlString(this.desc, "desc")} ${toXmlString(this.desc, "desc")}
${toXmlString(this.src, "src")} ${toXmlString(this.src, "src")}
${this.link?.toXmlString()} ${this.link?.toXmlString() ?: ""}
${toXmlString(this.number, "number")} ${toXmlString(this.number, "number")}
${toXmlString(this.type, "type")} ${toXmlString(this.type, "type")}
${this.extensions?.toXmlString()} ${this.extensions?.toXmlString() ?: ""}
${this.trkseg?.toXmlString()} ${this.trkseg?.toXmlString() ?: ""}
</trk> </trk>
""".trim() """.trim().removeEmptyStrings()
fun List<WptType>.toXmlString(nodeName: String?) = fun LinkType.toXmlString() = """
this.joinToString(prefix = "", postfix = "", separator = "") { <link href="${this.href}">
it.toXmlString(nodeName) <text>${this.text}</text>
} <type>${this.type}</type>
</link>
""".trim().removeEmptyStrings()
fun FixType.toXmlString() = """
<fix>${this.value}</fix>
""".trim().removeEmptyStrings()
fun ExtensionType.toXmlString() = """
<${this.nodeName}${toXmlString(this.parameters)}>${this.value ?: ""}</${this.nodeName}>
""".trim().removeEmptyStrings()
fun TrksegType.toXmlString() = """
<trkseg>
${this.trkpt?.toXmlString("trkpt") ?: ""}
</trkseg>
""".trim().removeEmptyStrings()
fun List<WptType>.toXmlString(nodeName: String?) = this.joinToString(prefix = "\n", postfix = "", separator = "") {
it.toXmlString(nodeName)
}
fun List<ExtensionType>.toXmlString() = this.joinToString(
prefix = "<extensions>\n", postfix = "\n</extensions>", separator = "\n", transform = ExtensionType::toXmlString
)
@JvmName("toXmlStringWptType") @JvmName("toXmlStringWptType")
fun List<WptType>.toXmlString() = fun List<WptType>.toXmlString() = this.joinToString(prefix = "", postfix = "", separator = "") {
this.joinToString(prefix = "", postfix = "", separator = "") { it.toXmlString()
it.toXmlString() }
}
@JvmName("toXmlStringLinkType") @JvmName("toXmlStringLinkType")
fun List<LinkType>.toXmlString() = fun List<LinkType>.toXmlString() =
@ -204,75 +224,41 @@ fun List<TrkType>.toXmlString() =
fun List<TrksegType>.toXmlString() = fun List<TrksegType>.toXmlString() =
this.joinToString(prefix = "", postfix = "", separator = "", transform = TrksegType::toXmlString) this.joinToString(prefix = "", postfix = "", separator = "", transform = TrksegType::toXmlString)
fun List<ExtensionType>.toXmlString() = fun toXmlString(value: String?, nodeName: String) = if (value != null) {
this.joinToString( "<${nodeName}>${value}</${nodeName}>"
prefix = "<extensions>\n", } else {
postfix = "\n</extensions>", ""
separator = "\n", }
transform = ExtensionType::toXmlString
)
fun LinkType.toXmlString() = """ fun toXmlString(value: Int?, nodeName: String) = if (value != null) {
<link href="${this.href}"> "<${nodeName}>${value}</${nodeName}>"
<text>${this.text}</text> } else {
<type>${this.type}</type> ""
</link> }
""".trim()
fun FixType.toXmlString() = """ fun toXmlString(value: Double?, nodeName: String) = if (value != null) {
<fix>${this.value}</fix> "<${nodeName}>${value}</${nodeName}>"
""".trim() } else {
""
}
fun ExtensionType.toXmlString() = """ fun toXmlString(value: OffsetDateTime?, nodeName: String) = if (value != null) {
<${this.nodeName}${toXmlString(this.parameters)}>${this.value ?: ""}</${this.nodeName}> "<${nodeName}>${value.format(DTF)}</${nodeName}>"
""".trim() } else {
""
}
fun TrksegType.toXmlString() = """ fun toXmlString(value: Map<String, String>?) = value?.entries?.joinToString(separator = "") {
<trkseg> " ${it.key}=\"${it.value}\""
${this.trkpt?.toXmlString("trkpt")} } ?: ""
</trkseg>
""".trim()
fun toXmlString(value: String?, nodeName: String) = private fun now(clock: Clock?) = OffsetDateTime.now(clock ?: Clock.systemDefaultZone()).format(DTF)
if (value != null) {
"""
<${nodeName}>${value}</${nodeName}>
""".trim()
} else {
""
}
fun toXmlString(value: Int?, nodeName: String) = private fun String.removeEmptyStrings() = this.lineSequence().map {
if (value != null) { it.trim()
""" }.filter {
<${nodeName}>${value}</${nodeName}> it != ""
""".trim() }.joinToString("\n")
} else {
""
}
fun toXmlString(value: Double?, nodeName: String) =
if (value != null) {
"""
<${nodeName}>${value}</${nodeName}>
""".trim()
} else {
""
}
fun toXmlString(value: OffsetDateTime?, nodeName: String) =
if (value != null) {
"""
<${nodeName}>${value.format(DTF)}</${nodeName}>
""".trim()
} else {
""
}
fun toXmlString(value: Map<String, String>?) =
value?.entries?.joinToString(separator = "") {
" ${it.key}=\"${it.value}\""
} ?: ""
class GpxWriter { class GpxWriter {
companion object { companion object {
@ -281,9 +267,9 @@ class GpxWriter {
const val XMLNS_XSI = "http://www.w3.org/2001/XMLSchema-instance" const val XMLNS_XSI = "http://www.w3.org/2001/XMLSchema-instance"
const val SCHEMA_LOCATION = "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd" const val SCHEMA_LOCATION = "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
internal val DTF = DateTimeFormatterBuilder() internal val DTF =
.append(ISO_LOCAL_DATE_TIME) // use the existing formatter for date time DateTimeFormatterBuilder().append(ISO_LOCAL_DATE_TIME) // use the existing formatter for date time
.appendOffset("+HH:MM", "+00:00") // set 'noOffsetText' to desired '+00:00' .appendOffset("+HH:MM", "+00:00") // set 'noOffsetText' to desired '+00:00'
.toFormatter() .toFormatter()
} }
} }

View File

@ -59,7 +59,7 @@ APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
Copyright [yyyy] [name of copyright owner] Copyright bvn13, 2022
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -77,184 +77,246 @@ limitations under the License.
package me.bvn13.sdk.android.gpx package me.bvn13.sdk.android.gpx
import io.kotest.core.spec.style.FunSpec import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import java.time.* import java.time.*
import kotlin.test.assertEquals import kotlin.test.assertEquals
class GpxWriterTest : FunSpec() { class GpxWriterTest {
init { @DisplayName("test minimum")
test("first test") { @Test
val clock = Clock.fixed( fun testMinimum() {
LocalDateTime.of(2022, 9, 24, 15, 4, 0, 0).toInstant(ZoneOffset.ofHours(3)), ZoneId.of("Europe/Moscow") val clock = Clock.fixed(
) LocalDateTime.of(2022, 9, 24, 15, 4, 0, 0).toInstant(ZoneOffset.ofHours(3)), ZoneId.of("Europe/Moscow")
)
val gpxType = GpxType( val gpxType = GpxType(
MetadataType("test name", description = "test description", authorName = "bvn13"), MetadataType("test name"),
wpt = listOf( trk = listOf(
WptType( TrkType(
lat = 14.64736838389662, name = "track1",
lon = 7.93212890625, trkseg = listOf(
ele = 10.toDouble(), TrksegType(
time = OffsetDateTime.now(clock), listOf(
magvar = 3.toDouble(), WptType(
geoidheight = 45.toDouble(), lat = 123.toDouble(),
name = "test point 1", lon = 321.toDouble()
cmt = "comment 1",
desc = "description of point 1",
link = listOf(
LinkType(
href = "http://link-to.site.href",
text = "text",
type = "hyperlink"
),
LinkType(
href = "http://link2-to.site.href",
text = "text2",
type = "hyperlink2"
)
),
src = "source 1",
sym = "sym 1",
type = "type 1",
fix = FixType.DGPS,
sat = 1,
hdop = 55.toDouble(),
vdop = 66.toDouble(),
pdop = 77.toDouble(),
ageofgpsdata = 44,
dgpsid = 88,
extensions = listOf(
ExtensionType(
"extension1",
parameters = mapOf(Pair("first", "second"), Pair("third", "fours"))
),
ExtensionType(
"extension2",
parameters = mapOf(Pair("aa", "bb"), Pair("cc", "dd"))
)
)
)
),
rte = listOf(
RteType(
name = "rte name",
cmt = "cmt",
desc = "desc",
src = "src",
link = listOf(
LinkType(
href = "https://new.link.rte",
text = "new text rte",
type = "hyperlink"
)
),
number = 1234,
type = "route",
extensions = listOf(
ExtensionType(
"ext-1",
value = "value1"
)
),
rtept = listOf(
WptType(
lat = 14.64736838389662,
lon = 7.93212890625,
ele = 10.toDouble(),
time = OffsetDateTime.now(clock),
magvar = 3.toDouble(),
geoidheight = 45.toDouble(),
name = "test point 1",
cmt = "comment 1",
desc = "description of point 1",
link = listOf(
LinkType(
href = "http://link-to.site.href",
text = "text",
type = "hyperlink"
),
LinkType(
href = "http://link2-to.site.href",
text = "text2",
type = "hyperlink2"
)
),
src = "source 1",
sym = "sym 1",
type = "type 1",
fix = FixType.DGPS,
sat = 1,
hdop = 55.toDouble(),
vdop = 66.toDouble(),
pdop = 77.toDouble(),
ageofgpsdata = 44,
dgpsid = 88,
extensions = listOf(
ExtensionType(
"extension1",
parameters = mapOf(Pair("first", "second"), Pair("third", "fours"))
),
ExtensionType(
"extension2",
parameters = mapOf(Pair("aa", "bb"), Pair("cc", "dd"))
)
) )
) )
) )
) )
), )
trk = listOf( )
TrkType( )
name = "track 1",
cmt = "comment track 1", assertEquals(
desc = "desc track 1", """
src = "src track 1", <?xml version="1.0" encoding="UTF-8"?>
number = 1234, <gpx
type = "type 1", xmlns="http://www.topografix.com/GPX/1/1"
trkseg = listOf( version="1.1"
TrksegType( creator="me.bvn13.sdk.android.gpx"
listOf( xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
WptType( xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
lat = 14.64736838389662, <time>2022-09-24T15:04:00+03:00</time>
lon = 7.93212890625, <metadata>
ele = 10.toDouble(), <name>test name</name>
time = OffsetDateTime.now(clock), <desc></desc>
magvar = 3.toDouble(), <author>
geoidheight = 45.toDouble(), <name></name>
name = "test point 1", </author>
cmt = "comment 1", </metadata>
desc = "description of point 1", <trk>
link = listOf( <name>track1</name>
LinkType( <trkseg>
href = "http://link-to.site.href", <trkpt lat="123.0" lon="321.0">
text = "text", </trkpt>
type = "hyperlink" </trkseg>
), </trk>
LinkType( </gpx>
href = "http://link2-to.site.href", """.trim()
text = "text2", .lineSequence()
type = "hyperlink2" .map {
) it.trim()
}
.joinToString("\n"),
gpxType.toXmlString(clock)
)
}
@DisplayName("test maximum")
@Test
fun maximumTest() {
val clock = Clock.fixed(
LocalDateTime.of(2022, 9, 24, 15, 4, 0, 0).toInstant(ZoneOffset.ofHours(3)), ZoneId.of("Europe/Moscow")
)
val gpxType = GpxType(
MetadataType("test name", description = "test description", authorName = "bvn13"),
wpt = listOf(
WptType(
lat = 14.64736838389662,
lon = 7.93212890625,
ele = 10.toDouble(),
time = OffsetDateTime.now(clock),
magvar = 3.toDouble(),
geoidheight = 45.toDouble(),
name = "test point 1",
cmt = "comment 1",
desc = "description of point 1",
link = listOf(
LinkType(
href = "http://link-to.site.href",
text = "text",
type = "hyperlink"
),
LinkType(
href = "http://link2-to.site.href",
text = "text2",
type = "hyperlink2"
)
),
src = "source 1",
sym = "sym 1",
type = "type 1",
fix = FixType.DGPS,
sat = 1,
hdop = 55.toDouble(),
vdop = 66.toDouble(),
pdop = 77.toDouble(),
ageofgpsdata = 44,
dgpsid = 88,
extensions = listOf(
ExtensionType(
"extension1",
parameters = mapOf(Pair("first", "second"), Pair("third", "fours"))
),
ExtensionType(
"extension2",
parameters = mapOf(Pair("aa", "bb"), Pair("cc", "dd"))
)
)
)
),
rte = listOf(
RteType(
name = "rte name",
cmt = "cmt",
desc = "desc",
src = "src",
link = listOf(
LinkType(
href = "https://new.link.rte",
text = "new text rte",
type = "hyperlink"
)
),
number = 1234,
type = "route",
extensions = listOf(
ExtensionType(
"ext-1",
value = "value1"
)
),
rtept = listOf(
WptType(
lat = 14.64736838389662,
lon = 7.93212890625,
ele = 10.toDouble(),
time = OffsetDateTime.now(clock),
magvar = 3.toDouble(),
geoidheight = 45.toDouble(),
name = "test point 1",
cmt = "comment 1",
desc = "description of point 1",
link = listOf(
LinkType(
href = "http://link-to.site.href",
text = "text",
type = "hyperlink"
),
LinkType(
href = "http://link2-to.site.href",
text = "text2",
type = "hyperlink2"
)
),
src = "source 1",
sym = "sym 1",
type = "type 1",
fix = FixType.DGPS,
sat = 1,
hdop = 55.toDouble(),
vdop = 66.toDouble(),
pdop = 77.toDouble(),
ageofgpsdata = 44,
dgpsid = 88,
extensions = listOf(
ExtensionType(
"extension1",
parameters = mapOf(Pair("first", "second"), Pair("third", "fours"))
),
ExtensionType(
"extension2",
parameters = mapOf(Pair("aa", "bb"), Pair("cc", "dd"))
)
)
)
)
)
),
trk = listOf(
TrkType(
name = "track 1",
cmt = "comment track 1",
desc = "desc track 1",
src = "src track 1",
number = 1234,
type = "type 1",
trkseg = listOf(
TrksegType(
listOf(
WptType(
lat = 14.64736838389662,
lon = 7.93212890625,
ele = 10.toDouble(),
time = OffsetDateTime.now(clock),
magvar = 3.toDouble(),
geoidheight = 45.toDouble(),
name = "test point 1",
cmt = "comment 1",
desc = "description of point 1",
link = listOf(
LinkType(
href = "http://link-to.site.href",
text = "text",
type = "hyperlink"
), ),
src = "source 1", LinkType(
sym = "sym 1", href = "http://link2-to.site.href",
type = "type 1", text = "text2",
fix = FixType.DGPS, type = "hyperlink2"
sat = 1, )
hdop = 55.toDouble(), ),
vdop = 66.toDouble(), src = "source 1",
pdop = 77.toDouble(), sym = "sym 1",
ageofgpsdata = 44, type = "type 1",
dgpsid = 88, fix = FixType.DGPS,
extensions = listOf( sat = 1,
ExtensionType( hdop = 55.toDouble(),
"extension1", vdop = 66.toDouble(),
parameters = mapOf(Pair("first", "second"), Pair("third", "fours")) pdop = 77.toDouble(),
), ageofgpsdata = 44,
ExtensionType( dgpsid = 88,
"extension2", extensions = listOf(
parameters = mapOf(Pair("aa", "bb"), Pair("cc", "dd")) ExtensionType(
) "extension1",
parameters = mapOf(Pair("first", "second"), Pair("third", "fours"))
),
ExtensionType(
"extension2",
parameters = mapOf(Pair("aa", "bb"), Pair("cc", "dd"))
) )
) )
) )
@ -263,148 +325,151 @@ class GpxWriterTest : FunSpec() {
) )
) )
) )
)
assertEquals( assertEquals(
""" """
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<gpx <gpx
xmlns="http://www.topografix.com/GPX/1/1" xmlns="http://www.topografix.com/GPX/1/1"
version="1.1" version="1.1"
creator="me.bvn13.sdk.android.gpx" creator="me.bvn13.sdk.android.gpx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"> xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
<time>2022-09-24T15:04:00+03:00</time> <time>2022-09-24T15:04:00+03:00</time>
<metadata> <metadata>
<name>test name</name> <name>test name</name>
<desc>test description</desc> <desc>test description</desc>
<author> <author>
<name>bvn13</name> <name>bvn13</name>
</author> </author>
</metadata> </metadata>
<wpt lat="14.64736838389662" lon="7.93212890625"> <wpt lat="14.64736838389662" lon="7.93212890625">
<ele>10.0</ele> <ele>10.0</ele>
<time>2022-09-24T15:04:00+03:00</time> <time>2022-09-24T15:04:00+03:00</time>
<magvar>3.0</magvar> <magvar>3.0</magvar>
<geoidheight>45.0</geoidheight> <geoidheight>45.0</geoidheight>
<name>test point 1</name> <name>test point 1</name>
<cmt>comment 1</cmt> <cmt>comment 1</cmt>
<desc>description of point 1</desc> <desc>description of point 1</desc>
<src>source 1</src> <src>source 1</src>
<link href="http://link-to.site.href"> <link href="http://link-to.site.href">
<text>text</text> <text>text</text>
<type>hyperlink</type> <type>hyperlink</type>
</link> </link>
<link href="http://link2-to.site.href"> <link href="http://link2-to.site.href">
<text>text2</text> <text>text2</text>
<type>hyperlink2</type> <type>hyperlink2</type>
</link> </link>
<sym>sym 1</sym> <sym>sym 1</sym>
<type>type 1</type> <type>type 1</type>
<fix>dgps</fix> <fix>dgps</fix>
<sat>1</sat> <sat>1</sat>
<hdop>55.0</hdop> <hdop>55.0</hdop>
<vdop>66.0</vdop> <vdop>66.0</vdop>
<pdop>77.0</pdop> <pdop>77.0</pdop>
<ageofgpsdata>44</ageofgpsdata> <ageofgpsdata>44</ageofgpsdata>
<dgpsid>88</dgpsid> <dgpsid>88</dgpsid>
<extensions> <extensions>
<extension1 first="second" third="fours"></extension1> <extension1 first="second" third="fours"></extension1>
<extension2 aa="bb" cc="dd"></extension2> <extension2 aa="bb" cc="dd"></extension2>
</extensions> </extensions>
</wpt> </wpt>
<rte> <rte>
<name>rte name</name> <name>rte name</name>
<cmt>cmt</cmt> <cmt>cmt</cmt>
<desc>desc</desc> <desc>desc</desc>
<src>src</src> <src>src</src>
<link href="https://new.link.rte"> <link href="https://new.link.rte">
<text>new text rte</text> <text>new text rte</text>
<type>hyperlink</type> <type>hyperlink</type>
</link> </link>
<number>1234</number> <number>1234</number>
<type>route</type> <type>route</type>
<extensions> <extensions>
<ext-1>value1</ext-1> <ext-1>value1</ext-1>
</extensions> </extensions>
<wpt lat="14.64736838389662" lon="7.93212890625"> <wpt lat="14.64736838389662" lon="7.93212890625">
<ele>10.0</ele> <ele>10.0</ele>
<time>2022-09-24T15:04:00+03:00</time> <time>2022-09-24T15:04:00+03:00</time>
<magvar>3.0</magvar> <magvar>3.0</magvar>
<geoidheight>45.0</geoidheight> <geoidheight>45.0</geoidheight>
<name>test point 1</name> <name>test point 1</name>
<cmt>comment 1</cmt> <cmt>comment 1</cmt>
<desc>description of point 1</desc> <desc>description of point 1</desc>
<src>source 1</src> <src>source 1</src>
<link href="http://link-to.site.href"> <link href="http://link-to.site.href">
<text>text</text> <text>text</text>
<type>hyperlink</type> <type>hyperlink</type>
</link> </link>
<link href="http://link2-to.site.href"> <link href="http://link2-to.site.href">
<text>text2</text> <text>text2</text>
<type>hyperlink2</type> <type>hyperlink2</type>
</link> </link>
<sym>sym 1</sym> <sym>sym 1</sym>
<type>type 1</type> <type>type 1</type>
<fix>dgps</fix> <fix>dgps</fix>
<sat>1</sat> <sat>1</sat>
<hdop>55.0</hdop> <hdop>55.0</hdop>
<vdop>66.0</vdop> <vdop>66.0</vdop>
<pdop>77.0</pdop> <pdop>77.0</pdop>
<ageofgpsdata>44</ageofgpsdata> <ageofgpsdata>44</ageofgpsdata>
<dgpsid>88</dgpsid> <dgpsid>88</dgpsid>
<extensions> <extensions>
<extension1 first="second" third="fours"></extension1> <extension1 first="second" third="fours"></extension1>
<extension2 aa="bb" cc="dd"></extension2> <extension2 aa="bb" cc="dd"></extension2>
</extensions> </extensions>
</wpt> </wpt>
</rte> </rte>
<trk> <trk>
<name>track 1</name> <name>track 1</name>
<cmt>comment track 1</cmt> <cmt>comment track 1</cmt>
<desc>desc track 1</desc> <desc>desc track 1</desc>
<src>src track 1</src> <src>src track 1</src>
null <number>1234</number>
<number>1234</number> <type>type 1</type>
<type>type 1</type> <trkseg>
null <trkpt lat="14.64736838389662" lon="7.93212890625">
<trkseg> <ele>10.0</ele>
<trkpt lat="14.64736838389662" lon="7.93212890625"> <time>2022-09-24T15:04:00+03:00</time>
<ele>10.0</ele> <magvar>3.0</magvar>
<time>2022-09-24T15:04:00+03:00</time> <geoidheight>45.0</geoidheight>
<magvar>3.0</magvar> <name>test point 1</name>
<geoidheight>45.0</geoidheight> <cmt>comment 1</cmt>
<name>test point 1</name> <desc>description of point 1</desc>
<cmt>comment 1</cmt> <src>source 1</src>
<desc>description of point 1</desc> <link href="http://link-to.site.href">
<src>source 1</src> <text>text</text>
<link href="http://link-to.site.href"> <type>hyperlink</type>
<text>text</text> </link>
<type>hyperlink</type> <link href="http://link2-to.site.href">
</link> <text>text2</text>
<link href="http://link2-to.site.href"> <type>hyperlink2</type>
<text>text2</text> </link>
<type>hyperlink2</type> <sym>sym 1</sym>
</link> <type>type 1</type>
<sym>sym 1</sym> <fix>dgps</fix>
<type>type 1</type> <sat>1</sat>
<fix>dgps</fix> <hdop>55.0</hdop>
<sat>1</sat> <vdop>66.0</vdop>
<hdop>55.0</hdop> <pdop>77.0</pdop>
<vdop>66.0</vdop> <ageofgpsdata>44</ageofgpsdata>
<pdop>77.0</pdop> <dgpsid>88</dgpsid>
<ageofgpsdata>44</ageofgpsdata> <extensions>
<dgpsid>88</dgpsid> <extension1 first="second" third="fours"></extension1>
<extensions> <extension2 aa="bb" cc="dd"></extension2>
<extension1 first="second" third="fours"></extension1> </extensions>
<extension2 aa="bb" cc="dd"></extension2> </trkpt>
</extensions> </trkseg>
</trkpt> </trk>
</trkseg> </gpx>
</trk> """.trim()
</gpx> .lineSequence()
""".trim(), .map {
gpxType.toXmlString(clock) it.trim()
) }
} .joinToString("\n"),
gpxType.toXmlString(clock)
)
} }
} }