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;
 | 
						|
}
 |