TheAuzzieJesus TheAuzzieJesus - 3 months ago 77
Ajax Question

XSLT and XML content not loading in Microsft Edge and Internet Explorer Browsers Issue

I've noticed that the following JavaScript code doesn't seem to be loading any XML or XSLT data from their corresponding files into either Internet Explorer or Microsoft Edge browsers, and I'm not sure what I've written incorrectly.

Below are the two JavaScript functions I am using to load the content..

function loadXMLDoc(filename) {
if (window.ActiveXObject) {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
else {
xhttp = new XMLHttpRequest();
}
xhttp.open("GET", filename, false);
try {
xhttp.responseType = "msxml-document"
} catch (err) {
} // Helping IE11
xhttp.send("");
return xhttp.responseXML;
}

function displayXMLDoc(xml_file, xsl_file, element_id) {
xml = loadXMLDoc(xml_file);
xsl = loadXMLDoc(xsl_file);

// BROWSER IS IE / EDGE.
if (window.ActiveXObject) {
ex = xml.transformNode(xsl);
document.getElementById(element_id).innerHTML = ex;
}
else if (document.implementation && document.implementation.createDocument) {
var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsl);
var resultDocument = xsltProcessor.transformToFragment(xml, document);
document.getElementById(element_id).appendChild(resultDocument);
}
}


And here is how these functions are being called...

<body onload="displayXMLDoc('myfile.xml', 'myfile.xsl', 'myoutput');">


PLEASE NOTE:

The code is currently working for all other browsers, for example, in FireFox and Chrome.

Answer

Considering that current versions of Edge, Chrome and Firefox support Promise one approach these days is to use a library to have Promise support in IE and that way use promises to handle the asynchronous loading of the XML and XSLT documents. That way the code to load an XML document and and XSLT document and apply an XSLT transformation to get an HTML result, with an option to set some XSLT parameters, looks as follows:

 function loadDoc(url) {
       return new Promise(function(resolve) {
         var req = new XMLHttpRequest();
         req.open("GET", url);
         if (typeof XSLTProcessor === 'undefined') {
           try {
             req.responseType = 'msxml-document';
           }
           catch (e) {}
         }
         req.onload = function() {
           resolve(this.responseXML)
         }
         req.send();
       });
  }

  function transform(xmlUrl, xslUrl, xsltParams, targetElement) {
    Promise.all([loadDoc(xmlUrl), loadDoc(xslUrl)]).then(function(data) {
      var xmlDoc = data[0];
      var xslDoc = data[1];

      if (typeof XSLTProcessor !== 'undefined') {
        var proc = new XSLTProcessor();
        proc.importStylesheet(xslDoc);

        for (var prop in xsltParams) {
          proc.setParameter(null, prop, xsltParams[prop]);
        }

        var resultFrag = proc.transformToFragment(xmlDoc, targetElement.ownerDocument);

        targetElement.textContent = '';
        targetElement.appendChild(resultFrag);
      }
      else {
          var template = new ActiveXObject('Msxml2.XslTemplate.6.0');
          template.stylesheet = xslDoc;
          var proc = template.createProcessor();

          for (var prop in xsltParams) {
            proc.addParameter(prop, xsltParams[prop]);
          }

          proc.input = xmlDoc;

          proc.transform();

          var resultHTML = proc.output;

          targetElement.innerHTML = resultHTML;
      }
    });
  }

It can then be called as

transform('file.xml', 'input.xsl', { ids : 'test_value2'}, document.getElementById('d1'));

where the third argument is a Javascript objects with any parameters to set for the XSLT stylesheet, for instance if the XSLT is

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <!-- pass in a string with a single id value for the parameters ids or a '|' separated list of ids -->
    <xsl:param name="ids" select="''"/>

    <xsl:output method="html" indent="yes"/>

    <xsl:template match="/">

        <xsl:for-each select="products/test[$ids = '' or contains(concat('|', $ids, '|'), id)]">
            <a href="#"> Hello # <xsl:value-of select="value"/></a>
        </xsl:for-each>

    </xsl:template>
</xsl:stylesheet>

then the above Javascript snippets sets that ids parameter.

An XML input sample is

<?xml version="1.0" encoding="UTF-8"?>
<products>

    <test>
        <id>test_value1</id>
        <value>1</value>
    </test>

    <test>
        <id>test_value2</id>
        <value>2</value>
    </test>

</products>

Online sample working with current versions of IE, Edge, Chrome and Firefox on Windows 10 is at http://home.arcor.de/martin.honnen/xslt/test2016081501.html.

A working code snippet is

      function loadDoc(url) {
           return new Promise(function(resolve) {
             var req = new XMLHttpRequest();
             req.open("GET", url);
             if (typeof XSLTProcessor === 'undefined') {
               try {
                 req.responseType = 'msxml-document';
               }
               catch (e) {}
             }
             req.onload = function() {
               resolve(this.responseXML)
             }
             req.send();
           });
      }
      
      function transform(xmlUrl, xslUrl, xsltParams, targetElement) {
        Promise.all([loadDoc(xmlUrl), loadDoc(xslUrl)]).then(function(data) {
          var xmlDoc = data[0];
          var xslDoc = data[1];
          
          if (typeof XSLTProcessor !== 'undefined') {
            var proc = new XSLTProcessor();
            proc.importStylesheet(xslDoc);
            
            for (var prop in xsltParams) {
              proc.setParameter(null, prop, xsltParams[prop]);
            }
            
            var resultFrag = proc.transformToFragment(xmlDoc, targetElement.ownerDocument);
            
            targetElement.textContent = '';
            targetElement.appendChild(resultFrag);
          }
          else {
              var template = new ActiveXObject('Msxml2.XslTemplate.6.0');
              template.stylesheet = xslDoc;
              var proc = template.createProcessor();
              
              for (var prop in xsltParams) {
                proc.addParameter(prop, xsltParams[prop]);
              }
              
              proc.input = xmlDoc;
              
              proc.transform();
              
              var resultHTML = proc.output;
              
              targetElement.innerHTML = resultHTML;
          }
        });
      }
      
      document.addEventListener('DOMContentLoaded', function() {
        transform('http://home.arcor.de/martin.honnen/cdtest/test2016081501.xml', 'http://home.arcor.de/martin.honnen/cdtest/test2016081501.xsl', { ids : 'test_value2'}, document.getElementById('d1'));
      })
<script src="https://www.promisejs.org/polyfills/promise-7.0.4.min.js"></script>

    <h1>Testing XSLT transformation</h1>
    <div id="d1"></div>

Comments