3

I'm looking for an elegant solution to transform CSV files based on specific template into hierarchical XML file in Node/Express server.

Eg : CSV of Type Template "Location"

Name,Lat,Lon,Timezone
name,lat,lon,timezone

should be transformed to something like the following:

<Location>
<Name>name<Name/>
<Address>
<Lat>lat</Lat>
<Lon>lon</Lon>
</Address>
<Timezone>timezone</Timezone>
</Location>

Few additional notes:

  1. This XML conforms to be a schema defined by an XSD.
  2. This is just a small sample of many template types

1 Answers1

0

Here is a solution based on CSV parser https://github.com/peterthoeny/parse-csv-js that creates a grid (array of arrays), and some simple code to generate XML based on the grid. This solution works in the browser, as well as in Node.js/Express:

function parseCsv(data, fieldSep, newLine) {
    fieldSep = fieldSep || ',';
    newLine = newLine || '\n';
    var nSep = '\x1D';
    var qSep = '\x1E';
    var cSep = '\x1F';
    var nSepRe = new RegExp(nSep, 'g');
    var qSepRe = new RegExp(qSep, 'g');
    var cSepRe = new RegExp(cSep, 'g');
    var fieldRe = new RegExp('(?<=(^|[' + fieldSep + '\\n]))"(|[\\s\\S]+?(?<![^"]"))"(?=($|[' + fieldSep + '\\n]))', 'g');
    var grid = [];
    data.replace(/\r/g, '').replace(/\n+$/, '').replace(fieldRe, function(match, p1, p2) {
        return p2.replace(/\n/g, nSep).replace(/""/g, qSep).replace(/,/g, cSep);
    }).split(/\n/).forEach(function(line) {
        var row = line.split(fieldSep).map(function(cell) {
            return cell.replace(nSepRe, newLine).replace(qSepRe, '"').replace(cSepRe, ',');
        });
        grid.push(row);
    });
    return grid;
}

const csv = 'London,0.1278° W,51.5074° N,Europe/London\n'
          + 'New York,74.0060° W,40.7128° N,America/New_York\n';
var grid = parseCsv(csv);
console.log('==> grid: ' + JSON.stringify(grid, null, ' '));
var xml = grid.map(function(row) {
  return '<Location>\n'
    + '<Name>' + row[0] + '<Name/>\n'
    + '<Address>\n'
    + '<Lat>' + row[1] + '</Lat>\n'
    + '<Lon>' + row[2] + '</Lon>\n'
    + '</Address>\n'
    + '<Timezone>' + row[3] + '</Timezone>\n'
    + '</Location>\n'
}).join('');
console.log('==> xml:\n' + xml);

Console output:

==> grid: [
 [
  "London",
  "0.1278° W",
  "51.5074° N",
  "Europe/London"
 ],
 [
  "New York",
  "74.0060° W",
  "40.7128° N",
  "America/New_York"
 ]
]
==> xml:
<Location>
<Name>London<Name/>
<Address>
<Lat>0.1278° W</Lat>
<Lon>51.5074° N</Lon>
</Address>
<Timezone>Europe/London</Timezone>
</Location>
<Location>
<Name>New York<Name/>
<Address>
<Lat>74.0060° W</Lat>
<Lon>40.7128° N</Lon>
</Address>
<Timezone>America/New_York</Timezone>
</Location>
Peter Thoeny
  • 7,379
  • 1
  • 10
  • 20
  • Thanks for this but the caveat with this approach is you till have to manually parse and transform individual fields, I was looking for something that would auto build XML based on XSD. – RedVelocity Jul 21 '20 at 05:21
  • Maybe this helps? https://stackoverflow.com/questions/29367474/build-xml-based-on-xml-schema-in-node-js – Peter Thoeny Jul 21 '20 at 16:55