- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎07-21-2025 04:43 AM
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
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎07-21-2025 10:37 PM
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:
If my response helped please mark it correct and close the thread so that it benefits future readers.
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎07-21-2025 04:49 AM
ServiceNow doesn't have any function for that.
You will have to build your own solution
Something like this
var uglyXml = '<level1><level2><apple>content</apple><boo>something else</boo><level3><baba>other things</baba></level3><foo>hello</foo><something/></level2></level1>';
var pretty = prettyPrintXML(uglyXml);
gs.info('\n' + pretty);
function prettyPrintXML(xmlInput) {
// Remove spaces between tags
xmlInput = xmlInput.replace(/>\s*</g, '><');
var formatted = '';
var indent = '';
var indentStep = ' '; // 2 spaces per level
// Split by tags, but keep them
var xmlArr = xmlInput.replace(/</g, '~::~<').split('~::~');
for (var i = 0; i < xmlArr.length; i++) {
var node = xmlArr[i];
if (!node.trim()) continue;
if (node.match(/^<\//)) { // Closing tag: </foo>
indent = indent.substring(0, indent.length - indentStep.length);
formatted += indent + node + '\n';
} else if (node.match(/^<.*\/>$/)) { // Self-closing tag: <foo/>
formatted += indent + node + '\n';
} else if (node.match(/^<[^!?][^>]*>$/)) { // Opening tag: <foo>
formatted += indent + node + '\n';
indent += indentStep;
} else { // Text, comment, declaration
formatted += indent + node + '\n';
}
}
return formatted.trim();
}
Output:
If my response helped please mark it correct and close the thread so that it benefits future readers.
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎07-21-2025 08:29 PM
Hope you are doing good.
Did my reply answer your question?
If my response helped please mark it correct and close the thread so that it benefits future readers.
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎07-21-2025 09:57 PM
Hi Ankur,
the tag should end on the same line. Currently, it is ending on new line.
e.g. <apple> fruit </apple>
and not <apple> fruit
</apple>
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎07-21-2025 10:37 PM
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:
If my response helped please mark it correct and close the thread so that it benefits future readers.
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader