Caching client-side XSLT imports in Internet Explorer - javascript

I'm transforming an XML document with XSLT in Internet Explorer 7. My XSLT imports/includes -- I've tried both -- another XSLT with the following line:
<xsl:import href="utils.xsl" />
This results in an HTTP request for the included file every time the including XSLT is used, even if a reference to the parent XSLT is cached and re-used. IE sends a Pragma: no-cache header on each request for the import/include request.
Is it possible to prevent these repeated HTTP requests?
Can I get IE to cache the file in the client?
If not, can I get IE to send an "If-Modified-Since" header?
For completeness, here's the corresponding transformation JavaScript:
var XMLUtil = {
// transforms the sourceStr using the given xslDoc
transformString: function(sourceStr, xslDoc /*XMLDOM doc*/) {
var sourceDoc = XMLUtil.loadFromString(sourceStr);
var resultDoc = new ActiveXObject("Microsoft.XMLDOM");
sourceDoc.transformNodeToObject(xslDoc, resultDoc);
return resultDoc;
},
// creates an XMLDOM document from a string containing XML
loadFromString: function(xml) {
var doc = new ActiveXObject("Microsoft.XMLDOM");
doc.async = false;
doc.loadXML(xml);
if (doc.parseError.errorCode != 0)
throw "Error parsing XML: " + doc.parseError.errorCode;
return doc;
}
}

The responses to a similar question recommends setting ForcedResync to false.
But Qi Samuel Zhang's response cautions
ForcedResync should work for most
cases, but the ForcedResync in MSXML3
has known issues to mitigate backward
compatibility, please use
MSXML2.DOMDocument.6.0 when possible.

Related

Internet Explorer 8 parse XML doesn`t work on huge response size

I have a huge page with really lots of data. Sometimes I need to reload this data using Ajax, so ajax request:
if (window.XMLHttpRequest) {
this._request = new XMLHttpRequest();
} else {
this._request = new ActiveXObject("Microsoft.XMLHTTP");
Then, I access this data with request.responseXML. I faced a problem, when size of responsibility more than 800k characters.
IE doesnt generate responseXML, its just empty XMLObject, but in responseText everithing is OK. I`ve tried to parse XML using the following code:
if (request.responseXML) {
var responseXML = request.responseXML;
//TODO: for huge xml responses some versions of IE can't automaticly parse XML
if (O$.isExplorer && responseXML && !responseXML.firstChild) {
var originalResponseText = request.responseText;
if (window.DOMParser) {
var parser = new DOMParser();
responseXML = parser.parseFromString(originalResponseText, 'text/xml');
} else {
responseXML = new ActiveXObject("Microsoft.XMLDOM");
responseXML.async = false;
responseXML.loadXML(originalResponseText);
}
}
But I faced the same problem.
Then, I tried to parse XML using jQuery:
responseXML = jQuery.parseXml(request.responseXML);
But the problem is still the same, everything is fine when the response length small, but for huge response I still get empty XML object with the parse error inside.
errorCode : -2147467259
filepos : 814853
reason : “Unspecified error\r\n”;
I check those position inside response string and everything is correct, just some ordinal symbol. Also I’ve recheck XML lots of time and I am sure that it’s valid. I don’t know what to do at all.
Also I tried to write my own xml parser, but I think that this is problem has more simple solution.
Thanks in Advance.
It would seem that IE notoriously has difficulties parsing XML data, and there may not be that much you can really do about it. A work around is that you can try to parse the XML data with IE, and if it fails, construct a new parser that will construct XML data out of the plaintext (which as you mentioned will work seemingly regardless of size). Take a look at the similar problem and answer here. It boils down to (pseudocode)
function() {
var XMLdata = reponse.XMLdata;
If (XMLdata.error) {
var parser = construct new DOMParser;
XMLdata = parser.XMLparse(response.plaintext);
}
return XMLdata;
}

Load local xml file using javascript in Google Chrome

I think until v5 of Google Chrome the below code worked. Now in the latest version I get the following error when opening my webpage locally:
"XMLHttpRequest cannot load file:///C:/Temp/Course.xml. Cross origin requests are only supported for HTTP."
The Javascript code:
function getXmlDocument(sFile) {
var xmlHttp, oXML;
// try to use the native XML parser
try {
xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", sFile, false); // Use syncronous communication
xmlHttp.send(null);
oXML = xmlHttp.responseXML;
} catch(e) {
// can't use the native parser, use the ActiveX instead
xmlHttp = getXMLObject();
xmlHttp.async = false; // Use syncronous communication
xmlHttp.resolveExternals = false;
xmlHttp.load(sFile);
oXML = xmlHttp;
}
// return the XML document object
return oXML;
}
// get the best ActiveX object that can read XML
function getXMLObject() {
// create an array with the XML ActiveX versions
var aVersions = new Array("Msxml2.DOMDocument.6.0", "Msxml2.DOMDocument.3.0");
// loop through the array until we can create an activeX control
for (var i=0; i<aVersions.length; i++) {
// return when we can create the activeX control
try {
var oXML = new ActiveXObject(aVersions[i]);
return oXML;
}
catch(e) {
}
}
// could not create an activeX, return a null
return null;
}
I really don't want to be forced to open the web page from a web server every time.
Local file access is disabled by default for security reasons. Try starting Google Chrome from the command line with the argument --allow-file-access
It would be more secure if you just start a local webserver and fetch your html and xml from localhost.
You can easily avoid deploying of the files by just let the server serve the contents of a local folder in which you place your xml.
This way you avoid
having to start chrome in an unsecure mode
having problems when you later deploy your app to a server on the internet
server to go is an example for an easy to install webserver http://www.server2go-web.de/

xslt with xpath that get some information from xml file doesn't work in JavaScript

I've got an xml file. It is meant for being transformed by xslt processor. The specific template is ready, however it use some information from two additional xml files. All information is used to produce the proper output.
It works fine when I open the main xml file with my browser. The problem is: the result is just a fragment of website, it is an HTML element ready for being appended as a child. That is why I want to transform the xml with the xslt processor within a JavaScript function. Unfortunatelly, the result is half-way done. All what don't need the additional information from these two xml files imported by xpath expression is transformed well. The rest is shortly speaking absent.
JavaScript:
var xhttp = new XMLHttpRequest()
var xsltProcessor = new XSLTProcessor()
xhttp.open("GET", "contentTemplate.xsl", false)
xhttp.send()
xsltProcessor.importStylesheet(xhttp.responseXML)
function buildElement(what) {
var xmlDoc = document.implementation.createDocument("", "root", null)
xmlDoc.documentElement.appendChild(xmlDoc.createElement(what))
var resultDocumentFragment = xsltProcessor.transformToFragment(xmlDoc, document)
return resultDocumentFragment
}
xslt:
there is lots of stuff, I paste just the xslt with xpath expression
<xsl:variable name="extInfo" select="document('tagAvailableToAdd.xml')/root"/>
<xsl:for-each select="$extInfo/tag">
<option>
<xsl:attribute name="value"><xsl:value-of select="tagName"/></xsl:attribute>
<xsl:value-of select="description"/>
</option>
</xsl:for-each>
and that is just absent. Just like no information was delivered.
EDIT:
it works in firefox, doesn't in chrome. I need to improve it. Actually, I don't know how.
xslt:
there is lots of stuff, I paste just
the xslt with xpath expression
<xsl:variable name="extInfo" select="document('tagAvailableToAdd.xml')/root"/>
<xsl:for-each select="$extInfo/tag">
<option>
<xsl:attribute name="value"><xsl:value-of
select="tagName"/>
and that is just absent. Just like no
information was delivered.
Some possible reasons for this behaviour:
The URI of the XML file is not the right one. This is a relative URI and this specific URI will mace the XSLT processor look for a file named 'tagAvailableToAdd.xml' and residing at the base-uri of the stylesheet. However, in this case the stylesheet is obtained dynamically and this means it doesn't have any base-uri. This is the most possible reason for the problem.
The Javascript doesn't have permissions to access files in the local file system.
The document() function isn't allowed by default by the XSLT processor.
The text contained in the file is not a well-formed XML document.
The top element of the XML file is not named root.
Solution: Specify an absolute URI as the argument to the document() function.
I thought I had solved the problem, however an issue in firefox has occured.
Nevertheless, I concern chrome my native browser, that is why i'm glad I made it work in this program. That is the change I implemented in JavaScript:
function talkToServer(address, synch, func) {
func = typeof(func) != 'undefined' ? func : null
xhttp.open(method, address, synch)
xhttp.onreadystatechange = func
xhttp.send()
}
function getXPath(query) {
return document.evaluate(query, xhttp.responseXML, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null)
}
function buildElement(what) {
var xmlDoc = document.implementation.createDocument("", "root", null)
xmlDoc.documentElement.appendChild(xmlDoc.createElement(what))
switch(what) {
case "windowElement":
talkToServer("tagAvailableToAdd.xml", false)
var additionalInfo = getXPath("/root/tag")
var aim = xmlDoc.documentElement.getElementsByTagName("windowElement")[0]
for(i=0;i<additionalInfo.snapshotLength;i++)
aim.appendChild(additionalInfo.snapshotItem(i).cloneNode(true))
talkToServer("cssTemplates.xml", false)
additionalInfo = getXPath("/root/*")
aim.appendChild(xmlDoc.createElement("css"));
aim = aim.getElementsByTagName("css")[0]
for(i=0;i<additionalInfo.snapshotLength;i++)
aim.appendChild(additionalInfo.snapshotItem(i).cloneNode(true))
break;
}
var resultDocumentFragment = xsltProcessor.transformToFragment(xmlDoc, document)
return resultDocumentFragment
}
in xslt now I have all information in , so there is no need to import any external info.
main function is buildElement. I'm sure everybody can see what it does. It'a aim is to provide sth I can "paste" to HTML document.
In chrome it works. In firefox says: Node cannot be used in a document other than the one in which it was created" code: "4, and points at return statement in getXPath function. I don't know how ti fix it, but who cares, it is just firefox (I know it's stupid). In IE it suck, because xhttp is XHttpRequest object, but I believe, that when I provide ActiveX it should give what I want.
If you feel you can help me with the firefix issue, write a comment.

What is the best method to detect xml in JavaScript

What is the best method to detect xml in JavaScript
e.g. is it possible to detect the mime type of a document - particularly if it is text/xml in JavaScript.
this needs to work in Chrome.
thanks,
Josh
If you are using XMLHttpRequest to get this data, then you can simply check for the Content-Type header using the getResponseHeader method (granted that the server sends the appropriate headers).
var getFile = function(address, responseHandler) {
var req = new XMLHttpRequest();
req.open('get', address, true);
req.onreadystatechange = responseHandler;
req.send(null);
}
var responseHandler = function(resp) {
if ( this.readyState < 4 ) { return; }
console.log(this.getResponseHeader("Content-Type"));
};
getFile("http://zebrakick.com/some/file", responseHandler);
(I seem to be using this code sample a lot...)
You can't determine what the mime-type is with Javascript. I would recommend doing checks on the data returned to see if it is valid XML before you try to parse it. (I'm only assuming what you're trying to do. I can provide a more rigid example if you clarify what your goal is.)
I came across this when looking to determine that a chrome extension script was on an XML page. Maybe this saves someone a few minutes.
In the chrome console and content scripts you can check with:
document.contentType==="application/xml"

Loading a xml to a class with Javascript

How can I load a XML file to class using Javascript?
Unfortunately, each browser presents its own way of parsing a string containing XML. Here are the ways that I know of for each of the big 3 browsers. Please note, I haven't had a chance to try each of these as they're cobbled together from various blogs and my own memory.
Firefox has an object called DOMParser that can be used to parse XML in a string. The API is pretty simple -- instantiate the DOMParser and call its parseFromString method. Here is an example:
var xmlString = '<?xml version="1.0"?>...';
var parser = new DOMParser();
var dom = parser.parseFromString(theString, "text/xml");
// use dom
IE uses the Microsoft ActiveX XMLDOM control, therefore you must instantiate the DOM control and use its methods, again here's an example:
var xmlString = '<?xml version="1.0"?>...';
dom=new ActiveXObject("Microsoft.XMLDOM");
dom.async="false";
dom.loadXML(xmlString);
// use dom
And lastly, the weirdo Safari version. Safari doesn't have a parser built in, and being that it doesn't run on Windows it doesn't support ActiveX controls. However, Safari does support data: urls. In Safari a URL with the document is created and called through an XMLHTTPRequest. Like all XMLHttpRequests, you use the standard responseXml property of the XMLHttpRequest to access the DOM.
var xmlString = '<?xml version="1.0"?>...';
var url = "data:text/xml;charset=utf-8," + encodeURIComponent(xmlString);
var xhr = new XMLHttpRequest();
xhr.open("GET", url, false);
xhr.send(null);
var dom = xhr.responseXML;
// Use dom here
I'm not aware of a built-in XML serializer/deserializer in JavaScript. Is you considered something native to JavaScript, like JSON?
Here is an XML to JSON Javascript converter that might steer you in the right direction.
This code will work for all kind of browsers
var url="file.xml"
var xmlDoc="";
if(window.XMLHttpRequest&&!window.ActiveXObject)
{
var Gz=new XMLHttpRequest();Gz.open('GET',url,false);Gz.send(null);xmlDoc=Gz.responseXML;
}
else
{
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");xmlDoc.async=false;xmlDoc.load(url);
}
After using this, you can parse the tag and retrieve the data.

Categories

Resources