Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ajax In Action (2006).pdf
Скачиваний:
63
Добавлен:
17.08.2013
Размер:
8.36 Mб
Скачать

Combining the XSLT and XML documents

481

 

 

elements in the XML namespace are recognized in the source document and not in the results document. The prefix xsl is used to define all our elements in the XSLT namespace. We can then set the template rule to the match pattern of / d, which references the whole document.

We can start building the table template that displays our results. We add the table tag e, giving the table an ID. The table header row f is next inserted, which contains the column names to be displayed to the user so she can understand what information is contained in the table.

By looping through the source node set, we obtain the remaining rows of the table. For this, we use the for-each loop g to iterate over the records to obtain the nodes that are located in phonebook/entry.

The column values have to be selected as we are looping through the document tree. To select the values from the nodes, we use value-of h, which extracts the value of an XML element and adds it to the output stream of the transformation. To specify the XML element whose text we want to retrieve, we use the select attribute with the element’s name. Now that we have built the XSLT file and created the code to dynamically generate the XML document, we can finish building the JavaScript code to see how the XSLT transformation structures our XML file into a viewable table when we combine them.

The next step takes us back to the client, which retrieves the files that we just created with the HTTP response.

12.4 Combining the XSLT and XML documents

Back on the client, we need to combine the XSLT and XML documents from the server. When using an XSLT transformation, we’ll find that the browsers differ on how they combine the two documents. Therefore, we first check to see what method the browser supports in order to load and combine our two documents.

Again we’re using the ContentLoader object, introduced in chapter 3. It is contained in the external JavaScript file, net.js. This file does all of the work of determining how to send the information to the server, hiding any browserspecific code behind the easy-to-use wrapper object.

<script type="text/javascript" src="net.js"></script>

Now we can begin the process of obtaining the server-side files and combining them on the client. In listing 12.7, the LoadXMLXSLTDoc() function is being called from the function GrabNumber() in listing 12.2. The function GrabNumber() passes in the values for the URL that generates the XML data, the XSL file, and

Check for loaded documents

482CHAPTER 12

Live search using XSLT

the output reference ID. With these three values, we are able to load the two documents and combine them when both have been completely loaded. After they have been loaded, we have to do some cross-browser coding in order to combine the XML and XSL files. You can see all of this happening in listing 12.7.

Listing 12.7 LoadXMLXSLTDoc

var xmlDoc;

b Declare global

 

 

 

var xslDoc;

variables

 

 

 

var objOutput;

 

 

 

 

function LoadXMLXSLTDoc(urlXML,urlXSL,elementID){

 

xmlDoc=null;

c Set variables

 

 

 

xslDoc=null;

to null

 

d Reference

 

objOutput = document.getElementById(

 

 

elementId);

 

 

output element

new net.ContentLoader(urlXML,onXMLLoad);

 

e

Load XML and

 

new net.ContentLoader(urlXSL,onXSLLoad);

 

 

XSL files

}

 

 

function onXMLLoad(){

 

f Handle XML

 

xmlDoc=this.req.responseXML;

 

document

doXSLT();

 

 

 

 

}

 

 

function onXSLLoad(){

 

g Handle XSL

 

xslDoc=this.req.responseXML;

 

document

doXSLT();

 

 

 

 

}

 

 

function doXSLT(){

if (xmlDoc==null || xslDoc==null){ return; } h if (window.ActiveXObject){

objOutput.innerHTML=xmlDoc.transformNode(xslDoc);

}

else{

var xsltProcessor = new XSLTProcessor(); xsltProcessor.importStylesheet(xslDoc); var fragment =xsltProcessor.

transformToFragment(

xmlDoc,document); objOutput.innerHTML = ""; objOutput.appendChild(fragment);

}

iTransformXML document

}

Combining the XSLT and XML documents

483

 

 

To simplify the client-side script, we need to declare three global variables b to hold three different objects. The first two variables, xmlDoc and xslDoc, are going to hold the XML and XSLT files returned from the server. The third variable, objOutput, holds the object reference to our DOM element where the results are to be inserted. With these variables defined, we can now build the function LoadXMLXSLTDoc(), which we invoked from the function GrabNumber().

Since we are loading two documents, we need a way to determine when they are both loaded. We do this by looking to see if the variables xmlDoc and xslDoc contain their respective documents. Before we start, we must set the variables to null c. This removes any data that may exist in the variables if this function is run more than once on the page. The output location for the results is set d by using the passed element ID from the function call. Now we call the ContentLoader etwice, once for the XML document and once for the XSL document. In each call, the ContentLoader will get the URL and then call another function to load the documents. onXMLLoad() floads the returned XML results into our global variable xmlDoc and then calls the function doXSLT() for future processing. onXSLLoad() gloads the XSL document into the global variable xslDoc and also calls the doXSLT() function.

Processing cannot continue until both documents have been loaded, and there is no way of knowing which will be loaded first, so the doXSLT() function first checks for that. It is called twice, once after the XML document is loaded and once after the XSL document is loaded. The first time it is called, one of our global variables is still set to null and we exit the function h. The next time it is called, the function will not exit since neither of the variables will be null. With both documents now loaded, we are able to perform the XSLT transformation i.

Once the two documents are loaded, we need to transform the XML document with the XSLT. As you can see by looking at the code in the listing, there are two different ways to do this, depending on the browser. Internet Explorer uses transformNode(), whereas Mozilla uses the XSLTProcessor object. Let’s examine these two different implementations of performing the transformation in greater detail.

12.4.1Working with Microsoft Internet Explorer

Internet Explorer makes it easy to transform the XML document with the XSLT with only a few lines of code. We use the transformNode() method, which takes the XML and XSLT documents and combines them in one step:

484CHAPTER 12

Live search using XSLT

if (window.ActiveXObject){ objOutput.innerHTML=xmlDoc.transformNode(xslDoc);

}

We first check to see if the browser supports the transformNode() method. We’ve done this here by testing for ActiveX object support. If it supports it, we call the transformNode() method on the global variable containing our XML data, passing it the global variable containing our XSLT data. The result of this transformation is added to the innerHTML of our result element, which then contains the newly formatted search results.

Now that we are able to format the results for Internet Explorer, let’s get this functioning for Mozilla-compatible browsers.

12.4.2Working with Mozilla

With Mozilla, we need to use the XSLTProcessor object, which lets us combine the XML and XSLT documents. Note that even though Opera and Safari both support the XMLHttpRequest object, they still do not support the XSLTProcessor object, and they cannot run this project without support from the server (we will address this issue in section 12.5.2). In the listing 12.8, we transform the XML document using the XSLT and display the formatted result set.

Listing 12.8 Invoking XSLT for Mozilla

else{

var xsltProcessor = new XSLTProcessor(); xsltProcessor.importStylesheet(xslDoc);

var fragment=xsltProcessor.transformToFragment(xmlDoc,document); objOutput.innerHTML = "";

objOutput.appendChild(fragment);

}

The first step is to initialize the XSLTProcessor object, which enables us to join the XML and XSLT files together. The importStylesheet method of the XSLTProcessor object allows us to import the XSLT file so that we can join it to the XML file in the upcoming steps. When the XSLT file is loaded into the processor, we are left with transforming the XML document. The XSLTProcessor is used again with a new method called transformToFragment(). The transformToFragment() method takes the XML file and combines it with the XSLT, and then returns the formatted result tree.

We replace the content that exists in our result element by setting the innerHTML with a blank string. This removes our loading animation from the