Parse .tct file data into MRVS

TanviP003244604
Tera Contributor

Hi All,

I am working on a Service Catalog Item where I have an attachment type variable. My requirement is:

  • User uploads a .txt file through the attachment field

  • On file upload (onChange client script), I need to:

    • Read the file content

    • Parse the data

    • Populate a Multi Row Variable Set (MRVS) on the same form before submission


Sample file format:

p1xyz.DB.ATT.COM =
(DESCRIPTION =
  (ADDRESS =
    (PROTOCOL = TCP)
    (HOST = p1xyz-scan.c01.sbcglobal.net)
    (PORT = 1521)
  )
  (CONNECT_DATA =
    (SERVER = DEDICATED)
    (SERVICE_NAME = p1xyz.db.att.com)
  )
)

Expected MRVS Output:

Each block in the file should create one row in MRVS with:

  • Domain → p1xyz

  • Service → DB.ATT.COM

  • Description

(DESCRIPTION =
  (ADDRESS =
    (PROTOCOL = TCP)
    (HOST = p1xyz-scan.c01.sbcglobal.net)
    (PORT = 1521)
  )
  (CONNECT_DATA =
    (SERVER = DEDICATED)
    (SERVICE_NAME = p1xyz.db.att.com)
  )
)

Thanks in advance!

1 REPLY 1

pr8172510
Tera Guru

Hi @TanviP003244604,

I have implemented this exact requirement successfully. Here's the complete working solution:

  • Script Include - Parses the uploaded file

    var ParseTCTFile = Class.create();
    ParseTCTFile.prototype = Object.extendsObject(AbstractAjaxProcessor, {

        parseFile: function() {
            var attachmentSysId = this.getParameter('sysparm_attachment_id');
           
            if (!attachmentSysId && arguments[0]) {
                attachmentSysId = arguments[0];
            }
           
            if (!attachmentSysId) {
                return JSON.stringify({ error: 'No attachment ID provided' });
            }
           
            // Get content from sys_attachment_doc (Method 2 from test)
            var content = this.getContentFromDoc(attachmentSysId);
           
            if (!content || content == '') {
                return JSON.stringify({ error: 'Could not read file content' });
            }
           
            gs.info('File content: ' + content.substring(0, 200));
           
            // Parse the content
            var result = this.parseContent(content);
           
            gs.info('Parsed result: ' + JSON.stringify(result));
           
            return JSON.stringify(result);
        },
       
        getContentFromDoc: function(attachmentSysId) {
            try {
                var docGR = new GlideRecord('sys_attachment_doc');
                docGR.addQuery('sys_attachment', attachmentSysId);
                docGR.query();
               
                var content = '';
                while (docGR.next()) {
                    var data = docGR.getValue('data');
                    if (data) {
                        // Data is already plain text, no decoding needed
                        content += data;
                    }
                }
               
                return content;
            } catch(e) {
                gs.error('getContentFromDoc error: ' + e.message);
                return null;
            }
        },
       
        parseContent: function(content) {
            var result = [];
           
            // Remove BOM character if present
            if (content.charCodeAt(0) === 0xFEFF) {
                content = content.substring(1);
            }
           
            // Find the line with pattern "something = (DESCRIPTION..."
            var lines = content.split('\n');
            var found = false;
           
            for (var i = 0; i < lines.length; i++) {
                var line = lines[i].trim();
               
                // Look for line that has = and then ( after
                if (line.indexOf('=') > -1) {
                    var equalIndex = line.indexOf('=');
                    var key = line.substring(0, equalIndex).trim();
                    var parts = key.split('.');
                    var domain = parts[0] || '';
                    var service = parts.slice(1).join('.') || '';
                   
                    // Get the description (everything after the = sign)
                    var description = content.substring(content.indexOf(line) + line.length).trim();
                   
                    // Clean up description
                    description = description.replace(/\s+/g, ' ').trim();
                   
                    result.push({
                        domain: domain,
                        service: service,
                        description: description
                    });
                   
                    found = true;
                    break;
                }
            }
           
            // If no match found with above method, try simpler approach
            if (!found && lines.length > 0) {
                var firstLine = lines[0].trim();
                if (firstLine.indexOf('=') > -1) {
                    var key = firstLine.split('=')[0].trim();
                    var parts = key.split('.');
                    var domain = parts[0] || '';
                    var service = parts.slice(1).join('.') || '';
                    var description = content.substring(content.indexOf('=') + 1).trim();
                    description = description.replace(/\s+/g, ' ').trim();
                   
                    result.push({
                        domain: domain,
                        service: service,
                        description: description
                    });
                }
            }
           
            return result;
        },

        type: 'ParseTCTFile'
    });



     

  • onChange Client Script - Triggers when file is uploaded and populates MRVS

    function onChange(control, oldValue, newValue, isLoading) {
       
        if (isLoading) {
            return;
        }
       
        if (!newValue || newValue === '') {
            return;
        }
       
        // Clear previous messages
        g_form.clearMessages();
        g_form.showFieldMsg('connection_details', 'Processing file, please wait...', 'info');
       
        console.log('File uploaded - Attachment ID: ' + newValue);
       
        var ga = new GlideAjax('ParseTCTFile');
        ga.addParam('sysparm_name', 'parseFile');
        ga.addParam('sysparm_attachment_id', newValue);
       
        ga.getXMLAnswer(function(response) {
           
            console.log('Server response: ' + response);
           
            if (!response) {
                g_form.showFieldMsg('connection_details', 'Error: No response from server', 'error');
                return;
            }
           
            try {
                var data = JSON.parse(response);
               
                if (data.error) {
                    g_form.showFieldMsg('connection_details', 'Error: ' + data.error, 'error');
                    return;
                }
               
                if (!data || data.length === 0) {
                    g_form.showFieldMsg('connection_details', 'No data parsed from file. Check file format.', 'warning');
                    return;
                }
               
                // Format data for MRVS
                var rows = [];
                for (var i = 0; i < data.length; i++) {
                    rows.push({
                        domain: data[i].domain || '',
                        service: data[i].service || '',
                        description: data[i].description || ''
                    });
                }
               
                // Set MRVS value
                var mrvsJson = JSON.stringify(rows);
                g_form.setValue('connection_details', mrvsJson);
               
                console.log('MRVS set to: ' + mrvsJson);
               
                g_form.clearMessages();
                g_form.showFieldMsg('connection_details', '✓ Successfully loaded ' + data.length + ' row(s)', 'info');
               
            } catch(e) {
                console.error('Parse error: ' + e.message);
                g_form.showFieldMsg('connection_details', 'Error: ' + e.message, 'error');
            }
        });
    }
    pr8172510_0-1777213267279.png