forked from cory/tildefriends
85 lines
2.1 KiB
JavaScript
85 lines
2.1 KiB
JavaScript
|
function xml_parse(xml) {
|
||
|
let result;
|
||
|
let path = [];
|
||
|
let tag_begin;
|
||
|
let text_begin;
|
||
|
for (let i = 0; i < xml.length; i++) {
|
||
|
let c = xml.charAt(i);
|
||
|
if (!tag_begin && c == '<') {
|
||
|
if (i > text_begin && path.length) {
|
||
|
let value = xml.substring(text_begin, i);
|
||
|
if (!/^\s*$/.test(value)) {
|
||
|
path[path.length - 1].value = value;
|
||
|
}
|
||
|
}
|
||
|
tag_begin = i + 1;
|
||
|
} else if (tag_begin && c == '>') {
|
||
|
let tag = xml.substring(tag_begin, i).trim();
|
||
|
if (tag.startsWith('?') && tag.endsWith('?')) {
|
||
|
/* Ignore directives. */
|
||
|
} else if (tag.startsWith('/')) {
|
||
|
path.pop();
|
||
|
} else {
|
||
|
let parts = tag.split(' ');
|
||
|
let attributes = {};
|
||
|
for (let j = 1; j < parts.length; j++) {
|
||
|
let eq = parts[j].indexOf('=');
|
||
|
let value = parts[j].substring(eq + 1);
|
||
|
if (value.startsWith('"') && value.endsWith('"')) {
|
||
|
value = value.substring(1, value.length - 1);
|
||
|
}
|
||
|
attributes[parts[j].substring(0, eq)] = value;
|
||
|
}
|
||
|
let next = {name: parts[0], children: [], attributes: attributes};
|
||
|
if (path.length) {
|
||
|
path[path.length - 1].children.push(next);
|
||
|
} else {
|
||
|
result = next;
|
||
|
}
|
||
|
if (!tag.endsWith('/')) {
|
||
|
path.push(next);
|
||
|
}
|
||
|
}
|
||
|
tag_begin = undefined;
|
||
|
text_begin = i + 1;
|
||
|
}
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
function* xml_each(node, name) {
|
||
|
for (let child of node.children) {
|
||
|
if (child.name == name) {
|
||
|
yield child;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export function gpx_parse(xml) {
|
||
|
let result = {segments: []};
|
||
|
let tree = xml_parse(xml);
|
||
|
if (tree?.name == 'gpx') {
|
||
|
for (let trk of xml_each(tree, 'trk')) {
|
||
|
for (let trkseg of xml_each(trk, 'trkseg')) {
|
||
|
let segment = [];
|
||
|
for (let trkpt of xml_each(trkseg, 'trkpt')) {
|
||
|
segment.push({
|
||
|
lat: parseFloat(trkpt.attributes.lat),
|
||
|
lon: parseFloat(trkpt.attributes.lon),
|
||
|
});
|
||
|
}
|
||
|
result.segments.push(segment);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
for (let metadata of xml_each(tree, 'metadata')) {
|
||
|
for (let link of xml_each(metadata, 'link')) {
|
||
|
result.link = link.attributes.href;
|
||
|
}
|
||
|
for (let time of xml_each(metadata, 'time')) {
|
||
|
result.time = time.value;
|
||
|
}
|
||
|
}
|
||
|
return result;
|
||
|
}
|