XML Transform : Firefox and IE
August 23rd, 2005After some trial and error, I have sorted out an XML transform that works for both Firefox and IE. This particular method is cobbled together from various methods I found around the web. I have tested this in IE and Firefox on the PC, and Firefox and Safari on the Mac. So far so good.
For starters, here’s all the stuff I used (and you might want) to get things working:
Dropping all of those in the same folder, and opening test.html should result in something like:
Colorado Rock Climbing
| Route | Grade | Type | Location | First Ascent |
|---|---|---|---|---|
| Bastille Crack | 5.7 | trad | El Dorado Canyon | Stan Shepard, Allen Bergen |
| Animal Magnetism | 5.11c | sport | Boulder Canyon | Ken Trout, Rick Leitner, and Kirk Mill |
| Kor’s Flake | 5.7 | trad | Lumpy Ridge | Layton Kor |
There are a lot of cool things you can do with transforms now that there are a lot of RSS feeds out there. For example, I put together a weather site and a newspaper site by grabbing some public RSS feeds.
The crux of this is, of course, is the transform. I generally think that the transform should be done on the server-side if possible. But more and more I find the need to do simple transforms on the client side. So to that end, I put together the following Javascript (also available in the html file above).
if(document.implementation && document.implementation.createDocument){
// *** Mozilla
var xsltProcessor = new XSLTProcessor();
// *** load the XSL file
var myXMLHTTPRequest = new XMLHttpRequest();
myXMLHTTPRequest.open("GET", "test.xsl", false);
myXMLHTTPRequest.send(null);
// *** get the XML document
xslStylesheet = myXMLHTTPRequest.responseXML;
xsltProcessor.importStylesheet(xslStylesheet);
// *** load the xml file
myXMLHTTPRequest = new XMLHttpRequest();
myXMLHTTPRequest.open("GET", "test.xml", false);
myXMLHTTPRequest.send(null);
var xmlSource = myXMLHTTPRequest.responseXML;
// *** transform
var resultDocument = xsltProcessor.transformToFragment(xmlSource, document);
document.getElementById("example").appendChild(resultDocument);
}else if(window.ActiveXObject){
// *** IE
// *** Load XML
xml = new ActiveXObject("MSXML2.DOMDocument");
xml.async = false
xml.load("test.xml")
// *** Load XSL
xsl = new ActiveXObject("MSXML2.DOMDocument");
xsl.async = false
xsl.load("test.xsl")
// *** Transform
document.getElementById("example").innerHTML=xml.transformNode(xsl);
}else{
// *** Browser unknown
alert("Browser unknown");
}
Basically, what is going on, is there are two different transforms. One for Firefox (and other modern browsers) and one for IE. They have different models for loading up the XML and XSL, and performing the transform. But in both cases, I stick the final resuts inside anther DIV, in this case a DIV with the ID “example”.
So far I’ve had good success wtih this, let me know if you run into problems…
Hi, I was looking at your code there.
I have a problem with the XMLHttpRequest in Firefox. If the URL of the request is not on the originating server of the page the request is not sucessful. So if load some xml and xslt from the same directory as the page I’m OK. If I try to pull the xml from somwhere else (an RSS feed, say) the XMLHttpRequest simply does not return.
Is this a sandboxing/security issue ?
Thanks.
Bert -
Yep, this is a security issue. You’re not allowed to get any content (XML, text etc) from a different domain with Javascript. There are a handful of workarounds that include iFrames etc. but they’re pretty clunky. Funny you mention this actually - I am working on a version of my solution right now. I’ll post it when it’s finalized. Maybe that’ll help.
Another solution is to do some server-side scripting (asp, php, jsp). On my weather page and newspaper page I use a bit of php to actually copy the RSS feed’s XML file to my local server (overwriting old versions), then do my XML transform.
Not great, but again, scripting cross-domain is just not allowed.
Hello,
my server recognises my xsl file as type text/plain while it should be text/xml. Any suggestion how and where to force the xsl file type recognotion into text/xml.
suggestions are appreciated
Bart -
Elaborate a bit… Are you generating the XSL with a scripting language (PHP/JSP/ASP)? Or is it just a static file (like what I’ve linked to above)?
It is static, like your example. I have found a work around. I just use .xml as the extension of my xsl file rather then the .xsl extension. It is a bit weird but it works. I still think my isp sends the wrong type with a xsl file from their server (text/plain vs text/xml or application/xhtml+xml). They don’t seem to see my point? I also tried to override server settings with a .htaccess file rule saying the .xsl extension files should be served as type=txt/xml, but that didn’t do the trick either. Any thoughts would be appreciated? It must be a common problem for more firefox developpers I would guess?
Hello there,
I’ve been working with AJAX for a few months today and I met a difficulty… not using it! I explain:
My web application is, on client-side, XHTML pages dealing with a Java/MySQL server part. AJAX helps me to keep any page loaded once instead of being reloaded after each user interaction with a component, which is really appreciable!
Though, some of these pages includes trees and are finally too slow to be loaded and I wondered how would be the performances if the XSL transformation is delegated to my server. Today I do not have the answer yet because I can not achieve to insert the transformed data into the DOM document of the page.
I juste wrote a wrapper named XSLTemplate which job is to transform XML (on client or server side according to a boolean parameter) and everything is ok on client-side, like before I got this freeky idea to transform the XSL on the server side.
I tried to use innerHTML to insert le transformed data into my page but with IE something displays but is odd and above all incomplete (no errors are popping by the way, very helpful…) and with FF the scripts tags do not seem to be executed… I tried to use the methods importNode / appendChild for FF too but when I call appendChild with the imported node as parameter FF just… crashes and closes… even without saying good bye ;)
Anyway, if no body as a clue for me, has someone test the difference of performaces between XSL transformation done by AJAX (browser) and by a server (in my case I use XALAN)? Is there a gap between the two results?
Thank you!
TigRoO:
As for the speed - doing the transform on the server will by much faster than doing the transform on the client. Especially if you’re transforming a lot of data (sounds like you are). I had a project a while back where my transform got bigger and bigger, and by moving it to the server the performance improved dramatically.
As for the error, I’m not sure what’s going on there… maybe if you have some code you could point to?
Yup !
Thank you for your rapid answer, I’m definitely convinced that server-side XSLT is faster. I just hope that I’ll succeed to resolve my problem.
- Let’s try to make it simple:
In my XSLTemplate wrapper the datas are retrieved with the responseText attribute, returned to my function which job is to display a tree for instance. When the datas are handled I call the appendFragment method of the target element wrapper which is doing the following code:
this.oHTMLNode.innerHTML += p_sFragment;
this.oHTMLNode being the raw DOM node, p_oFragment the transformed data as a string. Like this the <script/> tags seem to be “sleeping” but do exist (I can see them in the DOM inspector).
- The problem which lead me to try this method is the following:
Coming from my XSLTemplate wrapper again but, this time, using the responseXML attribute I call the appendFragment method with a DOM document object and process it like that:
var xFragment = p_oFragment.getElementsByTagName(”fragment”)[0];
var iIndex;
var oNode;
for(iIndex = 0; iIndex
Argh, sorry for that, my msg is cut! :P
Here is the missing part:
Argh… sorry again, I think I did not convert a “
LOL, sure it was a: “<”… ;)
< xFragment.childNodes.length; ++iIndex)
{
oNode = document.importNode(xFragment.childNodes[iIndex], false)
this.oHTMLNode.appendChild(oNode);
}
The call to importNode seems to be ok (I dumped the node in my console and there’s nothing particular to report) but the next call to importNode makes FF crash…
Wgy does this not want to work in Mozilla? I have tried various things but have not yet got it to work…..
Any help would be much appreciated.
Cy
Hi,
I am getting a problem in processing XML file using XSLT. I am using AJAX to get the XML file. I am trying to convert XML to HTML on client-side. The XML which I am receiving on client is fine. But after coverting it, i am only able to see half of the HTML which is static in XSL file.
Here is my funtion to load XML and XSL
function setMessage(message){
var xml = new ActiveXObject(”Microsoft.XMLDOM”);
xml.async = false;
alert(message);
//Load XSL
var xsl = new ActiveXObject(”Microsoft.XMLDOM”);
xsl.async = false;
xsl.load(xsl_url);
xml.onreadystatechange = function () {
if (xml.readyState == 4) alert(xml.transformNode(xsl));
};
xml.load(message);
blyr_add.innerHTML = xml.transformNode(xsl);
//blyr_add.innerHTML = message;
}
when i am displaying message it shows proper XML which I am sending from server. What could be the possible promble for this? Any suggestions?
In Safari 2.0.4 not work
I’ve been looking for this type of straight forward solution all day. I love how clean it is! This clarifies everything! Thanks for this.
I’ve tried this an multiple other ways to transform in FF, works fine in IE but with FF i continue to receive:
Error: uncaught exception: [Exception... "Component returned failure code: 0x80004003 (NS_ERROR_INVALID_POINTER) [nsIXSLTProcessor.importStylesheet]” nsresult: “0×80004003 (NS_ERROR_INVALID_POINTER)” location: “JS frame :: https://www.kc.us.army.mil/XML_XSLT/ArmyPub/army_pubs.js :: transDoc :: line 200″ data: no]
It’s driving me up the walls guys…anyhelp I’d GREATING appreciate!! ThankS!!!
Please take a look on http://www.losru.com.
This site is clear xml- xslt client site transform
based. Unfortunately it does not support mozilla so far. In IE the things can be simplifye even more. Just use the tag. It will supply the xml and xslt for you.
newbe needs much help.;-) I have an XML file that loads in IE just fine but not on my Mac in FF. I found your code and it works great however. I need to load images from XML to the HTML page. I don’t even know where to start.
Jan,
I’m not totally clear on what you’re trying to do. Does your XML file contain paths to the images? If so, your XSL just needs to write the image path, and insert the XML path (something like):
<xsl:template match=”yourXMLImageTags”>
<img src=”<xsl:value-of select=”@yourImagePath” />” />
</xsl:template match>
Feel free to post a link to your XML/XSL if they’re availalbe, and I’ll try to help.
November 7th at 10:58 am
#2 : Patrick Ryan
Bert -
Yep, this is a security issue. You’re not allowed to get any content (XML, text etc) from a different domain with Javascript. There are a handful of workarounds that include iFrames etc. but they’re pretty clunky. Funny you mention this actually - I am working on a version of my solution right now. I’ll post it when it’s finalized. Maybe that’ll help.
Another solution is to do some server-side scripting (asp, php, jsp). On my weather page and newspaper page I use a bit of php to actually copy the RSS feed’s XML file to my local server (overwriting old versions), then do my XML transform.
Not great, but again, scripting cross-domain is just not allowed.
========================
I have same problem can you provide me the latest verion which allow me to read xml file from diffrent domain with javascript.
Thanks.
Folks,
I tried the upper code, does the switch ok if viewed with IE but Firefox (or any other Mozilla), refuses to do the xsl/xml transform (it returns undefined) at this line:
var resultDocument = xsltProcessor.transformToFragment(resp, document);
‘resp’ is an xml string returned from the server. I also tried a physical xml file in there, in vain.
The xsl stylesheet is imported all fine (I checked the document type and the source), but that line REFUSES to do the transformation.
Any clue? Thanks!
Gabi.
I copied the files but the transformation does not happen in both IE and FF
Thank you! Haven’t implemented this yet, but it’s exactly what I’ve been looking for. Every other script I’ve tried was really buggy and didn’t work cross-browser.
I’m sorry to rake up an old thread…
This is a wonderful solution. Thank you, it’s working better than all other options I’ve been able to sort out for displaying XML in HTML.
I’m having one strange problem, that is more of a minor annoyance.
all the data is being transformed and displaying correctly… but it’s stripping all the vertical space from my styling.
For example all my cells are styled like this
td {line-height:1.5em;}
It styles perfectly when I put and example table in the HTML, but the table from the xsl doc strips the vertical space from that style. all other styles seem to be acting correctly. Only vertical space is being stripped. Padding, margin, line-height… all of em. very strange.
Any thoughts?
Rustin,
That’s very strange.. But I can’t reproduce it. I tried line-height inline, as well as in block at the top of the page. Firefox picked ‘em both up.
What browser/OS? Can you put an example up somewhere?
that might be my problem.. I’m using an external style sheet. Maybe it’s just not cascading correctly.
I’ll try inline and see what I get.
Thanks!
Thanks for this patrick…
As it turns out, my problem was all CSS, had nothing to do with the script. I have a reset stylesheet that was taking precedence over the inline style.
Somehow I thought it cascaded the other direction… but oh well. All fixed now.
This looks like interesting code and it works on my machine, but can you please elaborate on the purpose? If I open the .xml file directly, it displays fine in Firefox; I don’t need the .html file…
Hi. I would like to create my own RSS reader using Javascript / VBscript. I am not very much familiar to dealing with XML. Could you please help me with the code??? Mail me code on sagargeminimumbai at yahoo dot com. Thanks!!