Rocket Modern Experience (formerly LegaSuite)

 View Only

 Read an XML and store the data in a structure using Engine side javascript

Ameer Salman's profile image
Ameer Salman posted 11-06-2024 02:54

Hi,

I have a requirement where I need to read an XML file inside my project through engine-side Javascript and store that value in a structure. The XML contains the screen name and its function keys list.  However, I am not able to parse the XML file. Can anyone provide a solution for this?

Below I have attached the code for your reference

Engine Side Javascript:
-----------------------------

collect_FunctionKeys_From_Xml_File(screenName){
   const path = 'I have the given the full path of the XML file here';
   console.log("Is Exists....", fs.exists(' XML path'));
       try {
        const xmlString = fs.readFile(path);
        console.log("xmlString.......", xmlString);
        const parser = new DOMParser();  --> I am facing issue in this line. I am not able to parse the XML 
        const xmlDoc = parser.parseFromString(xmlString, "text/xml");
        console.log("xmlDoc.......", xmlDoc);
        // Find the screen with the matching name
        const screens = xmlDoc.Screens.Screen;
        const screen = screens.find(s => s.Name[0] === screenName);

        if (screen && screen.FunctionKeys && screen.FunctionKeys[0].Key) {
              const functionKeys = screen.FunctionKeys[0].Key.map(key => ({
                     fKey: key.FKey[0],
                     description: key.Description[0]
              }));
       }
        console.log(Function Keys for ${screenName}:, functionKeys);
        return functionKeys;
       } catch (error) {
        console.log("error", error);
   }
}

Sample XML:
----------------
<FunctionKeysList>
<Screens>
       <Screen>
           <Name>Screen1</Name>
           <FunctionKeys>
               <Key>
                   <FKey>F1</FKey>
                   <Description>F1 Description</Description>
               </Key>
           </FunctionKeys>
       </Screen>
       <Screen>
           <Name>Screen2</Name>
           <FunctionKeys>
            <Key>
                   <FKey>Help</FKey>
                   <Description>Help</Description>
               </Key>
               <Key>
                   <FKey>F3</FKey>
                   <Description>F3 Description</Description>
               </Key>
               <Key>
                   <FKey>F4</FKey>
                   <Description>F4 Description</Description>
               </Key>
               <Key>
                   <FKey>F5</FKey>
                   <Description>F5 Description</Description>
               </Key>
               <Key>
                   <FKey>F6</FKey>
                   <Description>F6 Description</Description>
               </Key>
           </FunctionKeys>
       </Screen>
</Screens>
</FunctionKeysList>

Roger Van Valen's profile image
Roger Van Valen

Hi Ameer,

Unfortunately there is no built-in DOMParser or XML parser available in Rocket MX engine side JavaScript at the moment.

Are you bound to the import format, or is the format free?

As example, JavaScript is very friendly with JSON. So if the format is free and the structure can be created in JSON instead of XML the code would be relatively easy:
Sample JSON data:

{ 
  "FunctionKeyList": {
    "Screens": [
      {
        "Name" : "Screen1",
        "FunctionKeys": [
          {
            "Fkey": "F1",
            "Description": "F1 Description"
          }
        ]
      },
      {
        "Name" : "Screen2",
        "FunctionKeys": [
          {
            "Fkey": "Help",
            "Description": "Help"
          },
          {
            "Fkey": "F3",
            "Description": "F3 Description"
          },
          {
            "Fkey": "F4",
            "Description": "F4 Description"
          },
          {
            "Fkey": "F5",
            "Description": "F5 Description"
          },
          {
            "Fkey": "F6",
            "Description": "F6 Description"
          }
        ]
      }  
    ]
  }
}

(And this example could even be simplified by removing the FunctionKeyList directive at start))

The code to read and parse this, could be something like:

/* import the file system api for file handling */
import * as fs from 'mx:fs';

let fullpath = script.environment.pckgdir + 'Resources/sample.json';
let file_contents = fs.readTextFile(fullpath);
let functionkeylist = JSON.parse(file_contents);
let screens = functionkeylist.FunctionKeyList.Screens;
screens.forEach((s) => {
	console.log(JSON.stringify(s));
});

The console output would be:

INFO  javascript.console - {"Name":"Screen1","FunctionKeys":[{"Fkey":"F1","Description":"F1 Description"}]} 
INFO  javascript.console - {"Name":"Screen2","FunctionKeys":[{"Fkey":"Help","Description":"Help"},{"Fkey":"F3","Description":"F3 Description"},{"Fkey":"F4","Description":"F4 Description"},{"Fkey":"F5","Description":"F5 Description"},{"Fkey":"F6","Description":"F6 Description"}]} 

If the source format needs to be XML (for instance for existing files or for files let me know and I can have a look if we have example code or if there are JavaScript modules available that can help.

Regards,

Roger.

Roger Van Valen's profile image
Roger Van Valen

Hi Ameer,

It is possible to use a third-party XML parser. As example you can use fast-xml-parser:
https://cdnjs.com/libraries/fast-xml-parser

When you download this javascript file from the URL, you can take the last comment line out:

//# sourceMappingURL=fxparser.min.js.map

As that line is used for the mapping in browsers. Not required for use in engine side JavaScript.

Next you will need to add an export line to use it as module in our JavaScript:

export {XMLParser};

That line can be added at the end of the js file.

I've placed this js file then in a 'mod' folder in my project, for instance as:
Scripts/Engine/mod/fsxparser.js

Now it is possible to import this module and use it, just like you would use the DOMParser.
Note that the syntax can be different, you can look up the fast-xml-parser documentation on their site.

The code to parse your example XML could be something like this now:

// import the file system api for file handling 
import * as fs from 'mx:fs';
// import the XML parser object (created from fast-xml-parser) 
import {XMLParser} from '/mod/fxparser.js';

let fullpath = script.environment.pckgdir + 'Resources/sample.xml';
let file_contents = fs.readTextFile(fullpath);

const xml_parser = new XMLParser({
	ignoreAttributes: true,
	ignorePiTags: true,
	ignoreDeclaration: true,
	trimValues: true,
});

let contents_obj = xml_parser.parse(file_contents);
let screens = contents_obj.FunctionKeysList.Screens.Screen;

screens.forEach((s) => {
	console.log(JSON.stringify(s));
});

Which will give the following output on the console:

INFO  javascript.console - {"Name":"Screen1","FunctionKeys":{"Key":{"FKey":"F1","Description":"F1 Description"}}} 
INFO  javascript.console - {"Name":"Screen2","FunctionKeys":{"Key":[{"FKey":"Help","Description":"Help"},{"FKey":"F3","Description":"F3 Description"},{"FKey":"F4","Description":"F4 Description"},{"FKey":"F5","Description":"F5 Description"},{"FKey":"F6","Description":"F6 Description"}]}} 

Hope this helps,

Regards,

Roger.