Parsing xml using Node

Starting a new thread as there are number of bits of discussion on this so this will hopefully track all my progress as I get through - eventually being able to read xml directly into the custom module to use.

I've installed from the console into the custom module directory using npm install xml2js and that has created the required directories as per the guidance from @jean-emmanuel here
image

This is the extract from my custom module that lads ok without it.

//xml to json test

const xml2json = requireNative('xml2json');

var xmlStr = "<root><person><name>violin</name></person></root>";
var json = JSON.parse(xml2json.toJson(xmlStr))

console.log('xmlinput string - xmlStr' + xmlStr)
console.log('json' + json)

I thought at least I might get a bit through this before asking for some help but I've already hit a bump in the road as I'm getting this error on the console

I've tried it with require and requireNative but neither work and have also tried some examples that are on the npm pages.

The function's name is nativeRequire, sorry if I mislead you !

Hmmmm....

This is not specific to open stage control but rather a common issue when working with electron (the binary that ships node with open-stage-control) and what's called native modules (C++ modules that need to be compiled to work). You have two solutions:

1 . run open stage control using the version of node installed of your system (Running with node - Open Stage Control)

or

2 . rebuild the native modules by running this in the directory that contains the node_modules folder:

npx electron-rebuild -v v15.1.0

v15.1.0 is the version of electron that open-stage-control is packaged with as found here, it may change in a future version.

On windows you'll need to have a bunch of stuff installed to be able to electron-rebuild: nodejs-guidelines/windows-environment.md at master · microsoft/nodejs-guidelines · GitHub

1 Like

Thanks, will give it a go… well outside my comfort zone here…

Or 3 . use another node module that doesn't rely on native modules: xml-js instead of xml2json could well do the job: xml-js - npm

1 Like

I’ve just gone with xml2js and managed to create a JS object of a whole xml, stringify the object and print to the console!!!

Progress!!!

So I'm halfway there I think:

Using this code:

// convert XML to JSON using xml-js

var convert = nativeRequire('xml-js');

//accessing this small xml locally here
var localxml =
    '<?xml version="1.0" encoding="utf-8"?>' +
    '<note importance="high" logged="true">' +
    '    <title>THIS IS XML IN CUSTOM MODULE</title>' +
    '    <todo>Maybe a violin</todo>' +
    '    <todo>Play con sordino</todo>' +
    '</note>';

//now accessing an xml in a file structure

const fs = nativeRequire('fs');

const path = nativeRequire("path");
var xmlFromFile = fs.readFileSync(path.resolve(__dirname, "../BlankMap.expressionmap"));


//var xmlFromFile = fs.readFileSync('user.xml')
var options = { compact: true, spaces: 0};

var result1 = convert.xml2js(localxml, options);
var result2 = convert.xml2json(localxml, options);
var result3 = convert.xml2js(xmlFromFile, { compact: true, spaces: 0 });
var result4 = convert.xml2json(xmlFromFile, { compact: false, spaces: 0 });

console.log('-----------------------------------------------------------');
console.log('Result 1 - OBJECT IN CUSTOM MODULE' + result1,);
console.log('-----------------------------------------------------------');

console.log(' ');
console.log('-----------------------------------------------------------');
console.log('Result 2 - JSON FROM XML IN CUSTOM MODULE' + result2);
console.log('-----------------------------------------------------------');
console.log(' ');

console.log('-----------------------------------------------------------');
console.log('Result 3 - OBJECT FROM XML FILE IN FILE STRUCTURE' + result3,);
console.log('-----------------------------------------------------------');
console.log(' ');

console.log('-----------------------------------------------------------');
console.log('Result 4 - JSON FROM XML FILE IN FILE STRUCTURE' + result4);
console.log('-----------------------------------------------------------');

I have been able to get this to the console:

Now, what I can't work out how to do is extract the 3 blue circled bits of data.

this worked.

thank you very much.

much appreciated

i find these entries in the browser.

  1. open your generated json in the browser (i use chrome)
  2. hit F12 to open the chrome dev tools
  3. hit the network tab and then preview

this shows you the structure of your json file. when you found your needed entry, you can right click and copy the path to that entry like we had here. as in cubase expression maps it's always the same structure we can use this one:

yourID.InstrumentMap.member[1].list.obj[0].member[1].string.value,

obj[0] = expression 1
obj[1] = expression 2
.
.
.
.
hope this helps

1 Like

Awesome!!! Now we’re getting somewhere!!!

1 Like

do you know how we can call all objects at once?

example: doesn't work. but something like that

yourID.InstrumentMap.member[1].list.obj[0 - 30].member[1].string.value,```

The idea is to loop thorough the js or json and collect all the instrument map definitions and create a new object, then loop through all the expression maps in the directory to create a full set of objects. I can then use these objects in place of the text strings in my custom module.

This is tonight’s challenge but I’m away from my machine currently…

what do you mean by instrument map definitions?

sorry i'm not seeing through at the moment.

:crazy_face:

they are already defined... i guess my brain is to cloudy at the moment... :innocent:

Sorry I mean expression map definitions. I want to create one object that has all the expressions from a map in it.

this i already have but with lots of lines of code.

var art_niss_bassoons = [niss_bassoons.InstrumentMap.member[1].list.obj[0].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[1].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[2].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[3].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[4].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[5].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[6].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[7].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[8].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[9].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[10].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[11].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[12].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[13].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[14].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[15].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[16].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[17].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[18].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[19].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[20].member[1].string.value,
    niss_bassoons.InstrumentMap.member[1].list.obj[21].member[1].string.value];

do you know if we could write this shorter to get all articulations at once with one line of code (list.obj[0-22])

The problem that you have there is that each expression map has a different number of articulations and this also could change.

You need to first count the number in the map using code to get a value, say myTotalArts.

Then build an array somehow using a loop or similar…

for 
n = 1 to myTotalArts

niss_bassoons.InstrumentMap.member[1].list.obj[n].member[1].string.value,

Next n

All of the above is total pseudo code as I’m on a train currently with my phone but you get the idea.

Have a look here for info on array

Array structure

1 Like

ahhh...now i see. and how would you map it to the track then?

like that?:

if (track_Id = 'whatever') {
    art_whatever
}

i think that's what i saw in the other thread. never mind. just remembered.

You don’t need to map it to the track directly. You need to tell OSC what articulations to put in the buttons.

You extract a track Identifier to get the custom module to choose which map to use them custom module maps the buttons. I’d you put something In the track name in cubase that identifies which map you have assigned in cubase then you can extract that in OSC from the sysex that it’s sent.

For example - Cubase track name might be

Violins 1 map005

You send the name to OSC from cubase - get the cm to pull the map005 from the track name and then pull the articulations from the xml for map005 and send it to the buttons.

this works all as expected. i think i just did it the complicated way. i coded it for every track with the if statement. works fine but just never ends with copy pasting editing and all that stuff.

i guess i have to think the other way around with coding. i always start with the smallest and keep copy pasting it. :tired_face:
things are getting clearer now

thank you very much.

still on the train?