tk-dwml-to-json
Version:
A fork of simple DWML parser by tkafka
107 lines (97 loc) • 3.68 kB
JavaScript
import parse from "xml-parser";
import _ from "underscore";
import locationParser from "./dwml-data-parsers/location.js";
import parameterParser from "./dwml-data-parsers/parameter.js";
import timeLayoutParser from "./dwml-data-parsers/time-layout.js";
/**
* The way I've chosen to parse DWML environmental data is to do the following:
* 1. Parse out the time-layouts per time-layout-key
* 2. Parse parameters, grouped by location-id, with time-layout data mixed in (as each param has a time-layout-key)
* 3. Parse out the location metadata (grouped by location-id)
* 4. Merge location metadata and parameters (given that they're both grouped by location-id)
*
* @typedef {Object} DwmlDataSubtreeParser
* @property {function(Object, import('./dwml-parser.js').DwmlParserOptions=): Object} parse - Parse DWML data subtree
* @property {function(Array): Object} _getLocations - Extract locations
* @property {function(Array, Object, import('./dwml-parser.js').DwmlParserOptions=): Object} _getParameters - Extract parameters
* @property {function(Array): Object} _getTimeLayouts - Extract time layouts
* @property {function(Object, Object): Object} _mergeLocationsAndParameters - Merge locations and parameters
* @property {function(Array): Object} _unwrap - Unwrap array of objects
*/
/**
* @type {DwmlDataSubtreeParser}
*/
const dwmlDataSubtreeParser = {
/**
* @param {Object} dwmlDataSubtree
* @param {import('./dwml-parser.js').DwmlParserOptions} [options={}] - optional config object with parsing options
* @returns {Object}
*/
parse: function (dwmlDataSubtree, options = {}) {
// Add time data into parameters as we parse them
const timeLayouts = this._getTimeLayouts(dwmlDataSubtree.children);
const parameters = this._getParameters(
dwmlDataSubtree.children,
timeLayouts,
options,
);
const locations = this._getLocations(dwmlDataSubtree.children);
return this._mergeLocationsAndParameters(locations, parameters);
},
_getLocations: function (dataSets) {
const locationDataSets = _.where(dataSets, { name: "location" });
const locationsArray = _.map(
locationDataSets,
locationParser.parse.bind(locationParser),
);
return this._unwrap(locationsArray);
},
/**
* @param {Array} dataSets - data sets to process
* @param {Object} timeLayouts - time layouts
* @param {import('./dwml-parser.js').DwmlParserOptions} [options={}] - optional configuration options
* @returns {Object} - processed parameters
*/
_getParameters: function (dataSets, timeLayouts, options = {}) {
const parameterDataSets = _.where(dataSets, { name: "parameters" });
const parametersArray = _.map(parameterDataSets, (parameterDataSet) =>
parameterParser.parse(timeLayouts, parameterDataSet, options),
);
return this._unwrap(parametersArray);
},
_getTimeLayouts: function (dataSets) {
const timeLayoutDataSets = _.where(dataSets, { name: "time-layout" });
const timeLayoutArray = _.map(
timeLayoutDataSets,
timeLayoutParser.parse.bind(timeLayoutParser),
);
return this._unwrap(timeLayoutArray);
},
_mergeLocationsAndParameters: (locations, parameters) => {
return _.reduce(
locations,
(memo, location, locationKey) => {
memo[locationKey] = {
location: location,
values: parameters[locationKey],
};
return memo;
},
{},
);
},
/**
* @param {Array} arrayOfObjects - eg: [ { point1: {}, point2: {} } ]
* @return {Object} - eg: { point1: {}, point2: {} }
*/
_unwrap: (arrayOfObjects) => {
return _.reduce(
arrayOfObjects,
(memo, object) => {
return _.extend(memo, object);
},
{},
);
},
};
export default dwmlDataSubtreeParser;