Welcome to Community Week 2025! Join us to learn, connect, and be recognized as we celebrate the spirit of Community and the power of AI. Get the details  

How to pretty print the XML.

Priyanka_77
Tera Contributor

I wan to develop one function which takes the XML as an input and returns an well formatted XML with indentation, just like how we do pretty print.

How can i do that?
Example:
<level1>
<level2>
<apple>content</apple>
<boo>something else</boo>
<level3>
<baba>other things</baba>
<level3>
<foo>hello</foo>
<something/>
<level2>
<level1>

Well formatted XML:
<level1>

 <level2>
   <apple>content</apple>
   <boo>something else</boo>
   <level3>
     <baba>other things</baba>
   </level3>
   <foo>hello</foo>
   <something />
  </level2>
</level1>

- sub levels are indented
- if the tag has no other tag the closing is at the end of line

1 ACCEPTED SOLUTION

@Priyanka_77 

this worked fine for me

function prettyPrintXML(xml) {
    xml = xml.replace(/>\s+</g, '><').trim(); // Remove whitespace between tags

    var result = '';
    var indentStep = '  ';
    var indent = '';

    // Split into nodes with regex, preserving text between tags
    var re = /(<[^>]+>|[^<]+)/g;
    var nodes = [];
    var match;
    while (match = re.exec(xml)) {
        // Remove empty text nodes
        if (match[0].trim() === '') continue;
        nodes.push(match[0]);
    }

    var i = 0;
    while (i < nodes.length) {
        var node = nodes[i];

        // Open tag
        var openTagMatch = node.match(/^<([a-zA-Z0-9_:.-]+)[^>]*>$/);
        if (openTagMatch) {
            // Check for the pattern: <tag>text</tag>
            if (
                i + 2 < nodes.length &&
                !nodes[i + 1].match(/^</) && // next node is text
                nodes[i + 2].match(new RegExp('^</'+openTagMatch[1]+'>\\s*$')) // and next-next node is matching close tag
            ) {
                result += indent + node + nodes[i + 1].trim() + nodes[i + 2] + '\n';
                i += 3;
                continue;
            } else {
                result += indent + node + '\n';
                indent += indentStep;
                i++;
                continue;
            }
        }

        // Close tag
        if (node.match(/^<\/[a-zA-Z0-9_:.-]+>/)) {
            indent = indent.substring(0, indent.length - indentStep.length);
            result += indent + node + '\n';
            i++;
            continue;
        }

        // Self-closing tag
        if (node.match(/^<[^>]+\/>$/)) {
            result += indent + node + '\n';
            i++;
            continue;
        }

        // Text or other stuff
        result += indent + node.trim() + '\n';
        i++;
    }
    return result.trim();
}

// EXAMPLE USAGE:
var uglyXml = '<level1><level2><apple>content</apple><boo>something else</boo><level3><baba>other things</baba></level3><foo>hello</foo><something/></level2></level1>';
gs.info('\n' + prettyPrintXML(uglyXml));

Output:

AnkurBawiskar_0-1753162638138.png

 

If my response helped please mark it correct and close the thread so that it benefits future readers.

Regards,
Ankur
✨ Certified Technical Architect  ||  ✨ 9x ServiceNow MVP  ||  ✨ ServiceNow Community Leader

View solution in original post

6 REPLIES 6

SumanthDosapati
Mega Sage
Mega Sage

@Priyanka_77 

 

You can use this simple script

var xmlString = 'your unformatted xml string here';

var xmlDoc = new XMLDocument(xmlString);
gs.info('\n' + xmlDoc.toIndentedString());  //This will print the formatted xml as string.

 

If you want to get xml from a gliderecord object, use below.

 var gr = new GlideRecord('incident');
 gr.get("0c5f3cece1b12010f877971dea0b1449");
 
 var xmlString = new GlideRecordXMLSerializer().serialize(gr); //this will be unformatted xml as string.

 

Accept the solution and mark as helpful if it does, to benefit future readers.
Regards,
Sumanth

 

Thanks - this worked for me!