Scripting mot MSXML
...fordrer MSIE 5+ og MSXML (helst versjon 4) installert
Vis DOM-treet
Se på følgende to filer:
| Råmaterialet til Olympiade eksempelet | |
| Som XML: all_results.xml | som DOM-tre i en Alert-boks. |
| Råmaterialet til Bok eksempelet | |
| Som XML: bokliste.xml | som DOM-tre i en Alert-boks. |
Koden som viser DOM-treet i en Alert-boks er slik:
function showURL(adr)
{
try
{
var objDOM = new ActiveXObject("Msxml2.DOMDocument");
objDOM.async = false;
if (objDOM.load(adr))
alert(objDOM.xml);
else
alert("Error: " + objDOM.parseError.reason);
}
catch(e)
{
alert("Error: " + e);
}
}
Merk linja:
var objDOM = new ActiveXObject("Msxml2.DOMDocument");
Det er her vi involverer MSXML. MSXML kommer i flere varianter. Vi kan navngi versjonen dersom vi ønsker en bestemt versjon, f.eks.:
var objDOM = new ActiveXObject("Msxml2.DOMDocument.4.0");
Merk at vi kan ha flere versjoner installert samtidig, og de kan kjøre . Hvis du lurer på hvilken versjon du har på din maskin så prøv denne siden: www.bayes.co.uk/xml/index.xml?/xml/utils/msxml_sniffer.htm
.XSLT-transformasjon
Vi vet at MSIE kan foreta XSLT-transformasjoner "on-the-fly" på klientsiden når vi laster opp en XML-fil med referanse til en XSL- eller XSLT-fil. I dette eksempelet skal vi se at vi også kan programmere en XSLT-transformasjon.
Vi bruker olympiaderesultatene: all_results.xml , og skriver en transformasjon som plukker ut 100m resultatene:
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" version="1.0" encoding="ISO-8859-1" indent="yes"/> <xsl:template match="/"> <xsl:apply-templates select="IOC/OlympicGame"/> </xsl:template> <xsl:template match="OlympicGame"> <h2><xsl:value-of select="@place"/></h2> <xsl:apply-templates select="event[@track='100m']"/> </xsl:template> <xsl:template match="event"> <xsl:apply-templates select="athlet"> <xsl:sort select="result" order="ascending"/> </xsl:apply-templates> </xsl:template> <xsl:template match="athlet"> <div> <xsl:value-of select="result"/> : <xsl:value-of select="name"/> </div> </xsl:template> </xsl:stylesheet>
HTML-fila som drar det hele, kun100.html, er i sin helhet slik:
<html>
<head>
<title>Olympic 100m results</title>
</head>
<body onload="init()">
<h2>Olympiske 100m resultater</h2>
<!-- we will place the result from the transformation here -->
<div id="displayDiv"></div>
<script language="javascript">
// on load
function init()
{
// load the XML-file
domDoc1=new ActiveXObject("Msxml2.DOMDocument")
domDoc1.async=false
domDoc1.load(
"http://www.ia.hiof.no/~borres/commondata/olympiade/all_results.xml")
// load the transformation
domDocForXsl=new ActiveXObject("Msxml2.FreeThreadedDOMDocument")
domDocForXsl.async=false
domDocForXsl.load("kun100.xslt")
// XSL Transformation
xslTpl = new ActiveXObject("Msxml2.XSLTemplate")
xslTpl.stylesheet = domDocForXsl
var xslProc = xslTpl.createProcessor()
xslProc.input = domDoc1
// do the transformation
xslProc.transform
htmlCode = xslProc.output
// it is too tempting to do this a non-DOM way
// innerHTML is not W3C, but widespread in browsers
displayDiv.innerHTML = htmlCode
}
</script>
</body>
</html>
Vi ser at transfomasjonene kalles når XML-fila lastes opp, så vi oppnår ikke noe annet enn det vi ville gjøre ved å legge en referanse til XSLT-fila i XML-fila.
.Parameterstyrt XSLT
Det ville være svært tungvindt om vi ikke kunne parameterstyre XSLT-transformasjoner. Det ville innbære at vi måtte skrive en egen transformasjon for alle operasjoner vi skulle gjøre. Parameterstyring er en mulighet i alle XSLT-biblioteker, og vi finner slike i Java (f.eks.: Xalan), Python (f.eks.: 4suite) og i C#-biblioteker.Nå skal vi forsøke og programmere dette på kientsiden, ved hjelp av DOM, MSXML og Javascript.
Vi bruker olympiaderesultatene: all_results.xml , og skriver en XSLT-transformasjon som ser slik ut:
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <!-- the global parameters that will be nmanipulated --> <xsl:param name="where"/> <xsl:param name="what"/> <xsl:template match="/"> <xsl:apply-templates select="IOC/OlympicGame[@place=$where]"/> </xsl:template> <xsl:template match="OlympicGame"> <xsl:apply-templates select="event[@track=$what]"/> </xsl:template> <xsl:template match="event"> <xsl:apply-templates select="athlet"> <xsl:sort select="result" order="ascending"/> </xsl:apply-templates> </xsl:template> <xsl:template match="athlet"> <div> <xsl:value-of select="result"/> : <xsl:value-of select="name"/> </div> </xsl:template> </xsl:stylesheet>
Merk at det er ingen referanse til XSLT-fila i XML-fila. Vi skal sette opp denne koplingen i Java scriptkoden. I tillegg trenger vi en HTML-fil som skal huse koden vår og vise transformasjonsresultater. Du kan starte denne her og se på resultatet. service2.html
Fila service2.html er i sin helhet slik:
<html>
<head>
<title>Olympic results</title>
</head>
<body onload="init()">
<h2>Olympiske sprintresultater</h2>
<hr/>
<table><tr>
<td>
Olympiade: <select name="OLSelect" size="1" onchange="select()">
<option value="Barcelona">Barcelona</option>
<option value="Atlanta">Atlanta</option>
<option value="Atlanta">Sidney</option></select>
</td><td>
Øvelse: <select name="EVSelect" size="1" onchange="select()">
<option value="100m">100m</option>
<option value="200m">200m</option>
<option value="400m">400m</option></select>
</td>
</tr></table>
<hr/>
<!-- we will place the result from the transformation here -->
<div id="displayDiv"></div>
<script language="javascript">
var domDoc1
var domDocForXsl
// on first time load
function init()
{
// load the XML-file
domDoc1=new ActiveXObject("Msxml2.DOMDocument")
domDoc1.async=false
domDoc1.load(
"http://www.ia.hiof.no/~borres/commondata/olympiade/all_results.xml")
// load the transformation
domDocForXsl=new ActiveXObject("Msxml2.FreeThreadedDOMDocument")
domDocForXsl.async=false
domDocForXsl.load("choose.xslt")
// show default
select();
}
// user respons on select
function select()
{
// what user has selected
var index = OLSelect.selectedIndex;
var selectedOL = OLSelect.options(index).text;
index = EVSelect.selectedIndex;
var selectedEV = EVSelect.options(index).text;
// XSL Transformation
xslTpl = new ActiveXObject("Msxml2.XSLTemplate")
xslTpl.stylesheet = domDocForXsl
xslProc = xslTpl.createProcessor()
xslProc.input = domDoc1
// Pass parameters to the XSL stylesheet
xslProc.addParameter("where",selectedOL)
xslProc.addParameter("what",selectedEV)
xslProc.transform
htmlCode = xslProc.output
// it is too tempting to do this a non-DOM way
// innerHTML is not W3C, but widespread in browsers
displayDiv.innerHTML = htmlCode
}
</script>
</body>
</html>
Dette åpner for en type systemløsninger som kan plassere mye av prosesseringsarbeidet på klienten. La oss anta at du skal undersøke dine konti og transaksjonshistorie i banken. Du kan laste ned en komplett XML-beskrivelse av ditt kundeforhold og søke i denne bare ved hjelp av nettleseren. Serveren og kommunikasjonskanalene avlastes og behovet for å ta kontakt med serveren oppstår bare dersom du skal gjøre endringer i din portofolio, f.eks. betale regninger.
.XML-øyer
I eksemplene ovenfor har vi lastes ned de aktuelle filene, bygget DOM-trær og holdt disse i variable. Her skal vi se på en løsning der vi kan laste opp XML-filer og plassere dem i det som refereres til som XML-islands i dokumentet. Så kan vi plukke dem derfra og bygge trær etter behov. Vi bruker en enkel XML-fil med bøker som rådata: bokliste.xml
Følgende fil viser hvordan vi kan endre layout på et stykke data ved hjelp av to alternative XSLT-tansformasjoner:
<html>
<head>
<title>XML-Islands</title>
</head>
<body onload="init()">
<h1>Bokliste</h1>
<div>Velg layout:
<select name="ViewSelect" size="1" onchange="select()">
<option value="Tabell">Tabell</option >
<option value="Liste">Liste</option >
</select >
</div>
<div id="displayDiv"></div>
<script language="javascript">
// on first time load
function init()
{
raadata.async = false;
// get the data
raadata.load("bokliste.xml");
// show default
select();
}
// user respons on select
function select()
{
//selected index and string
var index = ViewSelect.selectedIndex;
var selection = ViewSelect.options(index).text;
var xslString = selection + "xsl";
var stylesheet=document.getElementById(xslString)
var showPiece = raadata.transformNode( stylesheet.documentElement );
displayDiv.innerHTML = showPiece ;
}
</script >
<XML id="raadata"></XML>
<XML id="Tabellxsl" src="tabell.xsl"></XML>
<XML id="Listexsl" src="liste.xsl"></XML>
</body>
</html>
De to transformasjonsfilene er svært enkle. Tabell.xsl:
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" version="1.0" encoding="ISO-8859-1" indent="yes"/> <xsl:template match="/"> <table border="1"> <xsl:for-each select="/literature/book"> <tr> <td><xsl:value-of select="title"/></td> <td><xsl:value-of select="category"/></td> <td><xsl:value-of select="author"/></td> </tr> </xsl:for-each> </table> </xsl:template> </xsl:stylesheet>
og Liste.xsl:
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" version="1.0" encoding="ISO-8859-1" indent="yes"/> <xsl:template match="/"> <ul> <xsl:for-each select="/literature/book"> <li><xsl:value-of select="title"/></li> </xsl:for-each> </ul> </xsl:template> </xsl:stylesheet>