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');
}
share|improve this question

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.