transformNode function for ie9 - javascript

I need to transform an xml doc into another xml doc using xslt in ie9 or above versions.
I am trying to transform an xml doc using xslt in ie9. When i used transformNode() function it is working fine in ie8(code:: resultDocument = XML.transformNode(XSL);) but in ie9 transformNode function is not defined showing error::SCRIPT438: Object doesn't support property or method 'transformNode'
I found a solution for ie9 as given below
if (window.ActiveXObject) {
console.log('inside hi');
var xslt = new ActiveXObject("Msxml2.XSLTemplate");
var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument");
xslDoc.loadXML(xsltDoc.xml);
console.log(xslt.styleSheet);
xslt.stylesheet = xslDoc;
var xslProc = xslt.createProcessor();
xslProc.input = xmlDoc;
xslProc.transform();
return xslProc.output;
}
but when i run this i get an error: SCRIPT16389: The stylesheet does not contain a document element. The stylesheet may be empty, or it may not be a well-formed XML document.
I am new to javascript/jquery. Can anyone please help me in resolving this. If there is any other function either in javascript or jquery it would be helpful.
Thanks in advance

With earlier versions of IE the responseXML document used to be an MSXML DOM document and MSXML implements XSLT and transformNode. With newer IE versions the responseXML document gives you an IE DOM document and IE does not implement XSLT and transformNode for its DOM document/nodes. Nor does an IE DOM document have a property xml you are trying to use in xslDoc.loadXML(xsltDoc.xml);.
Try changing that part of the code to
if (typeof XMLSerializer !== 'undefined') {
xslDoc.loadXML(new XMLSerializer().serializeToString(xsltDoc));
// now use xslDoc here
}
A different option is to use xslDoc.loadXML(xmlHttp.responseText); if you still have access to the XMLHttpRequest. There is also an option to ensure you get an MSXML responseXML, see try { xhr.responseType = 'msxml-document'; } catch(e){} line in http://blogs.msdn.com/b/ie/archive/2012/07/19/xmlhttprequest-responsexml-in-ie10-release-preview.aspx.
Your whole approach to object checking in your code is wrong, check for the object or property or method you want to use (e.g. if (typeof XSLTProcessor !== 'undefined') { // now use XSLTProcessor here }), not for completely different object like document.implementation.

I too had the SCRIPT16389: The stylesheet does not contain a document element. The stylesheet may be empty, or it may not be a well-formed XML document error in IE9/10/11. I've found the following fixes it:
your code:
if (window.ActiveXObject) {
console.log('inside hi');
var xslt = new ActiveXObject("Msxml2.XSLTemplate");
var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument");
xslDoc.loadXML(xsltDoc.xml);
console.log(xslt.styleSheet);
xslt.stylesheet = xslDoc;
var xslProc = xslt.createProcessor();
xslProc.input = xmlDoc;
xslProc.transform();
return xslProc.output;
}
working code:
if (window.ActiveXObject) {
console.log('inside hi');
var xslt = new ActiveXObject("Msxml2.XSLTemplate");
var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument");
xslDoc.load(xsltDoc);
console.log(xslt.styleSheet);
xslt.stylesheet = xslDoc;
var xslProc = xslt.createProcessor();
xslProc.input = xmlDoc;
xslProc.transform();
return xslProc.output;
}
The change being line 6 - replace 'loadXML' with 'load' and 'xsltDoc.xml' with just 'xsltDoc'. Let me know how it goes!

Related

How to use XML Parser and get element by tagName when tag contains embedded element inside?

I'm using XMLParser to get data from a tag.
This tag is like this :
<tagName elem="XXX"></tagName>
I want to get : XXX
According to documentation, I'm doing like :
parseMyXML = new DOMParser();
xmlDoc = parseMyXML.parseFromString(contentXML,"text/xml");
var code_XXX = xmlDoc.getElementsByTagName("tagName")[0].childNodes[0].nodeValue;
I have an error : Uncaught (in promise) TypeError: Cannot read property 'nodeValue' of undefined
What I need is to go into tagName and to get the contain of elem
It's an attribute not a child node.
xmlDoc.getElementsByTagName("tagName")[0].getAttribute("elem");
With jQuery you can do something like this.
var $xml = $.parseXML(xml),
value = $xml.find('tagName').text();
if you're using plain JS you should parse xml like this.
if (window.DOMParser) {
// code for modern browsers
parser = new DOMParser();
xmlDoc = parser.parseFromString(text,"text/xml");
} else {
// code for old IE browsers
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.loadXML(text);
}

Check if 2 XML documents are identical with javascript

I have 2 xml documents stored which I get from an AJAX post request and I would like to check if they are the same. Obviously xml1 == xml2 is not working. Is there another way that I could make this work?
Try this. It parses the XML document using the method in this question and compares the two using isEqualNode.
function parseXMLString(xmlString) {
var xmlDoc;
if (window.DOMParser) {
var parser = new DOMParser();
xmlDoc = parser.parseFromString(xmlString, "text/xml");
} else // Internet Explorer
{
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.loadXML(xmlString);
}
return xmlDoc;
}
var xmlObj1 = parseXMLString('<hello>world</hello>');
var xmlObj2 = parseXMLString('<hello>world</hello>');
var xmlObj3 = parseXMLString('<hello>world2</hello>');
var xmlObj4 = parseXMLString('<hello2>world</hello2>');
console.log(xmlObj1.isEqualNode(xmlObj2));
console.log(xmlObj1.isEqualNode(xmlObj3));
console.log(xmlObj1.isEqualNode(xmlObj4));
If you're using jQuery, you can parse the XML document using parseXML().

Does the browser have an HTML parser that I can access to get errors?

I'm able to parse XML documents in the browser and get error messages using the following code:
// Internet Explorer
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.loadXML(txt);
var hasError = (xmlDoc.parseError.errorCode != 0);
// Firefox, Opera, Webkit
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(text, "text/xml");
var hasError = (xmlDoc.getElementsByTagName("parsererror").length > 0);
But I need to be able to parse an HTML document and check for errors.
Is there an HTML parser I can access in the same way as I'm accessing the XML parser?
UPDATE:
It looks like at least in Firefox I can attempt to create an HTML dom and parse the contents. But it doesn't seem to throw any error or return an error message no matter what I throw at it:
var text = "<html><body><label>test</labe></body></html>";
var parser = new DOMParser();
//var func = function (e) { console.log(e); };
//parser.attachEvent("InvalidStateError", func); // no attachEvent, no addEventListener
var htmlDoc = parser.parseFromString(text, "text/html");
var hasError = (htmlDoc.getElementsByTagName("parsererror").length > 0);
console.log("Has error: " + hasError); // also false. no errors ever.
console.log(htmlDoc);
This page, this page and this page helped me understand the DOMParser class more.

Error with XPath in a parsed XML document (WrongDocumentError)

I'm creating a Firefox for Android extension and I have a problem with a XML document retrieved from a XMLHttpRequest: I can't find a way to select a node. The better solution I found is this, but I got this error when selecting with xpath on the document:
WrongDocumentError: Node cannot be used in a document other than the one in which it was created
This is my code:
var parser = Cc["#mozilla.org/xmlextras/domparser;1"].createInstance(Ci.nsIDOMParser);
var parsedXml = parser.parseFromString(xmlhttp.responseText, "text/xml");
var xpathExpression = "//td[contains(.,'Raw text')]/../td[2]/pre";
var res = window.content.document.evaluate(xpathExpression, parsedXml, null, window.XPathResult.STRING_TYPE , null);
If I replace the "evaluate" with the next line:
var res = parsedXml.selectSingleNode(xpathExpression);
Then I get the following error:
[JavaScript Error: "parsedXml.selectSingleNode is not a function"
{file: "resource://gre/modules/addons/XPIProvider.jsm ->
jar:file:///data/data/org.mozilla.fennec/files/mozilla/ggz9zzjr.default/extensions/qrReader#qrReader.xpi!/bootstrap.js"
line: 61}]
Well, the name of the exception, WrongDocumentErrort gave it away. You're trying to call .evaluate() on a DOM (Document) that does not belong to the same Document .evaluate() is bound to.
The nsIDOMParser will actually return a new XMLDocument that has an .evaluate() itself, which you'll have to use.
var parser = Cc["#mozilla.org/xmlextras/domparser;1"].
createInstance(Ci.nsIDOMParser);
var parsedDoc = parser.parseFromString(
'<?xml version="1.0"?>\n<doc><elem>Raw text</elem></doc>',
"text/xml");
var xpathExpression = "//elem[contains(.,'Raw text')]";
var res = parsedDoc.evaluate(
xpathExpression,
parsedDoc,
null,
XPathResult.STRING_TYPE,
null);
console.log(res, res.stringValue);
Instead using nsIDOMParser, since your content seems to be originating from XHR anyway, and seems to be (X)HTML (indicated by your expression), it might be better to use XHR.responseType = "document" instead, which will parse a DOM from the response using the HTML parser.
var req = new XMLHttpRequest();
req.onload = function() {
var doc = req.response;
var h1 = doc.evaluate("//h1", doc, null, XPathResult.STRING_TYPE, null);
console.log(h1.stringValue);
// Alternative in some cases
h1 = doc.querySelector("h1");
console.log(h1.textContent);
};
req.open("GET", "http://example.org/");
req.responseType = "document"; // Parse as text/html
req.send();
parseFromString returns a document object. selectSingleNode is not a document function. Can't you select a node using the standard document.getElementsByClassname, document.getElementById, or document.querySelector?
try
var window = parsedXml.ownerDocument.defaultView;
var res = window.content.document.evaluate(xpathExpression, parsedXml, null, window.XPathResult.STRING_TYPE , null);

How do I transform an XML document using XSLT and add a parameter in IE?

I'm new to learning XSLT, and I've come across something I really don't quite understand. I need to add an XSLT parameter before transforming the document. I can do this for non-IE browsers like so:
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;
}
function displayResult() {
xml = loadXMLDoc("cdcatalog.xml");
xsl = loadXMLDoc("cdcatalog.xsl");
// code for IE
if (window.ActiveXObject) {
ex = xml.transformNode(xsl);
document.getElementById("example").innerHTML = ex;
}
// code for Mozilla, Firefox, Opera, etc.
else if (document.implementation && document.implementation.createDocument) {
xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsl);
resultDocument = xsltProcessor.transformToFragment(xml, document);
document.getElementById("example").appendChild(resultDocument);
}
}
Now, I can do it for non-IE browsers, a new XSLT Processor object is made, stylesheet imported, and you simply add the parameter before the transformation process. None of this seems to be happening for the IE version of the code though, and I can't simply add the parameter before the transformation. I've googled profusely and seen different things telling me to create new ActiveX objects of various different MSXML versions, and I'm deeply confused by the whole affair.
Taking the above code, how do I do this:
xsltProcessor.setParameter(null,"PARAMNAME","PARAMVALUE");
except for IE and if possible, can someone explain how IE deals with the whole concept of XSLT differently to FF/O/C/other civilised browsers?
You might try using Sarissa, which is an abstraction layer that provides a cross-browser XSLT transformation API.
According to this page, you can use
XSLTProcessor.addParameter("Parameter Name", "Parameter Value");
where XSLTProcessor is created with
var XSLTCompiled = new ActiveXObject("MSXML2.XSLTemplate");
XSLTCompiled.stylesheet = XSL.documentElement;
var XSLTProcessor = XSLTCompiled.createProcessor();
The transform call is also different.
XSLTProcessor.transform();
Anyway, it looks like there's a quite elaborate explanation of what you're asking for.
I did cross-browser XSLT transforms a while back, and here's the code I used. createDocument is just a function to return a DOM document. I didn't do stylesheet parameters, so maybe this is a little off-topic, but anyway it works on IE6+ and Firefox 1.5+.
// arguments can be string (uri of document) or document node
function xslTransform( content, transform, options )
{
if ("string" == typeof content) content = createDocument( content );
if ("string" == typeof transform) transform = createDocument( transform );
var targetEle;
if (options && options.target) targetEle = document.getElementById(options.target);
if (targetEle && options.replace)
while (targetEle.hasChildNodes())
targetEle.removeChild( targetEle.firstChild );
if (window.XSLTProcessor)
{
var processor = new XSLTProcessor();
processor.importStylesheet( transform );
var frag = processor.transformToFragment( content, document );
if (targetEle)
targetEle.appendChild( frag );
}
else if (window.ActiveXObject)
{
if (targetEle)
targetEle.innerHTML = content.transformNode( transform );
}
else return "XSLT not supported";
}

Categories

Resources