Oracle8i Application Developer's Guide - XML Release 3 (8.1.7) Part Number A86030-01 |
Library | Service | Contents | Index

Customizing Presentation with XML and XSQL: Flight Finder, 6 of 8

## Formatting XML with Stylesheets

Flight Finder applies an XSLT transformation to render the XML results in a format suitable for the end-user's client device. This section describes the process.

For general information about the relationships between XML, XSLT, and XSQL Servlet, see XSQL Pages and XSQL Servlet Release Notes on Oracle Technology Network (OTN), http://technet.oracle.com/tech/xml

### One Stylesheet, One Target Device

Flight Finder uses XSL stylesheets to format the XML documents that represent query results. A stylesheet is itself an XML document that specifies how to process the nodes of another XML document. The processing instructions are defined in structures called templates, and a stylesheet formats a document by applying these templates to selected nodes.

For example, the XML document above contains nodes named ROWSET, ROW, CODE, etc. The following code (from flyHTMLdefault.xsl) shows how the stylesheet selects the CODE, DEPART_AIRPORT, and ARRIVE_AIRPORT nodes for each ROW in a ROWSET, and it applies templates to format the output.

    <?xml version="1.0"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'>
    ...
    <xsl:template match="/">
    <html>
    ...
      <xsl:for-each select="flightFinderResult/ROWSET/ROW">
        <tr>
          <td><xsl:apply-templates select="CODE"/></td>
           <td><xsl:apply-templates select="DEPART_AIRPORT"/></td>
             <td><xsl:apply-templates select="ARRIVE_AIRPORT"/></td>
              ...
         </tr>
         </xsl:for-each>
         ...
      </html>
     </xsl:template>
    <xsl:template match="CODE">Fly Oracle Airlines <xsl:value-of select="."/>
    </xsl:template>
    <xsl:template match="DEPART_AIRPORT">Leaving <xsl:value-of select="."/>
    </xsl:template>
    <xsl:template match="ARRIVE_AIRPORT">
     for <xsl:value-of select="."/>
    </xsl:template>
    ...
    </xsl:stylesheet>

In this example, the formatting is simple: it just prepends a string to the contents of each node. For example, when the XSLT processor gets to the CODE node, it prepends the string "Fly Oracle Airlines " to the value of that node. The resulting HTML looks like this:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    ...
    <TR>
     <TD>Fly Oracle Airlines OA0309</TD>
     <TD>Leaving Los Angeles</TD>
     <TD>for San Francisco</TD>
     ...
    </TR>
    ...
    </HTML>

In a browser (enter the URL http://localhost:7070/fly/fly.xsql?FROM=LAX&TO=SFO&xml-stylesheet=flyHTMLdefault.xsl).

Figure 8-3 shows the results displayed on the browser after the stylesheet has been applied to the XML.

#### Figure 8-3 Flight Finder: Results After Formatting the XML with Stylesheets

### Many Stylesheets, Many Target Devices

XSL stylesheets are the key to multiple devices, languages, and user interfaces. You can include multiple `<?xml-stylesheet?>` tags at the top of an XSQL Page, and each of those tags can define media and href attributes to associate a user agent with an XSL stylesheet (an HTTP request includes a user-agent header that identifies the device making the request). A processing instruction without a media attribute matches all user agents so it can be used as the fallback/default.

For example, the following XML code comes from fly.xsql. It includes several `<?xml-stylesheet?>` tags, including one that maps the stylesheet `flyVox.xsl` to the Motorola Voice Browser agent, and one that maps the `flyPP.xsl` stylesheet to the HandHTTP (Palm Pilot) agent.

    <?xml version="1.0"?>
    <?xml-stylesheet type="text/xsl" media="MSIE 5.0" href="flyHTML.xsl"?>
    <?xml-stylesheet type="text/xsl" media="Motorola Voice Browser"
    href="flyVox.xsl"?>
    <?xml-stylesheet type="text/xsl" media="UP.Browser" href="flyWML.xsl"?>
    <?xml-stylesheet type="text/xsl" media="HandHTTP" href="flyPP.xsl"?>
    <?xml-stylesheet type="text/xsl" href="flyHTMLdefault.xsl"?>

    <flightFinderResult xmlns:xsql="urn:oracle-xsql" connection="fly"
    lang="english">
    <xsql:stylesheet-param name="lang" value="{@lang}"/>
    <xsql:query tag-case="upper">
    ...
    </xsql:query>
    ...
    </flightFinderResult>

The two listings below show the XSLT code to format one result set row each for a Palm Pilot (flyPP.xsl) and a voice browser device (flyVox.xsl).

#### XSLT Code From flyPP.xsl:

     ...
      <xsl:for-each select="flightFinderResult/ROWSET/ROW">
        <tr>
          <td>
            <a>
              <xsl:attribute name="href">
                #<xsl:value-of select="CODE"/>
              </xsl:attribute>
              <b><xsl:value-of select="CODE"/></b>
            </a>
          </td>
          <td><xsl:apply-templates select="SCHED"/></td>
          <td><xsl:apply-templates select="GATE"/></td>
        </tr>
      </xsl:for-each>
      ...
        <xsl:template match="CODE">
          <xsl:value-of select="."/>
        </xsl:template>
        <xsl:template match="SCHED">
          at <b><xsl:value-of select="."/></b>
        </xsl:template>
        <xsl:template match="GATE">
          gate <b><xsl:value-of select="."/></b>
        </xsl:template>
      ...

#### XSLT Code from flyVox.xsl:

    ...
    <xsl:for-each select="flightFinderResult/ROWSET/ROW">
     <step><xsl:attribute name="name">
     step<xsl:value-of select="position()"/>
      </xsl:attribute>
       <prompt>
         <xsl:apply-templates select="CODE"/>
         <xsl:apply-templates select="SCHED"/>,
         <xsl:text>Do you take that one?</xsl:text>
       </prompt>
       <input type="OPTIONLIST" name="FLIGHT">
       <xsl:choose>
        <xsl:when test="position() = @NUM">
         <option>
          <xsl:attribute name="next">
           #<xsl:value-of select="CODE"/>
          </xsl:attribute>
          <xsl:text>Yes</xsl:text>
         </option>
          <xsl:if test="position() &lt; last()">
         <option>
          <xsl:attribute name="next">#step<xsl:value-of select="position() + 1"/>
          </xsl:attribute>
          <xsl:text>Next</xsl:text>
         </option>
        </xsl:if>
        <xsl:if test="position() &gt; 1">
         <option>
          <xsl:attribute name="next">#step<xsl:value-of select="position() - 1"/>
          </xsl:attribute>
          <xsl:text>Previous</xsl:text>
         </option>
        </xsl:if>
       </xsl:when>
      </xsl:choose>
     </input>
    </step>
    </xsl:for-each>
    ...

### Localizing Output

When you invoke the Flight Finder through its portal (index.html), you can choose a language for prompts and labels.

The Flight Finder supports in English, French, Spanish, and German. To do this, it uses a parameter to identify the end-user's language of choice and passes it from HTML to XSQL to XSL, then it selects the appropriate text from a file of translated messages. For example, here is an overview of how the application tracks a user's language preference (French) and selects a label in that language:

1. `index.html` (The user clicks a link to choose a language):

       <a href="http://localhost:7070/xsql/fly/index.xsql?lang=french">Français</a>

2. `index.xsql` (The XSQL Page stores the user's choice in a parameter):

       <xsql:set-stylesheet-param name="lang" value="{@lang}"/>

3. `flyHTML.xsl` (The stylesheet uses the language choice parameter to select a message from the message file):

       <xsl:value-of select= "document('messages.xml')/messages/msg[@id=101 and
       @lang=$lang]"/>

4. `messages.xml` (The message file stores the translated messages):

       <msg id="101" lang="french">Prochains vols sur Oracle Airlines</msg>

The following listings show these steps in context.

index.html displays HREF links that invoke index.xsql with URLs for each supported language.

    ..

For Web-to-Go

    <!-- Assumes default install to c:\xsql and Flight Finder files in c:\xsql\fly
    -->
    <ul>
     <li type="disc">
      <a href="http://localhost:7070/xsql/fly/index.xsql">English</a>
       </li>
       <li type="disc">
      <a
    href="http://localhost:7070/xsql/fly/index.xsql?lang=french">Fran&ccedil;ais</a>
       </li>
       <li type="disc">
      <a
    href="http://localhost:7070/xsql/fly/index.xsql?lang=spanish">Espa&ntilde;ol</a>
       </li>
       <li type="disc">
      <a href="http://localhost:7070/xsql/fly/index.xsql?lang=german">Deutsch</a>
       </li>
      </ul>
    ...

Next, the user's choice is extracted from the URL and plugged into a parameter in index.xsql. If the URL does not specify a language, a line in the following code sets it to English by default. This XSQL Page also defines a query (not shown here), which the XSQL Servlet sends to the database.

    <?xml version="1.0"?>
    <?xml-stylesheet type="text/xsl" media="Mozilla" href="indexHTML.xsl"?>
    ...
    <index xmlns:xsql="urn:oracle-xsql" connection="fly" lang="english">
    <xsql:set-stylesheet-param name="lang" value="{@lang}"/>
    ...
    </index>

When the database returns the query results, the XSQL Servlet formats them by applying an XSLT transformation. The following code is from the stylesheet flyHTML.xsl. It includes a line that opens the message file (messages.xml) and selects message 101 for a specified language.

    <?xml version="1.0"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'>
        <xsl:output media-type="text/html" method="html"/>
          <xsl:param name="lang" select="@lang"/>
           <xsl:template match="/">
              <html>
    ...
              <body>
              ...
    <!-- Next available flights -->
    <xsl:value-of select=
     "document('messages.xml')/messages/msg[@id=101 and @lang=$lang]"/>
      ...
             </body>
           </html>
         </xsl:template>
         ...
    </xsl:stylesheet>

The XML code below comes from messages.xml. In this file, a message represents information (such as a label or a prompt) that the Flight Finder sends to the client. Messages are identified by ID numbers, and each message is translated into each supported language. The code below shows four translations of message 101. Notice that translations can include code for international character sets, as in the German version of the message. You may need to set your browser to display such characters; for example, in Internet Explorer, choose View > Encoding > Western European (Windows).

    <?xml version="1.0"?>
    <messages>
    ...
      <msg id="101" lang="english">Oracle Airlines available flights</msg>
      <msg id="101" lang="french">Prochains vols sur Oracle Airlines</msg>
      <msg id="101" lang="spanish">Proximos vuelos sobre Oracle Airlines</msg>
      <msg id="101" lang="german">M&#246;gliche Fl&#252;ge mit Oracle Airlines</msg>
    ...
    </messages>

| Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
Library | Service | Contents | Index