1. Trang chủ
  2. » Công Nghệ Thông Tin

Building Oracle XML Applications phần 5 doc

89 324 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Building Oracle XML Applications phần 5 doc
Trường học University of Science and Technology of Hanoi
Chuyên ngành Database and XML Applications
Thể loại Lecture Material
Thành phố Hanoi
Định dạng
Số trang 89
Dung lượng 489,11 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Using the techniques we learned earlier, a default value for the connattribute can be supplied using an attribute of that name on the document element, like this: This causes the page t

Trang 1

SELECT *

FROM doctor

WHERE id = '{@id}'

</xsql:query>

This parameterized XSQL page can be used to retrieve information about doctors, given the value

of their email id in the requesting URL like this:

This XSQL page allows the requester to control all the parts of the syntax of the SELECT

statement You can use XML attributes with the same names as the parameters to provide defaults in case the requester does not provide a specific value

Taking the last example a step further, you can build a page that uses a parameter to represent the entire SQL statement:

Trang 2

8.1.4 Customizing the XSQL Results

The most basic way to get XML results from queries into your XSQL page is to include the text of the desired SQL query between the <xsql:query> and </xsql:query> tags Using this technique, each query in the page will produce the following structure by default:

• A <ROWSET> element containing the query's results

• A <ROW> element and a row identifier, for each row in the result set

• A child element for each non-NULL column in each <ROW>

The element names for each column in the result set are derived from the column names or column aliases if provided

8.1.4.1 Changing element names by aliasing columns

You can use the standard SQL columnname AS alias syntax to rename a column included in the

SELECT list or to specifically provide a column alias for a SQL expression like this:

<?xml version="1.0"?>

<xsql:query connection="scott" xmlns:xsql="urn:oracle-xsql">

SELECT dept.deptno AS department,

Trang 3

If you include the column alias in double quotes, the alias will be used verbatim; otherwise, names are converted to uppercase In this case, the double quotes are required, since a name with a dash in it, like TOTAL-SALARIES in the following example, is not a valid SQL column name:

8.1.4.2 Tailoring XML query results

In addition to using column aliasing and parameter values to control the query's XML output, you can also specify values for any combination of the <xsql:query> tag attributes in Table 8.1 This allows you to further refine each query's XML results

Table 8.1 xsql:query Attributes to Control XML Output

rowset-element

Element name to use as a parent for the rowset of query results The default name is <ROWSET> Set equal to the empty string to suppress printing an element for the rowset

row-element

Element name to use as a parent element for each row in the query results The default name is <ROW> Set equal to the empty string to suppress printing a row element

max-rows

Maximum number of rows to fetch from the query Useful in combination

with an ORDER BY in your query for fetching the top-N rows When used

in combination with skip-rows, it's easy to implement getting the next-N

rows from a query result to page through a set of query results The default is to fetch all rows

skip-rows Number of rows to skip over before returning the query results The

Trang 4

default is not to skip any rows

id-attribute Attribute name for the row identifier attribute for each row in the query

result The default is num

id-attribute-column

Column name to use to supply the value of the row identifier attribute foreach row in the query result The default is to use the row count as the value

null-indicator

If set to y or yes, causes a null-indicator attribute to be used on the element for any column whose value is NULL The default is to omit the element in the result for any column with a NULL value

tag-case

If set to upper, causes the element names for columns in the query result

to be in uppercase If set to lower, causes the element names for columns in the query result to be in lowercase The default is to use the case of the column name (or column aliases if provided) from the query.fetch-size

Explicitly sets the number of records retrieved in each round-trip to the database for this query This overrides the default fetch size set in the XSQL configuration file

For example, using rowset-element and row-element you can serve a datagram for a list of department numbers and a sum of all the salaries in each department as a <DEPARTMENT-LIST>document with nested <DEPARTMENT> elements The XSQL page for this looks like the following:

Trang 6

single row or a single column and you don't need the extra levels of <rowset> and <row> elements

in the resulting document As an example, the following XSQL page:

WHERE dept.deptno = emp.deptno

AND dept.deptno = {@dept}

<?xml version="1.0"?>

<xsql:query connection="xmlbook" rowset-element="" row-element=""

xmlns:xsql="urn:oracle-xsql">

/* This query returns one row, two columns */

SELECT 1 AS VALUE1, 2 AS VALUE2 FROM DUAL

Trang 7

<?xml version="1.0"?>

<xsql:query connection="xmlbook" rowset-element="" row-element="PERSON"

xmlns:xsql="urn:oracle-xsql">

/* This query returns two rows of one column each */

SELECT 'Emma' AS NAME FROM DUAL

Oracle XSQL Command Line page processor

XSQL-014: Resulting page is an empty document or had multiple document elements

If you are building a page with a query that you think should return a single row, you can guarantee that only a single row will be returned by using the max-rows="1" attribute on your query tag to avoid this situation

8.1.4.3 Using parameters in <xsql:query> tag attributes

In addition to using parameters in the SQL statement for an <xsql:query> tag, the values of

<xsql:query> tag attributes can also reference parameters This makes it easy for the requester

to pass in values for the attributes that control the query's XML output For example, a page like this:

<?xml version="1.0"?>

<xsql:query connection="xmlbook" cat="news" skip="0"

max-rows="2" skip-rows="{@skip}" xmlns:xsql="urn:oracle-xsql">

SELECT title,url

Trang 8

Skips the number of rows specified in the skip parameter before returning data

So the following URL:

</ROWSET>

If we add the URL parameter skip=2, then the skip-rows="{@skip}" attribute on the query tag will evaluate to 2, overriding the default value of zero So the result of requesting:

http://xmlapps/examples/BrowseHeadlines.xsql?skip=2

Trang 9

is the XML datagram showing just the third and fourth rows of the results:

Here we've seen parameters in use for attribute values to control the behavior of individual

<xsql:query> tags, but as a final note to this section, we recall that it's also possible to use a parameter to control the page-level connection By simply including a parameter in the

connection attribute on the document element, you can build a page that allows the requester to provide the name of the named connection as a parameter to the request So, with a page that begins like this:

<page xmlns:xsql="urn:oracle-xsql" connection="{@conn}">

the requester can provide a parameter like conn="prod" or conn="test" to select between the production database whose named definition is prod and the test database instance whose

Trang 10

named definition is test Using the techniques we learned earlier, a default value for the connattribute can be supplied using an attribute of that name on the document element, like this:

<page xmlns:xsql="urn:oracle-xsql" conn="prod" connection="{@conn}">

This causes the page to default to the connection named prod, but allows the conn="test"parameter to be supplied to override the default value and use the test database connection for

a particular request

8.1.5 Using Multiple Queries on a Page

Our examples so far have all used a single <xsql:query> tag as the only element in the XSQL page However, there is no limit to the number of queries that can appear in a page or to where the <xsql:query> tags can appear in the page The only overriding rule is that the XSQL page itself must be a well-formed XML document: an <xsql:query> tag can appear anywhere an element can appear in a document:

<a-query connection="xmlbook" xmlns:xsql="urn:oracle-xsql">

<cannot go-here="<xsql:query> SELECT * FROM table1 </xsql:query>"/>

<or-here<xsql:query> SELECT * FROM table2</xsql:query>/>

<!

Ok here, but has no effect in a comment

<xsql:query> SELECT * FROM table3 </xsql:query>

Trang 11

An <xsql:query> tag cannot appear:

• Inside the value of an XML attribute

• As part of an element or attribute name

• Outside the document element

Of course it's legal, even useful sometimes, to include an <xsql:query> tag inside a comment between <! and > in the page, but when it's inside a comment it won't be executed by the XSQL page processor

Example 8.3 shows an XSQL page for returning a client's stock portfolio information; it includes

<xsql:query> tags wherever we need dynamic output inserted

Example 8.3 Portfolio of Quotes Using Multiple Queries

<?xml version="1.0"?>

<client-portfolio connection="xmlbook" xmlns:xsql="urn:oracle-xsql">

<xsql:query rowset-element="" row-element="">

select to_char(sysdate,'DD-MON-YYYY') as "effective-date" from dual

FROM quotes q, portfolio_stocks ps

WHERE q.symbol = ps.symbol

AND ps.owner = {@id}

</xsql:query>

Trang 12

</client-portfolio>

Let's examine a few things that make this XSQL page different from those we've seen previously:

• The page starts with the <client-portfolio> element instead of an <xsql:query> tag

• Since it must appear on the document element of the page, the connection="xmlbook"

appears on the <client-portfolio> element instead of on any individual <xsql:query> element

• The page uses three <xsql:query> tags instead of just a single one

• The second <xsql:query> tag appears nested inside the static elements <client> and

<info>

• Two different queries in the page both refer to the {@id} parameter

Requesting this page with the URL:

http://xmlapps/examples/ ClientPortfolio.xsql?id=101

produces the output shown in Example 8.4

Example 8.4 Results of an XSQL Page with Multiple Queries

Trang 13

The second query in the page produces an additional, nested element structure for the <name>,

<homeaddress>, and <workaddress> elements in the result This is an example of what

automatically occurs when the datatype for a column is a user-defined object type, rather than one of the simple scalar datatypes like VARCHAR2, DATE, or NUMBER

In this case, since we define the clients table as:

CREATE TABLE clients (

id NUMBER PRIMARY KEY,

name PERSON_NAME,

homeaddress ADDRESS,

workaddress ADDRESS

);

the user-defined PERSON_NAME and ADDRESS datatypes are being used and the results

automatically reflect the nested structure of their attributes

If we come up with a simple query over the Oracle Data Dictionary views USER_TAB_COLUMNS and USER_TYPE_ATTRS, we can quickly build an XSQL page like the one in Example 8.5 to examine the structure of any table or type in our schema interactively

Trang 14

Example 8.5 Describe.xsql Explores the Oracle Data Dictionary

Trang 15

We can see that the results are as we expected them to be: the user-defined type names appear

as the datatypes for the columns NAME, HOMEADDRESS, and WORKADDRESS Repeating the request to examine the structure of the ADDRESS type:

http://xmlapps/examples/Describe.xsql?obj=address

produces the results shown in Example 8.7

Example 8.7 Querying the Data Dictionary for Column-Type Information

Trang 16

used the SQL UNION operator to select information from a combination of the

USER_TAB_COLUMNS and USER_TYPE_ATTRS tables Since a table and a type cannot both have the same name, for any given value of the obj parameter passed our page, the query will return either table information or type information, but not both

8.1.6 Producing XML from SQL with Nested Structure

Let's look more closely at the different ways to produce XML with nested structure.Structured columns can be one of three types:

• Strongly typed, user-defined object

• Strongly typed, user-defined collection

• Untyped collection based on a SQL statement

The underlying Oracle XML SQL Utility for Java natively supports producing richly structured XML from SQL statements that make use of these types, so your Oracle XSQL Pages has this capability We'll look at two simple examples

8.1.6.1 Using user-defined object types

Suppose that you have used the object/relational capabilities of Oracle8i to create a user-defined

object type called POINT using the command:

CREATE TYPE POINT AS OBJECT (X NUMBER, Y NUMBER);

and have used your new POINT type as the datatype of the ORIGIN column in your LOCATION table with the following DDL statement:

CREATE TABLE LOCATION (

NAME VARCHAR2(80),

ORIGIN POINT

Trang 17

);

Suppose further that you have inserted a row into this LOCATION table using an INSERT

statement with the POINT( ) constructor, like this:

INSERT INTO LOCATION VALUES ( 'Someplace', POINT(11,17) );

COMMIT;

Then you can construct an XSQL page like point.xsql that does a query over the LOCATION table

like this:

<xsql:query connection="xmlbook" xmlns:xsql="urn:oracle-xsql">

SELECT name, origin

FROM location loc

WHERE loc.origin.x = {@x-coord}

Trang 18

8.1.6.2 Using the CURSOR operator for nested rowsets

If you have not created object types that contain a predefined structure, you can still introduce nested structure into your SQL queries using the CURSOR operator, which allows you to select a

nested rowset as a column in the SELECT list of a query While almost any nested query is legal

to include inside the CURSOR operator in the SELECT list, the most useful query selects a nested set of detail rows for the current master row

Taking the familiar dept and emp tables as an example, the following XSQL page contains a query that selects the DNAME column from the dept table and, for each row returns a nested rowset of the EMPLOYEES from the emp table who work in that department:

<xsql:query connection="demo" xmlns:xsql="urn:oracle-xsql">

Trang 19

</ROW>

</ROWSET>

Note that the second column in the SELECT statement is the CURSOR( ) expression used to select the details Since it is a column like any other, it can be aliased to the column name EMPLOYEES by using the AS COLUMNALIAS syntax as shown above Since the EMPLOYEES column is a nested rowset, it appears as a set of <EMPLOYEES_ROW> elements nested within its parent <ROW> Given the following facts, you can quickly see how structured information can be created on the fly in almost any structure you are looking for:

• One or more CURSOR operators can be used in the SELECT list of any SQL statement

• One or more CURSOR operators can be used in the SELECT list of SQL statements that appear inside any CURSOR operator (to any level of nesting)

• Virtually any valid SQL statement (including GROUP BY and ORDER BY, etc.) may appear with the CURSOR operator

• Any SQL statement can be included in an <xsql:query> tag in an XSQL page

This allows you to exploit the processing speed of the database for sorting and grouping instead

of having to rely on slower techniques that would attempt these operations on flat data from within the XSLT stylesheet

By using these query techniques in the <xsql:query> tags of an XSQL page, you can combine master/detail XML data pages with the database sorting and grouping These database

operations are applied to the data pages by the SQL engine before subsequently applying an XSLT

stylesheet to the resulting data page (as we learned earlier) In this way, we can transform the resulting data page into any presentation format you need

8.1.7 Providing a Fallback Query

Under normal circumstances, if an <xsql:query> tag in your XSQL page contains a SELECT statement that returns no rows when the page is processed, the <xsql:query> tag is simply replaced by an empty <ROWSET/> element with no <ROW> elements as children However,

sometimes it is useful to attempt an alternate query as a fallback when the original query produces no rows

This most often comes in handy when you want to look up some information by an exact match

on a parameter value in the original query, and then retry a different query which searches for a fuzzy match using the LIKE operator if no exact match is found Employing a fallback query in your XSQL page is easy For any <xsql:query> tag in your XSQL page, the XSQL page processor recognizes a nested <xsql:no-rows-query> tag as the fallback query to try in case the parent query retrieves no rows All of the attributes available to control the output of the <xsql:query>tag are equally functional on the nested <xsql:no-rows-query>

Trang 20

Consider the ValidateAirport.xsql page in Example 8.8 It implements an HTTP-based airport

validation service against a database table named AIRPORT containing the more than 9000 airports on the planet and their International Air Transport Association (IATA) three-letter abbreviations The page includes a single <xsql:query> tag that searches case-insensitively for

an airport whose three-letter code exactly matches the value of the {@code} parameter Nested inside the outer <xsql:query> is a <xsql:no-rows-query> that searches for any airports whose description contains the value of the {@code} parameter, case-insensitively using SQL's UPPER function

Example 8.8 XSQL Page to Validate Airport Codes

WHERE tla = UPPER('{@code}')

<xsql:no-rows-query max-rows="4" rowset-element="Error" row-element="Airport">

SELECT tla "Code", description "Description"

Note these highlights in the example page:

• The <xsql:query> sets rowset-element="Ok" while the <xsql:no-rows-query> sets rowset-element="Error" This allows the returned page to signal the success or failure

of the exact match while also providing additional information on matching airports in either case

• The <xsql:query> expects an exact match and specifies max-rows="1" while the

<xsql:no-rows-query> uses a max-rows="4" to return the first four fuzzy matches Any software that wants to validate the existence of an airport by code can do so over the Web by requesting a URL like:

http://xmlapps/examples/ValidateAirport.xsql?code=xml

Trang 21

This attempts to validate the existence of an airport with XML as its three-letter code Surprisingly, this request produces an exact match with the result:

Trang 22

<xsql:no-rows-query> itself can have a nested <xsql:no-rows-query> with no limit on the depth

8.2 Transforming XSQL Page Results with XSLT

Since the data page that results from executing the queries in your XSQL page template is an XML document, and since XSLT offers a robust, declarative mechanism for transforming XML

documents into anything else, we can put the two together to achieve a highly effective one-two punch:

1 The XSQL page assembles XML information relevant to the task at hand

2 The XSLT stylesheet transforms it into an appropriate format for delivery

We'll look at a few examples in this section that illustrate this approach

8.2.1 Associating a Stylesheet with an XSQL Page

To associate an XSLT stylesheet with an XSQL page, we use the standard technique prescribed by the W3C (see http://www.w3.org/TR/xml-stylesheet), the <?xml-stylesheet?> processing instruction It goes after the <?xml version="1.0"?> declaration and before the document element in your XSQL page It must include as attributes two key pieces of information required

to identify the stylesheet:

• An href attribute that describes the absolute or relative location of the desired stylesheet

• A type="text/xsl" attribute that indicates the type of stylesheet in use

Including an <?xml-stylesheet?> instruction of type "text/xsl" in your XSQL page causes the XML document obtained by expanding the XSQL page's <xsql:query> tags to be transformed by the indicated stylesheet in the server before returning the results to the requester Only an

<?xml-stylesheet?> instruction with an attribute of type="text/xsl" will be considered for use, since the XSQL page processor supports only this type of stylesheet

8.2.2 Using a Stylesheet to Produce HTML

A simple example of an XSQL page that includes a reference to an XSLT stylesheet is the

following:

<?xml version="1.0"?>

<?xml-stylesheet type="text/xsl" href="Bookmark.xsl"?>

<xsql:query connection="xmlbook" xmlns:xsql="urn:oracle-xsql">

SELECT title, url

Trang 23

FROM bookmark

ORDER BY title

</xsql:query>

This page queries information about web browser bookmarks from the bookmark table, and uses

the following Bookmark.xsl stylesheet to format the results:

Trang 25

Using an example of the desired HTML page as a template, this XSLT stylesheet:

1 Declares the xsl namespace on the root <html> tag so we can use XSL elements in the stylesheet to loop over data and plug values into the result page

2 Uses <xsl:for-each select="ROWSET/ROW"> to loop through all the <ROW> elements that appear as children of the <ROWSET> element, creating an HTML table row and table data tag for each <ROW> encountered

3 Specifies the attribute value template href="{URL}" on the <a> element to plug the value of the <URL> element from the current <ROW> into the <xsl:for-each> loop

4 Uses <xsl:value-of select="TITLE"/> to plug in the value of the <TITLE> element from the current <ROW> as the text for the hyperlink

Note the use of the {URL} syntax It is an example of an XSLT attribute value template, which

provides the handy shortcut syntax of {XPathExpression} for inserting the value of an XPath expression into an attribute value in the result document

The XSLT attribute value syntax of {XPathExpression} is very similar to the syntax for referring to a parameter in an XSQL page {@paramname}, but they are used in two different

contexts

The XSLT stylesheet transforms the XSQL data page into an HTML page that uses tables and has

a linked CSS stylesheet Bookmark.css to be used by the browser:

body { font-family: Garamond }

h2 { color: red }

td { font-size: 12pt ; background: yellow }

Requesting the page now produces the list of bookmarks with a different look

Trang 26

We'll learn even more of what you can do with XSLT stylesheets in Chapter 9, but from this simple example you should be able to see that the clean separation of powers between the XSQL page for data and the XSL stylesheet for transformation is going to be big Really big!

8.2.3 Using a Stylesheet to Produce a Datagram

Besides serving your web bookmarks in HTML for convenient browser access and navigation, it makes sense to serve the data in the XML Bookmark Exchange Language (XBEL) (see

http://www.python.org/topics/xml/xbel/ ) XBEL is an XML DTD created by the Python XML Special Interest Group (see http://www.python.org/sigs/xml-sig/ ) to support the automated exchange of web links over the Web

We can copy the Bookmark.xsql page to a new filename like XBEL-Bookmark.xsql; replacing the

href attribute in the <?xml-stylesheet?> instruction with the name of an XSLT stylesheet that transforms the XSQL data page into a valid XBEL document:

<?xml version="1.0"?>

<?xml-stylesheet type="text/xsl" href="XBEL.xsl" ?>

<xsql:query connection="xmlbook" xmlns:xsql="urn:oracle-xsql">

SELECT title, url

FROM bookmark

ORDER BY title

</xsql:query>

We happen to have the XBEL.xsl stylesheet, which does just this, lying around:

<xbel xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

Trang 27

1 Declares the xsl namespace on the root <xbel> tag so we can use XSL elements in the stylesheet to loop over data and plug values into the result document

2 Uses <xsl:for-each select="ROWSET/ROW"> to loop through all the rows of data in the XSQL data page, creating one <bookmark> element for each <ROW> encountered

3 Specifies the attribute value template href="{URL}" on the <bookmark> element to plug the value of the <URL> element from the current <ROW> of the <xsl:for-each> loop

4 Uses <xsl:value-of select="TITLE"/> to plug in the value of the <TITLE> element from the current <ROW> as the value of the XBEL document's <title> element

8.2.4 Using a Stylesheet on Static XML Documents

You can use the XSQL Servlet to do server-side XSLT transformation on any XML document While all of the examples we've seen so far have contained at least one <xsql:query> tag and a connection attribute indicating what database connection to use, neither of these characteristics

is a strict requirement If the XSQL page processor doesn't notice any <xsql:query> tags to process, it moves on to perform its normal server-side XSLT transformation based on the

<?xml-stylesheet?> processing instruction in your document

Trang 28

The simplest way to feed a static XML document to the XSQL page processor is to rename it to

have an xsql file extension For example, take Jon Bosak's dream.xml, an XML version of

Shakespeare's A Midsummer Night's Dream, shown in Example 8.9

Example 8.9 Excerpt from XML Version of A Midsummer Night's Dream

<?xml version="1.0"?>

<?xml-stylesheet type="text/xsl" href="shakespeare.xsl" ?>

<!DOCTYPE PLAY SYSTEM "play.dtd">

<PLAY>

<TITLE>A Midsummer Night's Dream</TITLE>

<FM>

<P>Text placed in the public domain by Moby Lexical Tools, 1992.</P>

<P>SGML markup by Jon Bosak, 1992-1994.</P>

<P>XML version by Jon Bosak, 1996-1998.</P>

<P>This work may be freely copied and distributed worldwide.</P>

</FM>

<PERSONAE>

<TITLE>Dramatis Personae</TITLE>

<PERSONA>THESEUS, Duke of Athens.</PERSONA>

<PERSONA>EGEUS, father to Hermia.</PERSONA>

causes the XSQL page processor to transform dream.xsql using the associated shakespeare.xsl

stylesheet and return the formatted results to the requester Technically speaking, it would be

fine if dream.xsql had no <?xml-stylesheet?> instruction The net effect would be to serve the

XML document for A Midsummer Night's Dream to the requester verbatim Serving a raw XML

document using the XSQL page processor with no <xsql:query> tags and no

<?xml-stylesheet?> instruction would only make sense if you intended to introduce either of these instructions into the document later If no dynamic data and no server-side XSLT

Trang 29

transformation are necessary, letting your web server serve the static dream.xml page off the

filesystem will be faster

A more mundane use for an XSQL page with purely static XML elements might be as a prototyping technique to put some static XML elements in place—representing information you will eventually query from a database—while you work on the XSLT stylesheets to present those elements For example, say we start by keeping the menu structure of our web site in a static XML document like the one shown in Example 8.10

Example 8.10 Static XML Datagram Describing Web Site Structure

By associating the SiteMenu.xsl stylesheet from Example 8.11 to the XSQL page containing the

site structure elements, the HTML page for the web site's navigation bar is produced

Trang 30

Example 8.11 Simple XSLT Stylesheet for an HTML Menu Bar

<img border="0" align="absmiddle" src="{icon}"/>

<a href="{url}"><b><xsl:value-of select="name"/></b></a>

2 Uses <xsl:for-each select="website/categories/category"> to loop through all the

<category> elements that appear as children of the <categories> element within the

<website> element, creating an HTML table data tag for each <category> encountered

3 Specifies the attribute value template src="{icon}" on the <img> element to plug the value of the <icon> element from the current <category> into the loop

4 Specifies the attribute value template href="{url}" on the <a> element to plug in the value of the <url> element from the current <category>

5 Uses <xsl:value-of select="name"/> to plug in the value of the <name> element from the current <category> as the text for the hyperlink

Now if we request the URL:

http://xmlapps/examples/SiteMenu.xsql

the XSQL page processor produces the HTML results shown in Figure 8.3

Trang 31

Figure 8.3 Web site menu bar rendered with a stylesheet

If the structure of the site becomes more dynamic later on, you can substitute the static XML tags

in the XSQL page with dynamic XML results using the now familiar <xsql:query> tag as shown in Example 8.12

Example 8.12 Querying Web Site Categories from a Table

<?xml version="1.0"?>

<?xml-stylesheet type="text/xsl" href="SiteMenu.xsl"?>

<website connection="xmlbook" xmlns:xsql="urn:oracle-xsql">

<xsql:query rowset-element="categories" row-element="category"

8.2.5 Offline Publishing of XSQL Pages

We've seen how to use the XSQL Pages facility to materialize data and apply XSLT

transformations If the data used in a page is not changing frequently, you can improve

Trang 32

performance by processing the XSQL page offline and serving the static results instead of dynamically transforming the same content on each request We can use the XSQL command-line utility to process any XSQL page offline to support this style of working where it makes sense To process an XSQL page offline, simply use the oracle.xml.xsql.XSQLCommandLine class and send the output to standard out or to a filename we provide as an argument on the command line Command-line page processing can be useful as:

• An automation technique to produce the results of XSQL pages from interactively or periodically executed batch scripts

• A data page "snapshot" technique to deliver an example XML document to a web designer who has no access to a database connection

• An optimization technique to avoid requerying database information that does not change frequently by capturing it as static XML elements

The full syntax of running the XSQL command-line utility is:

java oracle.xml.xsql.XSQLCommandLine xsqlURI [outputFile]

If you take advantage of the \bin\xsql.bat DOS batch file and \bin\xsql shell script that are

provided as a convenience with the XSQL Pages distribution, you can use the shorter command: xsql xsqlURI [outputFile]

Both the batch file and the shell script set up the CLASSPATH to contain all of the required jar

files, then call Java to run the oracle.xml.xsql.XSQLCommandLine class Note that you may need to edit the path values in the script for the xsql script to work in your environment

You can set the value of parameters your page uses by providing them on the command line in the following way:

xsql StatusReport.xsql week=27-SEP-99 title="My Status"

If you want to send the output to an output file instead of standard out, the output file comes before the parameters, like this:

xsql StatusReport.xsql MyReport.html week=27-SEP-99 title="My Status"

8.3 Troubleshooting Your XSQL Pages

While you're developing your XSQL pages, if for any reason you receive an unexpected result, the following techniques may help diagnose the problem

Trang 33

8.3.1 Common Problems for XSQL Pages with No Stylesheet

If your page does not include any <?xml-stylesheet?> instructions, there are only a few problems

that can affect the page:

• If you request the page and receive a result that still has your <xsql:query> tags in it, the problem is one of the following:

o You are running an XSQL page from within the JDeveloper 3.1 environment and have not properly included the "XSQL Runtime" library in your current project's

library list To remedy this, select Project Project Properties from the main JDeveloper 3.1 menu, and select the Libraries tab of the Project Properties dialog Click the Add button and select the "XSQL Runtime" library from the list to add it to

your project

o You are running the XSQL Servlet using a servlet engine that has not been correctly configured to associate the oracle.xml.xsql.XSQLServlet class to the file

extension *.xsql To remedy, see Appendix B for instructions on setting this up

correctly for your servlet engine

o You have used an incorrect namespace URI to define the xsql namespace prefix for use on your <xsql:query> elements To remedy, double-check that your namespace declaration is exactly as follows:

you have forgotten to put a connection="connname" attribute on the document element

of your page The document element is the outermost enclosing element of the template XSQL pages do not strictly require a connection attribute; however, if any of the action elements used on the page (<xsql:query>, for example) require a database connection to

do their job, you'll get this error message as part of the resulting data page

• If your returned data page contains <xsql-error> elements like:

• <xsql-error action="xsql:query">

• <statement>select ename, sal where sal > 50</statement>

• <message>ORA-00923: FROM keyword not found where expected</message>

</xsql-error>

your query has a syntax error that needs to be resolved

• If your page contains <ERROR> tags like:

• <ERROR>

Trang 34

SELECT 10+20, SYSDATE+2 FROM dual

because the first column's unaliased column name would be the string "10+20" and the second column's unaliased column name would be "SYSDATE+2", neither of which is a valid XML element name Use column aliases like:

SELECT 10+20 AS thirty, SYSDATE+2 AS futuredate FROM dual

to make sure that the column names are legal XML element names

8.3.2 Common Problems for Pages with a Stylesheet

If your page includes one or more <?xml-stylesheet?> instructions, errors in your data page like the ones mentioned in the previous section can cause the transformation to behave incorrectly If you request a page and receive an unexpected result or blank screen in your browser, chances are your stylesheet is not correctly matching the structure of the elements in your data page This can happen because:

• The underlying data page had errors, so the elements your stylesheet was expecting weren't actually in the data page it tried to process

• The select patterns or {attribute value templates} in your stylesheet contained typographical errors or incorrect path expression

In either case, you need to take a look at what data page the XSLT engine is seeing when it performs the transformation If your page does not disallow it with an

allow-client-style="no" attribute on its document element, temporarily disable the

transformation your page is attempting to perform by adding the parameter

xml-stylesheet=none to the URL requesting the page For example if you are receiving strange

or blank transformation results from a page called SomePage.xsl, you can request the page again

with the URL:

http://xmlapps/SomePage.xsql?xml-stylesheet=none

to view the raw data page underneath After your page is working correctly, you may wish to prevent further client overrides of your stylesheet (including the ability to disable the stylesheet

Trang 35

with xml-stylesheet=none) by adding the allow-client-style="no" attribute to your XSQL page's document element

8.3.3 Summary of Basic Error Messages

If you receive an XSQL error message, the following information may help you determine what the problem is and what action to take to resolve it:

XSQL-001: Cannot locate requested XSQL file Check the name

Cause : You requested a page that the XSQL page processor cannot find

Action: Make sure the path to the file is correct As a test, put an HTML file in the same

directory and try to request it from your browser

XSQL-002: Cannot acquire database connection from pool: connname

Cause : A database error prevented the XSQL page processor from acquiring a connection

from the pool of connections it maintains for the connection named connname

Action: This could be caused by a database shutdown or a database resource's being

exceeded Check the connection using SQL*Plus (or some JDBC program, if available, if the problem is specific to JDBC) Contact the database administrator to find out if there are problems with the server

XSQL-003: Failed to find 'XSQLConfig.xml' file in server CLASSPATH

Cause : The directory containing the file XSQLConfig.xml is not listed in CLASSPATH

Action: Make sure you have included the name of the directory where the XSQLConfig.xml

file is located in the Java CLASSPATH of your servlet engine The way to set the

CLASSPATH of the servlet engine is different for each engine, but typically involves changing configuration files or setting the CLASSPATH environment variable before starting your web server Detailed instructions for setting up the XSQL Servlet properly are included in Appendix B

XSQL-004: Could not acquire a database connection named: connname

Cause : Your page specifies a value for the connection attribute on its document element that does not correspond to a named connection defined in the <connectiondefs> section

of the XSQLConfig.xml file

Action: Check the value of your connection attribute for typographical errors If it's correct,

make sure that there is a matching <connection> entry in the <connectiondefs> section

of the XSQLConfig.xml file If it's there, make sure that your servlet engine's CLASSPATH

Trang 36

is not pointing at some archive or directory containing another XSQLConfig.xml file that might be found before the one you're looking at

XSQL-005: XSQL page is not well-formed

Cause : Your XSQL page does not parse properly because it is not well-formed XML Action: This error is accompanied by the specific XML Parser error, including line and

character position information, to help correct the error After correcting the syntax error

in your page, request the page again to see the results You can use the Check XML Syntax feature in Oracle JDeveloper 3.1 to check the well-formedness of your XSQL

page before attempting to request it

XSQL-006: XSLT stylesheet is not well-formed: stylesheet.xsl

Cause : Your XSLT stylesheet does not parse properly because it is not well-formed XML

Action: This error is accompanied by the specific XML Parser error, including line and

character position information to help correct the error After correcting the syntax error

in your stylesheet, request the XSQL page that references it again to see the results You

can use the Check XML Syntax feature in Oracle JDeveloper 3.1 to check the

well-formedness of your XSLT stylesheet before attempting to request an XSQL page that uses it

XSQL-007: Cannot acquire a database connection to process page

Cause : The named connection referenced in the XSQL page's connection attribute was valid, but the attempt to connect to the database using the information for this connection

in XSQLConnections.xml produced an error

Action: The specific error should be given in the error message Check the values of the

<username>, <password>, <dburl>, and <driver> elements for this connection name nested inside your <connection> definition in the <connectiondefs> section of

XSQLConfig.xml

XSQL-008: Cannot find XSLT Stylesheet: stylesheet.xsl

Cause : You specified an href attribute on a <?xml-stylesheet?> instruction whose value references an XSLT stylesheet the XSQL page processor cannot find Alternatively, if your href attribute indicates a stylesheet using an HTTP-based URL, the attempt to retrieve the stylesheet over the Web failed

Action: Make sure that the path to the file is correct The stylesheet URI is relative to the

location of the requested XSQL page, unless specified as an absolute URL If you are trying

to use an HTTP-based URL, make sure that the address is correct and that you've defined

Trang 37

the proxy server settings appropriately in the XSQLConfig.xml file if your server sits

behind a firewall

XSQL-009: Missing arguments on command line

Cause : You failed to provide the minimum number of arguments to the XSQL

command-line utility

Action: Provide at least the name of the XSQL page to process, and optionally the name of

an output file

XSQL-010: Error creating: outfilename

Cause : The XSQL command-line utility encountered an error opening the outfilename file

for writing the results of the page processing request

Action: Check that the directory exists, that you have permission to write in it, that the file

doesn't already exist and is read-only, and that your disk has space left on it

XSQL-011: Error processing XSLT stylesheet: stylesheet.xsl

Cause : The XSQL page processor encountered a runtime error while processing your

stylesheet

Action: This error could be caused by the use of an undefined function or unrecognized

element in the xsl namespace in the stylesheet It is accompanied by the specific error raised by the XSLT Engine to assist in tracking down the problem

XSQL-012: Cannot read XSQL page

Cause : The XSQL page exists but an I/O error was encountered trying to open it

Action: Make sure that the contents of the file are not corrupt and verify the file

permissions on your page Specifically, the page must be readable by the user under which the servlet engine is running

XSQL-013: XSQL page URI is null or has an invalid format

Cause : This error only occurs if the XSQL Servlet is used by a servlet engine which

incorrectly implements the Servlet API

Action: Try another servlet engine The list of supported servlet engines appears in

Appendix B

XSQL-014: Resulting page is an empty document or had multiple document elements

Trang 38

Cause : You suppressed the default rowset-element and/or row-element attributes on an

<xsql:query> tag at the root of your XSQL page such that the resulting XML

representation of your query results is not a well-formed XML document

Action: Use max-rows="1" to limit the number of rows or don't suppress the row-elementand the rowset-element attributes if your query returns more than one column

XSQL-017: Unexpected error occurred

Cause : An unexpected Java exception was thrown by a user-written action handler or by

the XSQL page processor itself A complete stack trace of the offending statement accompanies the error page

Action: If the unexpected error is caused by your own action handler, debug the problem

using Oracle JDeveloper 3.1's remote debugging feature, as described in Chapter 16, to find out why the exception is being thrown If the error is thrown by the XSQL page processor itself, report the problem to Oracle Support with a test case that reproduces the problem

XSQL-018: Unexpected error occurred processing stylesheet: stylesheet.xsl

Cause : An unexpected Java exception was thrown by a user-written XSLT extension

function or by the Oracle XSLT processor itself A complete stack trace of the offending statement accompanies the error page

Action: If the unexpected error is caused by your own XSLT Java extension function,

debug the problem using Oracle JDeveloper 3.1's remote debugging feature to find out why the exception is being thrown If it was thrown by the Oracle XSLT processor itself, report the problem to Oracle Support with a test case that reproduces the problem

Trang 39

Chapter 9 XSLT Beyond the Basics

In this chapter, I delve into some of the most common kinds of transformations you will want to

do on datagrams In the process, we'll explore several XSLT features and techniques you can use

to perform these transformations

9.1 Using XSLT Variables

This section explains how to use XSLT variables and how to steer clear of some common traps that first-time XSLT developers run into when trying to use them

9.1.1 What Are XSLT Variables?

XSLT variables allow you to assign a meaningful name to the value of an XPath expression or result tree fragment and to refer to that value by name later The value assigned to a variable can

be any of the four basic XPath data types (string, number, boolean, and node-set) or a literal tree of XML nodes

Defining a variable is easy You just use:

<xsl:variable name="varname" select="XPathExpression"/>

to assign the value of the XPathExpression to the variable named varname, or the alternative syntax:

If you use the latter syntax, and if the tree of nodes you include between <xsl:variable> and

</xsl:variable> is a single text node like this:

<xsl:variable name="varname">Some Value</xsl:variable>

then this is equivalent to setting the variable to a string value containing the value of that text node

Trang 40

A common mistake developers make when assigning a string value to a variable is to use:

<xsl:variable name="var" select="MyString"/>

This is not syntactically wrong, but it does not do what you think Recall that the value of the select attribute on

<xsl:variable> is an XPath expression, and that the XPath expression MyString selects the set of <MyString> elements that are children of the current node So assuming that your source document does not have any <MyString> elements that are children of the current node, the variable var will be

assigned a value that is an empty node-set To assign the string 'MyString' to the variable var, you need to include the value

in quotes to be treated as a literal string and not as a pattern matching an element name:

<! Extra enclosing quotes around 'MyString' >

<xsl:variable name="var" select="'MyString'"/>

or you can use the following less error-prone alternative:

<xsl:variable name="var">MyString</xsl:variable>

Variables can be defined inside a template or at the top level of the stylesheet If you define a variable at the top level of the stylesheet outside any template, as a direct child of the

<xsl:stylesheet> element, you can reference the variable in any template in the stylesheet If

defined inside a particular template, the value of a variable may be referenced on any sibling elements following the <xsl:variable> element that assigned the value, as well as on any descendent elements of those siblings To refer to the value of a variable when it is in scope, use the $varname notation This example illustrates the variable scoping rules:

<xsl:template match="something">

<a>

<!

| Count number of ROW elements have a SAL greater than 2000

| and assign to a variable named 'var'

+ >

<xsl:variable name="var" select="count(ROW[SAL > 2000])"/>

<b><xsl:value-of select="$var"/></b><! $var is visible here >

<c abc="{$var}"><! and here in an attribute value template >

Ngày đăng: 08/08/2014, 18:21

TỪ KHÓA LIÊN QUAN