yellow1234
asked on
XML XSLT parameters Javascript - how to make it work in Mozilla...
Yes - I ve seen similair questions before and I searched the web but I cannot get it to work in Mozilla - (works fine in IE with the ActiveXObjects). What I like to achieve is a much more complicated then this - but I ve seen to many times pages and pages of code where a basic example would have done OK... so I narrowed down the code to this:
The basic idea is that through Javascript you set a variable in the xsl document, the xml and xsl is loaded again and the hml document shows the data according to the parameter. I quess my question is what's the ActiveX equivalent in Mozilla and how do i set a parameter then? Thanks everybody - 3 files below - copy and paste it and you'll see works OK in IE
1. The XML file (four books - Author, Title and Price): books.xml
========================== ========== =====
<?xml version='1.0' encoding='ISO-8859-1'?>
<Catalog>
<Book>
<Title>On holiday in Turkey</Title>
<Author>O Arslan</Author>
<Price>20</Price>
</Book>
<Book>
<Title>South Coast of Turkey</Title>
<Author>Peter Jones</Author>
<Price>18</Price>
</Book>
<Book>
<Title>Istanbul and the West Coast</Title>
<Author>John Apple</Author>
<Price>19</Price>
</Book>
<Book>
<Title>The Turkish Black Sea Coast</Title>
<Author>John Deniz</Author>
<Price>19.5</Price>
</Book>
</Catalog>
2. The XSL file, to display the items sorted by price: sort.xsl
Note the parameter at the top for sorting
========================== ========== ===
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="sortOrder" select="'ascending'" />
<xsl:template match="/">
<xsl:for-each select="Catalog/Book">
<xsl:sort select="Price" data-type="number" order="{$sortOrder}"/>
<xsl:call-template name="ShowBooks" />
</xsl:for-each>
</xsl:template>
<xsl:template name="ShowBooks">
<xsl:value-of select="Author"/> /
<xsl:value-of select="Title"/> / USD
<xsl:value-of select="Price"/> <br />
</xsl:template>
</xsl:stylesheet>
3. The HTML file including Javascript. The Javascript
loads the XML and XSL and displays it in a <div>
When changing the select, the Javascript runs again, assigning a value
to the parameter in the xsl file:
========================== ========== =========
<html>
<head>
<script language="javascript">
function sortlist(myvalue) {
var xslt = new ActiveXObject("Msxml2.XSLT emplate");
var xslDoc = new ActiveXObject("Msxml2.Free ThreadedDO MDocument" );
var xslProc;
xslDoc.async = false;
xslDoc.resolveExternals = false;
xslDoc.load("sort.xsl");
xslt.stylesheet = xslDoc;
var xmlDoc = new ActiveXObject("Msxml2.DOMD ocument");
xmlDoc.async = false;
xmlDoc.resolveExternals = false;
xmlDoc.load("books.xml");
xslProc = xslt.createProcessor();
xslProc.input = xmlDoc;
xslProc.addParameter("sort Order", myvalue);
xslProc.transform();
var str;
str = xslProc.output;
document.getElementById('b ooks').inn erHTML=str ;
}
</script>
</head>
<body onLoad="sortlist('ascendin g')">
<h2>Books</h2>
<form name='ascdesc'>
Sort price
<select name ='SortOrder'
onChange="sortlist(ascdesc .SortOrder .options[a scdesc.Sor tOrder.sel ectedIndex ].value)">
<option value='ascending' selected>Ascending</option >
<option value='descending'>Descend ing</optio n>
</select>
</form>
<div id='books'></div>
</body>
</html>
=====
The basic idea is that through Javascript you set a variable in the xsl document, the xml and xsl is loaded again and the hml document shows the data according to the parameter. I quess my question is what's the ActiveX equivalent in Mozilla and how do i set a parameter then? Thanks everybody - 3 files below - copy and paste it and you'll see works OK in IE
1. The XML file (four books - Author, Title and Price): books.xml
==========================
<?xml version='1.0' encoding='ISO-8859-1'?>
<Catalog>
<Book>
<Title>On holiday in Turkey</Title>
<Author>O Arslan</Author>
<Price>20</Price>
</Book>
<Book>
<Title>South Coast of Turkey</Title>
<Author>Peter Jones</Author>
<Price>18</Price>
</Book>
<Book>
<Title>Istanbul and the West Coast</Title>
<Author>John Apple</Author>
<Price>19</Price>
</Book>
<Book>
<Title>The Turkish Black Sea Coast</Title>
<Author>John Deniz</Author>
<Price>19.5</Price>
</Book>
</Catalog>
2. The XSL file, to display the items sorted by price: sort.xsl
Note the parameter at the top for sorting
==========================
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="sortOrder" select="'ascending'" />
<xsl:template match="/">
<xsl:for-each select="Catalog/Book">
<xsl:sort select="Price" data-type="number" order="{$sortOrder}"/>
<xsl:call-template name="ShowBooks" />
</xsl:for-each>
</xsl:template>
<xsl:template name="ShowBooks">
<xsl:value-of select="Author"/> /
<xsl:value-of select="Title"/> / USD
<xsl:value-of select="Price"/> <br />
</xsl:template>
</xsl:stylesheet>
3. The HTML file including Javascript. The Javascript
loads the XML and XSL and displays it in a <div>
When changing the select, the Javascript runs again, assigning a value
to the parameter in the xsl file:
==========================
<html>
<head>
<script language="javascript">
function sortlist(myvalue) {
var xslt = new ActiveXObject("Msxml2.XSLT
var xslDoc = new ActiveXObject("Msxml2.Free
var xslProc;
xslDoc.async = false;
xslDoc.resolveExternals = false;
xslDoc.load("sort.xsl");
xslt.stylesheet = xslDoc;
var xmlDoc = new ActiveXObject("Msxml2.DOMD
xmlDoc.async = false;
xmlDoc.resolveExternals = false;
xmlDoc.load("books.xml");
xslProc = xslt.createProcessor();
xslProc.input = xmlDoc;
xslProc.addParameter("sort
xslProc.transform();
var str;
str = xslProc.output;
document.getElementById('b
}
</script>
</head>
<body onLoad="sortlist('ascendin
<h2>Books</h2>
<form name='ascdesc'>
Sort price
<select name ='SortOrder'
onChange="sortlist(ascdesc
<option value='ascending' selected>Ascending</option
<option value='descending'>Descend
</select>
</form>
<div id='books'></div>
</body>
</html>
=====
this page has an example of the use
http://developer.mozilla.org/en/docs/The_XSLT/JavaScript_Interface_in_Gecko:Setting_Parameters
http://developer.mozilla.org/en/docs/The_XSLT/JavaScript_Interface_in_Gecko:Setting_Parameters
ASKER
Gertone,
I had a look again in these pages.
Unfortunately my problem is that there are parts of the solution everywhere - but unfortunately I am not familair enough with this stuff to glue it all together. Also these articles don't give any examples - should you have one, or should you be able to rewrite my JavaScript file so it runs in Firefox would greatly appreciate it.
I had a look again in these pages.
Unfortunately my problem is that there are parts of the solution everywhere - but unfortunately I am not familair enough with this stuff to glue it all together. Also these articles don't give any examples - should you have one, or should you be able to rewrite my JavaScript file so it runs in Firefox would greatly appreciate it.
the javascript below works both in IE and Mozilla. The condition is that the parameter must be present: this function only changes a parameter.
function SetXSLParam(xsl, paramname, iValue) {
var i, oNode;
var oNodeList = xsl.documentElement.childN odes;
for(i=0;i<oNodeList.length ;i++) {
oNode = xmlNextNode(oNodeList,i);
if(oNode.nodeName=='xsl:pa ram' && oNode.getAttribute('name') ==paramnam e) {
oNode.setAttribute('select ',iValue);
break;
}
}
}
function SetXSLParam(xsl, paramname, iValue) {
var i, oNode;
var oNodeList = xsl.documentElement.childN
for(i=0;i<oNodeList.length
oNode = xmlNextNode(oNodeList,i);
if(oNode.nodeName=='xsl:pa
oNode.setAttribute('select
break;
}
}
}
Oh, you need this function as well, because it is called:
function xmlNextNode(oNodeList,i) {
var oNode;
if(oNodeList.snapshotLengt h) {
oNode = oNodeList.snapshotItem(i);
} else {
try {
oNode = oNodeList.item(i);
} catch(e) {
alert('xmlxsl.js: xmlNextNode() not succesfull');
}
}
return oNode;
}
function xmlNextNode(oNodeList,i) {
var oNode;
if(oNodeList.snapshotLengt
oNode = oNodeList.snapshotItem(i);
} else {
try {
oNode = oNodeList.item(i);
} catch(e) {
alert('xmlxsl.js: xmlNextNode() not succesfull');
}
}
return oNode;
}
ASKER
Hi sybe,
Don't want to be funny but this is only a part for the problem I have - may main challenge is:
Having an empty div in an html document,
fill this div (by Javascript) with the xml data (in an external document - or string), formatted by the xsl document.
I am sure once I ve got this far, I will be able to add the parameter thing.
I saw another question on ee: (Title: Cross browser XSL Javascript solution?) - there are some links to an example which unfortunately do not work.
Thanks for you contribution - Regards
Don't want to be funny but this is only a part for the problem I have - may main challenge is:
Having an empty div in an html document,
fill this div (by Javascript) with the xml data (in an external document - or string), formatted by the xsl document.
I am sure once I ve got this far, I will be able to add the parameter thing.
I saw another question on ee: (Title: Cross browser XSL Javascript solution?) - there are some links to an example which unfortunately do not work.
Thanks for you contribution - Regards
Ok, I have done that (and it works)
function LoadXMLFile(sURL) {
var oXML, oRequest;
try {
oXML = new ActiveXObject('Msxml2.DOMD ocument');
} catch(e) {oXML = false;}
if(oXML) {
//IE load XML document
oXML.async = false;
oXML.load(sURL);
if(oXML.parseError.errorCo de) {
alert('error: ' + oXML.parseError.descriptio n);
return false;
}
}
if(!oXML) {
//Mozilla load XML document
try {
oXML = document.implementation.cr eateDocume nt("", "", null);
} catch(e) {oXML = false;}
if(oXML) {
oXML.async = false;
try {
oXML.load(sURL);
} catch(e) {oXML = false;}
}
}
if(!oXML) {
try {
oRequest = new XMLHttpRequest();
oRequest.open("GET", sURL, false);
oRequest.send(null);
oXML = oRequest.responseXML;
} catch(e) {oXML = false;}
}
return oXML;
}
function ProcessXMLAndXSL(oXML, oXSL) {
var sHTML = '';
//IE
if(window.ActiveXObject) {
try {
sHTML = oXML.transformNode(oXSL);
return sHTML;
} catch (e) {
alert('could not transform xml and xsl');
}
}
//Mozilla
if (document.implementation && document.implementation.cr eateDocume nt) {
var oProcessor = new XSLTProcessor();
oProcessor.importStyleshee t(oXSL);
sHTML = oProcessor.transformToFrag ment(oXML, document);
return sHTML;
}
}
function FillDivWithXMLAndXSL(sXMLU RL, sXSLURL, oDiv)
var oXML = LoadXMLFile(sXMLURL);
var oXSL = LoadXMLFile(sXSLURL);
oHTML = ProcessXMLAndXSL(oXML,oXSL );
if(typeof(oHTML)=='string' ) {
//IE
var oTempDiv = document.createElement('di v');
oTempDiv.innerHTML = oHTML;
oHTML = oTempDiv.firstChild;
oDiv.appendChild(oHTML);
//this seems nonsense, but otherwise the HTML won't show up
oDiv.innerHTML = oDiv.innerHTML;
oTempDiv = null;
window.CollectGarbage();
} else {
//Mozilla
oDiv.appendChild(oHTML);
}
}
function LoadXMLFile(sURL) {
var oXML, oRequest;
try {
oXML = new ActiveXObject('Msxml2.DOMD
} catch(e) {oXML = false;}
if(oXML) {
//IE load XML document
oXML.async = false;
oXML.load(sURL);
if(oXML.parseError.errorCo
alert('error: ' + oXML.parseError.descriptio
return false;
}
}
if(!oXML) {
//Mozilla load XML document
try {
oXML = document.implementation.cr
} catch(e) {oXML = false;}
if(oXML) {
oXML.async = false;
try {
oXML.load(sURL);
} catch(e) {oXML = false;}
}
}
if(!oXML) {
try {
oRequest = new XMLHttpRequest();
oRequest.open("GET", sURL, false);
oRequest.send(null);
oXML = oRequest.responseXML;
} catch(e) {oXML = false;}
}
return oXML;
}
function ProcessXMLAndXSL(oXML, oXSL) {
var sHTML = '';
//IE
if(window.ActiveXObject) {
try {
sHTML = oXML.transformNode(oXSL);
return sHTML;
} catch (e) {
alert('could not transform xml and xsl');
}
}
//Mozilla
if (document.implementation && document.implementation.cr
var oProcessor = new XSLTProcessor();
oProcessor.importStyleshee
sHTML = oProcessor.transformToFrag
return sHTML;
}
}
function FillDivWithXMLAndXSL(sXMLU
var oXML = LoadXMLFile(sXMLURL);
var oXSL = LoadXMLFile(sXSLURL);
oHTML = ProcessXMLAndXSL(oXML,oXSL
if(typeof(oHTML)=='string'
//IE
var oTempDiv = document.createElement('di
oTempDiv.innerHTML = oHTML;
oHTML = oTempDiv.firstChild;
oDiv.appendChild(oHTML);
//this seems nonsense, but otherwise the HTML won't show up
oDiv.innerHTML = oDiv.innerHTML;
oTempDiv = null;
window.CollectGarbage();
} else {
//Mozilla
oDiv.appendChild(oHTML);
}
}
ASKER
Hi Sybe,
Looks good - thanks much for you efforts - will have a look at it tomorrow - as I have to go out this evening.
Thanks
Looks good - thanks much for you efforts - will have a look at it tomorrow - as I have to go out this evening.
Thanks
ASKER
Hello Sybe,
I tried to apply your script as follows in an html doc:
<html>
<head>
<script language='javascript'>
your script here....
</script>
</head>
<body onload="FillDivWithXMLAndX SL('exampl e1.xml', 'example1.xsl', 'example')">
<div id='example'></div>
</body>
</html>
This gives the following error message in IE:
Object doesn't support this property or method (refers to oDiv.appendChild(oHTML) in function FillDivWithXMLAndXS)
And the followong in Firefox:
oDiv.appendChild is not a function. (referring to last line of FillDivWithXMLAndXS)
let me know if I overlook something?
(By the way, a '{' was missing before the function body with FillDivWithXMLAndXS when I copied yur script - I just wacked that in.)
Thanks and regards.
I tried to apply your script as follows in an html doc:
<html>
<head>
<script language='javascript'>
your script here....
</script>
</head>
<body onload="FillDivWithXMLAndX
<div id='example'></div>
</body>
</html>
This gives the following error message in IE:
Object doesn't support this property or method (refers to oDiv.appendChild(oHTML) in function FillDivWithXMLAndXS)
And the followong in Firefox:
oDiv.appendChild is not a function. (referring to last line of FillDivWithXMLAndXS)
let me know if I overlook something?
(By the way, a '{' was missing before the function body with FillDivWithXMLAndXS when I copied yur script - I just wacked that in.)
Thanks and regards.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
For IE you have to change the code a bit, the result of the XML-XSL transformation is an HTML-fragment with multiple nodes (I never work that way, my transformations always return a single node). That is why the code should be changed a bit:
function FillDivWithXMLAndXSL(sXMLU RL, sXSLURL, oDiv) {
var oXML = LoadXMLFile(sXMLURL);
var oXSL = LoadXMLFile(sXSLURL);
oHTML = ProcessXMLAndXSL(oXML,oXSL );
if(typeof(oHTML)=='string' ) {
//IE
oDiv.innerHTML = oHTML;
} else {
//Mozilla
oDiv.appendChild(oHTML);
}
}
function FillDivWithXMLAndXSL(sXMLU
var oXML = LoadXMLFile(sXMLURL);
var oXSL = LoadXMLFile(sXSLURL);
oHTML = ProcessXMLAndXSL(oXML,oXSL
if(typeof(oHTML)=='string'
//IE
oDiv.innerHTML = oHTML;
} else {
//Mozilla
oDiv.appendChild(oHTML);
}
}
ASKER
Works - I am very gratefull thanks!
As a last remark, I am just curious to see that you don't use ActiveXObjects for IE?
In this case where would you be able to set an xsl parameter for the IE section (e.g. simialir to the following for Mozilla: oProcessor.setParameter(nu ll, "sortOrder", "descending"); ?
Thanks again!
As a last remark, I am just curious to see that you don't use ActiveXObjects for IE?
In this case where would you be able to set an xsl parameter for the IE section (e.g. simialir to the following for Mozilla: oProcessor.setParameter(nu
Thanks again!
ActiveX is still needed for IE, see this line: "oXML = new ActiveXObject('Msxml2.DOMD ocument'); "
Of course I have been trying out a lot before I got this working crossbrowser. As you said, I could not find complete examples on internet too, and had to dig through a lot of documentation. But it is worth it, because with this you can use AJAX and combine it with XSL. I think that is the best solution. The bad thing about many AJAX-stuff is that the response from the server must hold HTML-code. And in fact you don't want that. You just want to send the browser new information as XML, and then transform it on the browser.
With this method, the browser can receive just XML, transform it with the XSL that already has been loaded in the browser and pick the updated fragment from the transformation, to replace the current fragment. The only disadvantage is that the initial load of the page will take some time. But that is almost everywhere with Web 2.0 applications.
----
After loading the XSL, the function I posted before (SetXSLParam() ) can change existing parameters.
It should not be too hard to adapt it so that an existing parameter would be changed and a non-existing would be added. But as I see: parameters are only usefull if they have are being used in the XSL, and if they are being used in the XSL, then the parameter has to be set in the XSL. So a usefull parameter is always there already, no need to add one. Except of course if you are generating XSL on the fly, but then you already have a completely different way of working.
Of course I have been trying out a lot before I got this working crossbrowser. As you said, I could not find complete examples on internet too, and had to dig through a lot of documentation. But it is worth it, because with this you can use AJAX and combine it with XSL. I think that is the best solution. The bad thing about many AJAX-stuff is that the response from the server must hold HTML-code. And in fact you don't want that. You just want to send the browser new information as XML, and then transform it on the browser.
With this method, the browser can receive just XML, transform it with the XSL that already has been loaded in the browser and pick the updated fragment from the transformation, to replace the current fragment. The only disadvantage is that the initial load of the page will take some time. But that is almost everywhere with Web 2.0 applications.
----
After loading the XSL, the function I posted before (SetXSLParam() ) can change existing parameters.
It should not be too hard to adapt it so that an existing parameter would be changed and a non-existing would be added. But as I see: parameters are only usefull if they have are being used in the XSL, and if they are being used in the XSL, then the parameter has to be set in the XSL. So a usefull parameter is always there already, no need to add one. Except of course if you are generating XSL on the fly, but then you already have a completely different way of working.
http://developer.mozilla.org/en/docs/Using_the_Mozilla_JavaScript_interface_to_XSL_Transformations