how to run XSL file using JavaScript / HTML file - javascript

i want to run xsl file using javascript function. I wrote a javascrpt function which is working well with Firefox and Crom but it is not working on Internet Explorer
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("NewXml.xml");
xsl=loadXMLDoc("NewFile.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);
}
}
Please help my by modifying this code or by another code so that i can work with Internet Explorer.
Thanks

To apply xsl trasformation I use, and promote, Sarissa. It is a crossbrowser library that envelope the xml apis of the different browser.
For an example of a trasformation with Sarissa you can head straight to the howto page
but it is similar to this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>sarissa test1</title>
<script type="text/javascript" src="sarissa.js"></script>
</head>
<body>
<script type="text/javascript">
function loadXMLDoc(dname) {
xhttp = new XMLHttpRequest();
xhttp.open("GET",dname,false);
xhttp.send("");
return xhttp.responseXML;
}
var processor = new XSLTProcessor();
var theXML = loadXMLDoc('xml.xml');
var theXSL = loadXMLDoc('xsl.xsl');
// prepare the processor
processor.importStylesheet(theXSL);
var theResult = processor.transformToDocument(theXML);
// now you have a DomDocument with the result
// if you want to serialize (transform to a string) it you van use
document.write(new XMLSerializer().serializeToString(theResult));
</script>
</body>
</html>
Quick, easy, mantained and you can focus your efforts to the xsl creation instead than struggling to overcome the browsers differences.
The single glitch, to me is a plus but someone may see it as a limitation, the code is released under GPL 2.1 or higher or, if you prefer Apache Licence 2.0 or higher
Edit: Mine fault, I posted an old (and wrong code) without checking it. Created a new version miming your script (and tested it) on firefox, chrome, ie8, ie7 and it worked flawlessy. I used the first two xsl/xml found on a google search (I report them below for
completeness). Try the code as is and with your xsl/xml. If it goes wrong report the malfunction too (we can be more effective with a deeper error description than - don't work - ). What happens when the code misbehave? (the browser freeze, report an error, return a blank result)
xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--?xml-stylesheet type="text/xsl" href="xsl.xsl"?-->
<tutorials>
<tutorial>
<name>XML Tutorial</name>
<url>http://www.quackit.com/xml/tutorial</url>
</tutorial>
<tutorial>
<name>HTML Tutorial</name>
<url>http://www.quackit.com/html/tutorial</url>
</tutorial>
</tutorials>
xsl:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- try to enable/disable the xsl:output -->
<!-- xsl:output method="xml"
version="1.0"
encoding="iso-8859-1"
indent="yes"/-->
<xsl:template match="/">
<html>
<head>
<title>XML XSL Example</title>
<style type="text/css">
body
{
margin:10px;
background-color:#ccff00;
font-family:verdana,helvetica,sans-serif;
}
.tutorial-name
{
display:block;
font-weight:bold;
}
.tutorial-url
{
display:block;
color:#636363;
font-size:small;
font-style:italic;
}
</style>
</head>
<body>
<h2>Cool Tutorials</h2>
<p>Hey, check out these tutorials!</p>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="tutorial">
<span class="tutorial-name"><xsl:value-of select="name"/></span>
<span class="tutorial-url"><xsl:value-of select="url"/></span>
</xsl:template>
</xsl:stylesheet>

Related

Chrome XSL Transformation insert script node security bug?

AJAX loaded xml and xsl then transform it to html. The result node is imported to html container. The result has script element with inline javascript code.
After Chrome update inline code won't executed.
For example:
HTML
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<script>
let buttonElement = document.createElement("button");
buttonElement.textContent = "Press me";
document.body.appendChild(buttonElement);
buttonElement.addEventListener("click", event => {
Promise.all([fetch('/test.xml'), fetch('/test.xsl')]).then(result => {
Promise.all([result[0].text(), result[1].text()]).then(result => {
let parser = new DOMParser(),
xml = parser.parseFromString(result[0], "application/xml"),
xsl = parser.parseFromString(result[1], "application/xml"),
target = document.body,
processor = new XSLTProcessor(),
output;
processor.importStylesheet(xsl);
output = processor.transformToDocument(xml);
let newOutput = document.body.appendChild(output.documentElement);
/*
Uncomment the block below, the result node its replacement helps and inline script will be executed properly
*/
/* newOutput.querySelectorAll("script").forEach(element => {
let replacement = document.createElement("script");
replacement.text = element.text;
element.replaceWith(replacement);
});
*/
});
});
}, false);
</script>
</body>
</html>
XML
<?xml version="1.0" encoding="UTF-8"?>
<hello>
<world/>
</hello>
XSL
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
<xsl:output method="xml" indent="no"/>
<xsl:template match="/">
<div>
<p>Hello world</p>
<script>console.log("Test me!");</script>
</div>
</xsl:template>
</xsl:stylesheet>
So, is it security bug of Webkit? Because, this bug was also detected in Opera.
And if this is security solution, why inline script is succesfully executed after result node replacement?

XSLT loaded with AJAX, contains <script> fired only in Firefox

I write an application where AJAX loads an XSLT which has a <script> inside.
The strange thing is that script runs in Firefox without eval(). Script is not ran in Opera or Chrome.
So, I simplify the code and I post it here.
Is it a Firefox bug?
Is there a cross-browser workaround? (A workaround which does not run eval() on firefox, only for scripts from xslt, but run eval() on Chrome, Opera for every script loaded with AJAX - both in XSLT or in XHTML).
index.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head><script src="app.js" /></head>
<body onload="locationHashChanged();" />
</html>
app.js
function get(file) {
var request = new XMLHttpRequest();
request.open("GET", file, false);
request.send();
return request.responseXML;
}
function insert(where, root) {
//var scripts = root.getElementsByTagName('script');
where.parentNode.replaceChild(root, where);
//for(var z = 0; z != scripts.length; z++) eval(scripts[z]);
}
function locationHashChanged() {
var xml = get('apps.xml');
var xslt = get('xslt.xsl');
var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xslt);
insert(document.body, xsltProcessor.transformToFragment(xml, document).firstChild);
};
xslt.xsl
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*" />
<xsl:template match="//*[#path='']">
<body xmlns="http://www.w3.org/1999/xhtml">
<script>alert('Only in Firefox');</script>
</body>
</xsl:template>
</xsl:stylesheet>
apps.xml
<?xml version="1.0" encoding="UTF-8"?>
<menu name="" path="" />
Would it help to put the alert in a CDATA tag? So
<script type="text/javascript">
<![CDATA[alert('Only in Firefox');]]>
</script>
I've started doing that for all javascript that I include in xslt templates

MSXML4 versus MSXML6 XSLT Parsing Namespace Error

I saw a lot of posts online about MSXML4 to 6 or XSLT 1.0 versus 2.0 etc. But they could not answer my question.
I have a XSLT transformation code that works with MSXML4 APIs (XSLTransform and FreeThreadedDomDocument) on IE7 via Javascript.
Same code doesnt work with with MSXML6 APIs (XSLTransform and DomDocument) on IE9 via Javascript. It throws this error
"Namespace 'urn:mynamespace:mytable:transactions' does not contain any functions"
I have made sure that my ActiveX are enabled for MSXML4 and 6 both on IE9. Below is the code of the main tranformer XSLT, the reference XSLT & the JS code ...
Core XSLT: functions.xsl
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:myfuncs="urn:mynamespace:mytable:transactions" >
<msxsl:script language="javascript" implements-prefix="myfuncs">
<![CDATA[
// convert system GMT time into local time
// usage: <xsl:value-of select="myfuncs:localDateTime(datetime)"/>
var openBalance = 0;
function setOpenBalance(openBal)
{
openBalance = openBal;
}
function getOpenBalance()
{
openBalance = openBal;
return openBalance ;
}
]]>
</msxsl:script>
</xsl:stylesheet>
Main XSLT: MyTransformer.xsl ... that refers functions.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:myfuncs="urn:mynamespace:mytable:transactions">
<xsl:output method="xml"/>
<xsl:include href="functions.xsl" />
<!--<xsl:variable name="trade_cur_bal" select="myfuncs:getOpenBalance(100)"/>-->
<xsl:template match="/">
<Response>
<!-- Some working code here -->
</Response>
</xsl:template>
</xsl:stylesheet>
JS Code
var domXsl = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.4.0");
/*
// In case of IE9 ....
var domXsl = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.6.0");
*/
var domHTML = new ActiveXObject("Msxml2.XSLTemplate.4.0");
/*
// In case of IE9 ....
var domHTML = new ActiveXObject("Msxml2.XSLTemplate.6.0");
*/
domXsl.async=false;
domXsl.load("MyTransformer.xsl");
domHTML.stylesheet = domXsl;
var domData = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.4.0");
var input = "<MyInputData></MyInputData>"
domData.loadXML(input);
var result = tranform(domHTML, domData); //Works for MSXML 4.0 and fails for MSXML 6.0
function transform(template_, input_) {
var output = "";
if (input_ != null && input_.xml != "") {
var proc = template_.createProcessor();
proc.input = input_;
proc.transform();
output = proc.output;
delete proc;
}
return output;
}
Can someone guide me where am I going wrong w.r.t. MSXML6 or IE9?
Thx.
With MSXML 6 use of script inside XSLT is disabled by default for security reasons, so you need to explicitly enable it by calling
var domXsl = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.6.0");
domXsl.setProperty("AllowXsltScript", true);
And additionally to allow the use of xsl:import or xsl:include you also need to set
domXsl.setProperty("ResolveExternals", true);
I got this fixed by removing the versions (4 and 6) form the activeX class ID
e.g. new ActiveXObject("Msxml2.FreeThreadedDomDocument") etc.

XSL parameters using JavaScript

I have a html page like:
<html>
<head>
<script>
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("1.xml");
xsl=loadXMLDoc("2.xsl");
// code for IE
if (window.ActiveXObject)
{
xml.addParameter("rss", test);
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);
}
}
</script>
</head>
<body onload="displayResult()">
<div id="example" />
</body>
</html>
Now I would like to pass a variable (javascript) to the XSL like for example "course_name" so that in the XSL I can use it like
<xsl:param name="course_name" />
<xsl:value-of select="$course_name" />
Any help with the approach to solve this problem is highly appreciated.
You can do it like this:
xsltProcessor.setParameter(null, "course_name", "whatever the name is");
and for IE, you will need to change your code as per http://msdn.microsoft.com/en-us/library/windows/desktop/ms762312%28v=vs.85%29.aspx , but the command is:
xslproc.addParameter("param1", "Hello");
...but given that you added "xslt-2.0" as a tag, you should know that built-in XSLT support in browsers only goes up to XSL 1.0.
The following may be of additional help:
https://developer.mozilla.org/en-US/docs/Using_the_Mozilla_JavaScript_interface_to_XSL_Transformations
https://developer.mozilla.org/en-US/docs/The_XSLT_JavaScript_Interface_in_Gecko/Setting_Parameters
http://msdn.microsoft.com/en-us/library/windows/desktop/ms762312%28v=vs.85%29.aspx
The Saxon-CE XSLT 2.0 processor runs in the browser as a JavaScript library/framework. Because its JavaScript there's a high level of interoperability, so you can pass parameters to the XSLT processor, but you can also call JavaScript functions from the XSLT, which gives added flexibility.
When passing values across, arrays in JavaScript correspond to XSLT 2.0 sequences, but some care is still required to ensure types are preserved across the language boundary.
The JavaScript API for Saxon-CE has 2 distinct forms of syntax - one is the same as that in your code, but below is an example of the alternate syntax - the same code runs on all the major browsers:
<!DOCTYPE html>
<html>
<head>
<title>stacko</title>
<script type="text/javascript" language="javascript"
src="../Saxonce/Saxonce.nocache.js"></script>
<script type="text/javascript" language="javascript">
var my_course = "physics";
onSaxonLoad = function() {
proc = Saxon.run( {
stylesheet: 'stacko.xsl',
source: 'stacko.xml',
parameters: {
course_name: my_course,
tutor: "Mr smith"
}
} );
}
</script>
</head>
<body>
<div id="example"></div>
</body>
</html>
There's no need to return the result fragment back to JavaScript with this processor (though you can if necessary), because the XSLT 2.0 xsl:result-document instruction has been extended so it can use an href attribute that specifies the id of the element in the HTML page to update, for example:
<xsl:result-document href="#example" method="replace-content">
<p><xsl:value-of select="ixsl:source()/books/book[#title = 'One']/></p>
</xsl:result-document>
There's more detail in the API section of the Saxon-CE documentation

Need help parsing xml with javascript

First let me thank you for the assistance, I am new to Javascript, and want to learn to parse a >.xml file into my javascript. The file I want to parse is contact.xml, located in my root folder.
Again, thank you.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1 /DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript">
function loadXMLDoc(XMLname)
{
var xmlDoc;
if (window.XMLHttpRequest)
{
xmlDoc=new window.XMLHttpRequest();
xmlDoc.open("GET",XMLname,false);
xmlDoc.send("");
return xmlDoc.responseXML;
}
// IE 5 and IE 6
else if (ActiveXObject("Microsoft.XMLDOM"))
{
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async=false;
xmlDoc.load(XMLname);
return xmlDoc;
}
alert("Error loading document!");
return null;
}
<title>Contacts</title>
</script>
</head>
<body>
<script type="text/javascript">
xmlDoc = loadXMLDoc("contactinfo.xml") // Path to the XML file;
var M = xmlDoc.getElementsByTagName("item");
for (i=0;i<M.length;i++){
document.write("<div style='width:450px;'>")
document.write("<h2>"+xmlDoc.getElementsByTagName("item")[i].childNodes[0].nodeValue+"</h2>");
document.write("<p>" + xmlDoc.getElementsByTagName("servicephone")[i].childNodes[0].nodeValue+ "</p>");
document.write("<p><a href='" + xmlDoc.getElementsByTagName("email")[i].childNodes[0].nodeValue +"</p>);
document.write("</div>")
}
</script>
</body>
</html>
*Here is my .xml file*
<?xml version="1.0" encoding="utf-8" ?>
<Contacts>
<item servicephone="(800) 500-0066"
email="customerservice#fsig.com"
url="http://www.fsig.com"
address="5000 Barcilona Beach Rd. Wilmington, NC 28000">
</item>
</Contacts>
You need to go down the hierarchy, so, first find the Contacts node, then inside there you can get all the tagnames as you have.
You have a great deal of attributes so you may find this useful also:
node.attributes["url"].nodeValue
So just loop through all the items, then I would just copy itemelem[t] to node just to make it easier, then you get the attributes you need.
Depending on the browser you are using most of them come with some javascript debugger, so you can put in breakpoints and look at the values in the variables and see what the next step needs to be.

Categories

Resources