I've created a vanilla JS function to indent XML strings so they can be more easily read. It uses some pretty nasty regex...yes, I know it's a cardinal sin for XML/HTML, but it works. For instance, this string...
<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><ns:getCourseResponse xmlns:ns="http://course.ws.blackboard" xmlns:ax212="http://course.ws.blackboard/xsd" xmlns:ax211="http://ws.platform.blackboard/xsd" /></soapenv:Body></soapenv:Envelope>
...would look like this after being passed through the function:
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns:getCourseResponse xmlns:ns="http://course.ws.blackboard" xmlns:ax212="http://course.ws.blackboard/xsd" xmlns:ax211="http://ws.platform.blackboard/xsd" />
</soapenv:Body>
</soapenv:Envelope>
Here's the function itself. What can I do to simplify it?
function formatXML(input) {
// PART 1: Add \n where necessary
// A) add \n between sets of angled brackets without content between them
// B) remove \n between opening and closing tags of the same node if no content is between them
// C) add \n between a self-closing set of angled brackets and the next set
// D) split it into an array
xmlString = input.trim()
.replace(/>\s*</g,'>\n<')
.replace(/(<[^\/>].*>)\n(<[\/])/g,'$1$2')
.replace(/(<\/[^>]+>|<[^>]+\/>)(<[^>]+>)/g,'$1\n$2');
xmlArr = xmlString.split('\n');
// PART 2: indent each line appropriately
var tabs = ''; //store the current indentation
var start = 0; //starting line
if (/^<[?]xml/.test(xmlArr[0])) start++; //if the first line is a header, ignore it
for (var i = start; i < xmlArr.length; i++) { //for each line
var line = xmlArr[i].trim(); //trim it just in case
if (/^<[/]/.test(line)) { // if the line is a closing tag
// remove one tab from the store
// add the tabs at the beginning of the line
tabs = tabs.replace(/.$/, '');
xmlArr[i] = tabs + line;
} else if (/<.*>.*<\/.*>|<.*[^>]\/>/.test(line)) { // if the line contains an entire node
// leave the store as is
// add the tabs at the beginning of the line
xmlArr[i] = tabs + line;
} else { // if the line starts with an opening tag and does not contain an entire node
// add the tabs at the beginning of the line
// and add one tab to the store
xmlArr[i] = tabs + line;
tabs += '\t';
}
}
//rejoin the array to a string and return it
return xmlArr.join('\n');
}