BizTalk Utilities CV ,   Jobs ,   Code library  
 
 
Page 6 of 7

 

Previous Page Table Of Contents Next Page

Tailoring Content Using XML and XSL

Dynamically Creating WML and HTML
Using XML and XSLT

The above example has demonstrated the use of XSLT to transform XML into HTML, but it's quite possible to use the same technique to generate whatever markup language you desire.

 

However, the XSL stylesheet was embedded in the XML document, which does not help us to tailor our transformation to other platforms. What we need is the ability to transform the XML source into our desired target platform dynamically, during runtime.

Using ASP to Manipulate the XML Source

I'm going to demonstrate how to use Microsoft ASP to manipulate the XML source at the server side. By doing this server-side, we include thin clients that need any savings in processing we can give them. It also means we do not need to have XSLT support in the client. The process should be transparent to the client when the transformation is done server side.

 

To try out my example, you'll need to have a web server installed. If you're running Windows 95/98/NT, you can use the Microsoft Personal Web Server (PWS), available for download from Microsoft in the NT 4.0 Option Pack. This installs IIS 4.0 for NT and, PWS for Windows 95/98. It is also supplied with Visual Studio. If you're using Windows 2000, you can use Microsoft Internet Information Server (IIS) 4/5.

 

In addition, you'll also need to have the MSXML component installed on your system. If you've installed IE5, you have it already. However, I recommend that you install the latest preview release.

Using the XMLDOM Object

The MSXML DOM object represents the top level of the XML source. It has methods and properties allowing us to obtain or create all other XML objects. I will illustrate the use of the MSXML DOM object using server-side VBScript. Here's books.asp:

 

<%

Set xml = Server.CreateObject("MSXML2.DOMDocument")

 

' Halt execution until the document has been loaded

xml.async = false

 

' Load books.xml

xml.load (Server.MapPath("books.xml"))

 

Set xsl = Server.CreateObject("MSXML2.DOMDocument")

xsl.async = false

 

If InStr(Request.ServerVariables("HTTP_USER_AGENT"), "Moz") Then

   xsl.load(Server.MapPath("books.xsl"))

Else

   xsl.load(Server.MapPath("bookswml.xsl"))

   Response.ContentType = "text/vnd.wap.wml"

End If

Response.write (xml.transformNode(xsl))

%>

 

For the example that follows, the reference to the XSL stylesheet in the XML document must be removed. That is, the line,

<?xml:stylesheet type="text/xsl" href="books.xsl"?>

must be deleted.

 

Before I look into how the ASP document works, let's try to view the document using:

 

Ø       Internet Explorer 5.0

Ø       Nokia WAP emulator

 

     

 

And there you have it! You now have a single XML data source that is viewable on two radically different platforms. Let's recall and refine the diagram that you saw earlier:

 

 

In this case, we have two XSL stylesheets:

 

Ø       books.xsl for generating HTML code

Ø       bookswml.xsl for generating WML code

 

The books.asp document will load the XML document and transform it to the target markup language using the appropriate XSL stylesheet. I will discuss the books.asp document first, and after that we'll look at the bookswml.xsl stylesheet. To start with, then, we create an MSXML DOM object:

 

<%

Set xml = Server.CreateObject("MSXML2.DOMDocument")

 

Next, we set the async property to false, so that the XML document is fully loaded before control is transferred back to the script:

 

xml.async = false

 


After that, the XML source is loaded using the load() method of the MSXML DOM object:

 

xml.load(Server.MapPath("books.xml"))

 

The Server.MapPath() method is used to map the specified relative path to the physical directory on the server.

 

Once the XML source is loaded, we create another MSXML DOM object to load the XSL stylesheet:

 

Set xsl = Server.CreateObject("MSXML2.DOMDocument")

xsl.async = false

Parsing the XML Document

The load() method of the MSXML DOM object actually parses the XML source while it's loading. It will generate an error if the XML source is not well formed, and we can use the parseError property to view any error information. Suppose that our XML source has an error:

 

   <Book Price="44">

      <ISBN>

         1861003129

      <ISBN> <!--- missing "/" -->

      ...

 

We can modify the ASP file to trap the error generated by the XML parser:

 

xml.load(Server.MapPath("books.xml"))

 

If xml.parseError.errorcode <> 0 Then

   Response.write "Error Code : " & xml.parseError.ErrorCode & "<br/>"

   Response.write "Reason : " & xml.parseError.Reason

End If

 

 

Next, we check the client type. The Request.ServerVariables collection will contain the user agent string. If it contains the word Mozilla, it must be a web browser; if not, we assume the user is using a WAP device. This is a simplified way of differentiating a web browser from a WAP browser. (A more elaborate way would be to check the USER_ACCEPT string for the word HTML (for web browser) or WML (for WAP browser.)

 

If InStr(Request.ServerVariables("HTTP_USER_AGENT"), "Moz") Then

 

If the user agent is a web browser, we load the XSL stylesheet for HTML:

 

xsl.load(Server.MapPath("books.xsl"))

 


To transform the XML source to the designated HTML document, we use the transformNode() method of the MSXML DOM object, which processes the XML source using the supplied stylesheet. It returns a string containing the result of the transformation:

 

   Response.write(xml.transformNode(xsl))

 

If the user isn't using a web browser, we assume that they are using a WAP device, and therefore transform the XML document using the necessary XSLT elements:

 

Else

   xsl.load (Server.MapPath("bookswml.xsl"))

 

As a WAP device expects the WML MIME type, we use the Response.ContentType property to set the appropriate type:

 

   Response.ContentType = "text/vnd.wap.wml"

 

   Response.write(xml.transformNode(xsl))

Applying the Stylesheet

With that, we're ready to take a look at the XSL stylesheet for generating the WML content. Here's bookswml.xsl:

 

<?xml version="1.0"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">

   <xsl:template match="/">

      <xsl:eval no-entities="true">

         '<![CDATA[

            <?xml version="1.0"?>

         ]]>'

      </xsl:eval>

      <xsl:eval no-entities="true">

         '<![CDATA[

            <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

               "http://www.wapforum.org/DTD/wml_1.1.xml">

         ]]>'

      </xsl:eval>

      <wml>

         <card id="card1" title="Books">

            <p>

               <xsl:for-each select="Library/Book">

                  <b><xsl:value-of select="Title" /></b><br/>

                  <i><xsl:value-of select="ISBN" /></i><br/>

                  <xsl:value-of select="Synopsis" /><br/>

                  <a>

                     <xsl:attribute name="href">

                        <xsl:value-of select="URL" />

                     </xsl:attribute>

                     <xsl:attribute name="title">

                        <xsl:value-of select="URL" />

                     </xsl:attribute>

                  </a><br/><br/>

               </xsl:for-each>

            </p>

         </card>

      </wml>

   </xsl:template>

</xsl:stylesheet>

 

To some extent, this is similar to the XSL stylesheet for generating HTML. For WML content, however, you need to include the following headers:

 

<?xml version="1.0"?>

<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

                     "http://www.wapforum.org/DTD/wml_1.1.xml">

 

The problem is that if I simply include these two lines into the XSL stylesheet, the XSLT processor will attempt to parse them, resulting in errors. What I need to do is preserve the two lines and not allow the parser to parse them.

 

I can use the <![CDATA[string]]> syntax to preserve the content of the string, and an <xsl:eval> element to evaluate the string:

 

      <xsl:eval no-entities="true">

         '<![CDATA[

            <?xml version="1.0"?>

         ]]>'

      </xsl:eval>

      <xsl:eval no-entities="true">

         '<![CDATA[

            <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

               "http://www.wapforum.org/DTD/wml_1.1.xml"

         >]]>'

      </xsl:eval>

 

The rest of the stylesheet is then very similar to the one we had for HTML.

Alternatives

Instead of using the <xsl:eval> element to include the headers, I could also have sent them in the ASP document:

 

Response.ContentType = "text/vnd.wap.wml"

Response.Write "<?xml version=""1.0""?>"

Response.Write "<!DOCTYPE wml PUBLIC ""-//WAPFORUM//DTD " & _

       "WML 1.1//EN"" ""http://www.wapforum.org/DTD/wml_1.1.xml"">"

 

In this case, you have to be careful with the double quotes. If you want to output double quotes in your string, use a double quote character (which is simply two double quotes) where you wish one to appear. The code download includes this alternative.

Customizing WML for Different WAP Browsers

In the last section, we looked at how to generate content for display on both web browsers and WAP browsers. In this section, we will apply what we have learned to the art of tailoring WML content for display on different WAP browsers.

 

For this example, we will consider the Nokia browser and Phone.com's browser. I will use the Nokia WAP toolkit and the UP.Simulator. The source code for all the files involved is given below.

 

The browser-specific features mentioned in this section are based on the emulators. In real life, it is important for developers to test an application on each different platform before deploying it.

Modules.xml

<?xml version="1.0" ?>

<Modules>

   <Module name="OS">

      <Title>Operating Systems</Title>

      <Description>

         This module teaches the fundamentals

         of Operating Systems

      </Description>

      <Year>1</Year>

      <URL>www.np.edu.sg/~OS</URL>

   </Module>

   <Module name="CSA">

      <Title>Computer Systems and Architecture</Title>

      <Description>

         This module teaches the fundamentals

         of Computer Systems

      </Description>

      <Year>2</Year>

      <URL>www.np.edu.sg/~CSA</URL>

   </Module>

   <Module name="WAD">

      <Title>Web Application Development</Title>

      <Description>

         This module teaches the basics

         of developing web applications

      </Description>

      <Year>3</Year>

      <URL>www.np.edu.sg/~WAD</URL>

   </Module>

</Modules>

Modules.asp

<%

Set xml = Server.CreateObject("MSXML2.DOMDocument")

xml.async = false

xml.load (Server.MapPath("modules.xml"))

 

Set xsl = Server.CreateObject("MSXML2.DOMDocument")

xsl.async = false

 

If InStr(Request.ServerVariables("HTTP_USER_AGENT"), "Nok") Then

   xsl.load(Server.MapPath("NokWML.xsl"))

Elseif InStr(Request.ServerVariables("HTTP_USER_AGENT"), "UP") Then

   xsl.load(Server.MapPath("UPWML.xsl"))

End If

 

Response.ContentType = "text/vnd.wap.wml"

Response.write (xml.transformNode(xsl))

%>

UPWML.xsl

<?xml version="1.0"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">

   <xsl:template match="/">

      <xsl:eval no-entities="true">

         '<![CDATA[

            <?xml version="1.0"?>]]>

         '</xsl:eval>

      <xsl:eval no-entities="true">

         '<![CDATA[

            <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

               "http://www.wapforum.org/DTD/wml_1.1.xml">

         ]]>'

      </xsl:eval>

      <wml>

         <card id="card1" title="Modules">

            <p align="center"><b>Modules List</b></p>

            <p>

               <xsl:for-each select="Modules/Module">

                  <b><xsl:value-of select="@name" /></b><br/>

                  <a>

                     <xsl:attribute name="href">

                        <xsl:value-of select="URL" />

                     </xsl:attribute>

                     <xsl:attribute name="title">

                        <xsl:value-of select="URL" />

                     </xsl:attribute>

                     <xsl:value-of select="Title" />

                  </a><br/>

               </xsl:for-each>

            </p>

         </card>

      </wml>

   </xsl:template>

</xsl:stylesheet>

NokWML.xsl

<?xml version="1.0"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">

   <xsl:template match="/">

      <xsl:eval no-entities="true">

         '<![CDATA[

            <?xml version="1.0"?>

         ]]>'

      </xsl:eval>

      <xsl:eval no-entities="true">

         '<![CDATA[

            <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"

               "http://www.wapforum.org/DTD/wml_1.1.xml">

         ]]>'

      </xsl:eval>

      <wml>

         <card id="card1" title="Modules List">

            <p>

               <table columns="3">

                  <xsl:for-each select="Modules/Module">

                     <tr>

                        <td>

                           <b><xsl:value-of select="@name"/></b>

                           <br/>

                        </td>

                        <td>

                           <a>

                              <xsl:attribute name="href">

                                 <xsl:value-of select="URL" />

                              </xsl:attribute>

                              <xsl:value-of select="Title" />

                           </a>

                        </td>

                        <td>

                           <b><xsl:value-of select="Year"/></b>

                           <br/>

                        </td>

                     </tr>

                  </xsl:for-each>

               </table>

            </p>

         </card>

      </wml>

   </xsl:template>

</xsl:stylesheet>

 

When a UP.Browser is used to view the page (Modules.asp), this is what is shown:

 

 

When a Nokia browser is used, the following will be seen:

 

 


The Modules.asp document detects the type of WAP device requesting the page, and loads the correct XSL stylesheet. In the case of the UP.Browser, the WML content generated does not contain a table, while the WML content for the Nokia browser contains a table with three columns. The reason for this is that the UP.Browser does not display tables correctly when there is an <a> element within a table cell. This is a good example of the different look-and-feel of current WAP 1.1 devices.

Retrieving Attribute Values

Finally, notice that the XML source has a <Module> element with a name attribute:

 

<?xml version="1.0" ?>

<Modules>

   <Module name="OS">

      <Title>Operating Systems</Title>

 

To extract the value of name in our XSL stylesheet, we use the @ character, followed by the attribute name:

 

                  <b><xsl:value-of select="@name" /></b><br/>

 

Page 6 of 7

 

Previous Page Table Of Contents Next Page
 

Recent Jobs

Software Developers Needed in Charl
Sr. Software Engineer - Analytics
Immediate Mainframe openings for Ch
Immediate TANDEM-TAL openings for C
Immediate ASP.NET/C# Openings for C

View all Jobs (Add yours)
View all CV (Add yours)



online fax
swimming pool contractor
conference calling services
water softener
Teleconference
Host Department NOLIMIT Web Hosting
MSN
sunglasses


    Email TopXML  

Front Page Daily Stuff TopXML Forum XML blogs XML Newsgroups BizTalk Biztalk Utilities Biztalk Utilities Tutorial B2B SAP XML Microsoft .NET Dotnet System XML Soapformatter SQLXML XMLserializer XQuery PHP PHP SimpleXML PHP XML Dom PHP XML RPC PHP XSLT Java Java Java XML Xalan Microsoft ASP ASP Schemas XML SQL Server XML XMLDom XSL XSL Tutorial XSLT Stylesheets General Javascript CSS XHTML WAP