XSL processing a fragment in IE

2019-06-13 17:18发布

问题:

I am trying to use Javascript to transform part of a XML file to a single row of an HTML table. The thought is that I will create multiple rows in the table from multiple XML files. For Firefox and Opera, this nice little chunk of code works beautifully.

var resTable = document.createElement('table');

for (i = 0; i < xmlNames.length; i++)
{
  // code for IE
  if (window.ActiveXObject)
  {
  }
  // code for Mozilla, Firefox, Opera, etc.
  else if (document.implementation && document.implementation.createDocument)
  {
    xml=loadXMLDoc(xmlNames[i]);
    xsl=loadXMLDoc(xslName);
    xsltProcessor=new XSLTProcessor();
    xsltProcessor.importStylesheet(xsl);
    resultDocument = xsltProcessor.transformToFragment(xml,document);
    resTable.appendChild(resultDocument);
  }
}

document.getElementById("theDoc").appendChild(resTable);

The problem is that I have tried a thousand things in the "if IE" part, and nothing ever works. I've done a lot of googling, and browsing here before I asked, but to no avail. In fact, there is an unanswered question on SO that sounds very similar, but there were no responses and no resolution, so I was hoping someone would be able to help me out here..

I've been successful in getting an entire doc to transform on IE, but the fact that I want to do this as a fragment is whats causing my problem.. Any help would be much appreciated! Thanks!

Edit: Sorry I forgot to provide my loadXMLDoc function in case thats important. Here is is:

function loadXMLDoc(dname)
{
  if (window.XMLHttpRequest)
  {
    xhttp=new XMLHttpRequest();
  }
  else
  {
    xhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
  xhttp.open("GET",dname,false);
  xhttp.send("");
  return xhttp.responseXML;
}

回答1:

After much more trial and error, I came up with something that works. Here's what I did:

Create a xsltProcessor as usual, and call the transform method. This results in xsltProcessor.output being a HTML formatted string. Of course, I want a DOM element, so I had to convert the HTML string to a DOM. Luckily, because I'm the author of the XSL stylesheet too, I know exactly what I'm expecting to come back. In my case, the output HTML string would be some number of <tr>...</tr> elements. I initially tried setting my resTable (a table DOM element) innerHTML to the output string, but that did not work. I'm still not sure why, but it seems like it has something specific to do with the fact they were <tr>s and it wasn't able to be parsed when set to innerHTML outside the context of a table tag.

At any rate, I created a temporary div element and set ITs innerHTML to a string having the xsltProcessor's output string encased in a <table></table> tag. Now the temp div element is DOM table, which I then stepped through and grabbed just the child nodes (which are the tr nodes that the xsl processor returned in the first place). Seems kind of ridiculous to do all this, but it works, and thats the first time I can say that.. Here's the final version that works in all the browsers I've tested..

var resTable = document.createElement('table');

for (i = 0; i < xmlNames.length; i++)
{
  // code for IE
  if (window.ActiveXObject)
  {
    var xml = new ActiveXObject("Microsoft.XMLDOM");
    xml.async = false;
    xml.load(xmlNames[i]);

    var xslt = new ActiveXObject("Msxml2.XSLTemplate");
    var xsl = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.3.0");

    var xsltProcessor;
    xsl.async = false;
    xsl.resolveExternals = false;
    xsl.load(xslName);
    xslt.stylesheet = xsl;

    xsltProcessor = xslt.createProcessor();
    xsltProcessor.input = xml;

    //This transform results in one or more tr.../tr HTML tag(s)
    xsltProcessor.transform();

    //Create a temp div element which is used to convert the HTML
    //string to a DOM element so I can grab just the part I want..
    tmp = document.createElement('div');

    //Can't set innerHTML to tr tags directly I guess, so have to put
    //in context of a table so it can be parsed...
    tmp.innerHTML = "<table>" + xsltProcessor.output + "</table>";

    //Now I need to grad the tr children from inside the table node, since
    //the table was only to please the parser
    for (tmpChildInd = 0; tmpChildInd <  tmp.childNodes[0].childNodes.length;   tmpChildInd++)
    {
      //finally, append the temporary elements children (the tr tags) 
      //to the overall table I created before the loop.
      resTable.appendChild(tmp.childNodes[0].childNodes[tmpChildInd]);
    }  
  }
  // code for Mozilla, Firefox, Opera, etc.
  else if (document.implementation && document.implementation.createDocument)
  {
    xml=loadXMLDoc(xmlNames[i]);
    xsl=loadXMLDoc(xslName);
    xsltProcessor=new XSLTProcessor();
    xsltProcessor.importStylesheet(xsl);
    resultDocument = xsltProcessor.transformToFragment(xml,document);
    resTable.appendChild(resultDocument);
  }
}

//put the full table at the div location "theDoc" now..
document.getElementById("theDoc").appendChild(resTable);

Not sure how often folks try to do this, but hopefully this helps someone else out there..