fix extensions and attributes

This commit is contained in:
vcoppe
2024-04-16 13:02:22 +02:00
parent 3dc9b7d703
commit b5eebacc02
7 changed files with 1365 additions and 1163 deletions

View File

@@ -1,11 +1,11 @@
import { XMLParser } from "fast-xml-parser";
import { XMLParser, XMLBuilder } from "fast-xml-parser";
import { GPXFile } from "./types";
export function parseGPX(gpxData: string): GPXFile {
const parser = new XMLParser({
ignoreAttributes: false,
attributeNamePrefix: "",
removeNSPrefix: true,
attributesGroupName: 'attributes',
isArray: (name: string) => {
return name === 'trk' || name === 'trkseg' || name === 'trkpt' || name === 'wpt';
},
@@ -18,7 +18,7 @@ export function parseGPX(gpxData: string): GPXFile {
transformTagName(tagName: string) {
if (tagName === 'power') {
// Transform the simple <power> tag to the more complex <gpxpx:PowerExtension> tag, the nested <gpxpx:PowerInWatts> tag is then handled by the tagValueProcessor
return 'PowerExtension';
return 'gpxpx:PowerExtension';
}
return tagName;
},
@@ -32,30 +32,69 @@ export function parseGPX(gpxData: string): GPXFile {
return new Date(tagValue);
}
if (tagName === 'hr' || tagName === 'cad' || tagName === 'atemp' || tagName === 'PowerInWatts' || tagName === 'opacity' || tagName === 'weight') {
if (tagName === 'gpxtpx:hr' || tagName === 'gpxtpx:cad' || tagName === 'gpxtpx:atemp' || tagName === 'gpxpx:PowerInWatts' || tagName === 'opacity' || tagName === 'weight') {
return parseFloat(tagValue);
}
if (tagName === 'PowerExtension') {
if (tagName === 'gpxpx:PowerExtension') {
// Finish the transformation of the simple <power> tag to the more complex <gpxpx:PowerExtension> tag
// Note that this only targets the transformed <power> tag, since it must be a leaf node
return {
'PowerInWatts': parseFloat(tagValue)
'gpxpx:PowerInWatts': parseFloat(tagValue)
};
}
}
return tagValue;
},
transformAttributeName(attributeName) {
if (attributeName !== 'lat' && attributeName !== 'lon' && attributeName !== 'creator' && attributeName !== 'href') {
return `@_${attributeName}`;
}
return attributeName;
},
});
const parsed = parser.parse(gpxData);
return parsed.gpx;
}
export function buildGPX(gpx: GPXFile): string {
const builder = new XMLBuilder({
format: true,
ignoreAttributes: false,
attributeNamePrefix: "",
attributesGroupName: 'attributes',
suppressEmptyNode: true,
tagValueProcessor: (tagName: string, tagValue: unknown): string => {
if (tagValue instanceof Date) {
return tagValue.toISOString();
}
return tagValue.toString();
},
});
gpx.attributes.creator = 'https://gpx.studio';
gpx.attributes['version'] = '1.1';
gpx.attributes['xmlns'] = 'http://www.topografix.com/GPX/1/1';
gpx.attributes['xmlns:xsi'] = 'http://www.w3.org/2001/XMLSchema-instance';
gpx.attributes['xsi:schemaLocation'] = 'http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd http://www.garmin.com/xmlschemas/PowerExtension/v1 http://www.garmin.com/xmlschemas/PowerExtensionv1.xsd http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd';
gpx.attributes['xmlns:gpxtpx'] = 'http://www.garmin.com/xmlschemas/TrackPointExtension/v1';
gpx.attributes['xmlns:gpxx'] = 'http://www.garmin.com/xmlschemas/GpxExtensions/v3';
gpx.attributes['xmlns:gpxpx'] = 'http://www.garmin.com/xmlschemas/PowerExtension/v1';
gpx.attributes['xmlns:gpx_style'] = 'http://www.topografix.com/GPX/gpx_style/0/2';
gpx.metadata.author = {
name: 'gpx.studio',
link: {
attributes: {
href: 'https://gpx.studio',
}
}
};
return builder.build({
"?xml": {
attributes: {
version: "1.0",
encoding: "UTF-8",
}
},
gpx
});
}