We're reclaiming inactive PDIs to keep them available for active builders. Learn what's changing, who's affected, and how to protect your work. Read More

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
Kilo Sage

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