Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 89 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
89
Dung lượng
608,16 KB
Nội dung
<xsl:value-of select="oracleUrl:EncodeURLArgs($text)"/> </xsl:when> </xsl:choose> </xsl:template> </xsl:stylesheet> This example stylesheet selects a string value for a urlBase variable of: http://foo.com/SomeService and a string value for a urlArgs variable of: company=at & t / mobilcom which contains some spaces, an ampersand, and a slash. To test this example transformation, you can use any XML file as the source and try the following: • With James Clark's xt XSLT 1.0 processor: $ xt anyfile.xml PortableURLEncoderTest.xsl • With Michael Kay's Saxon XSLT 1.0 processor: $ saxon anyfile.xml PortableURLEncoderTest.xsl • With the Oracle XSLT 1.0 Processor: $ oraxsl anyfile.xml PortableURLEncoderTest.xsl All three processors produce the following identical output: http://foo.com/SomeService?company=at%20%26%20t%20%2F%20mobilecom We can write a stylesheet that refers to extension functions in several different namespaces (only one of which we're expecting to be usable by the current processor at transformation time) because an XSLT 1.0-compliant processor signals errors only if you actually try to use the function. By wrapping the extension function in a named template that uses <xsl:choose> and function-available( ) to selectively invoke the correct function, we can avoid the situation of ever invoking a function that is not available. 16.3.4 Debugging Your XSLT Java Extension Functions You will certainly need to debug your XSLT Java extension functions to make sure they are working correctly. Using JDeveloper 3.1, you have two choices for how to do this, both straightforward. If you are using XSLT in combination with XSQL Pages, you can follow the steps we outlined earlier for debugging XSQL page action handlers. If you set breakpoints in the Java code for your own XSLT extension functions, the debugger will stop at your breakpoint when your function is invoked by the XSLT processor. If you want to debug from the command line, you can use JDeveloper 3.1 remote debugging support to debug the command-line Oracle XSLT processor. In order to remotely debug the oraxsl command-line utility, do the following: • For the simplest possible experience, make sure you run the oraxsl command-line utility using the Java 1.2 VM supplied with JDeveloper 3.1. This VM natively supports remote debugging on Windows NT, where you'll be using JDeveloper 3.1. If you've installed JDeveloper 3.1 in the C:\jdev31 directory, for example, the complete path to the Java VM is C:\jdev31\java1.2\bin\java.exe. • Run the oraxsl command-line utility using the remote debugging argument to the Java VM. If you are trying to test the transformation of source.xml by the style.xsl stylesheet that makes use of your extension functions, the exact command will be: java -XXdebug oracle.xml.parser.v2.oraxsl source.xml style.xsl If you run this command with the JDeveloper 3.1 Java VM, you will immediately see the following message on the console: *** Port is 4000 *** *** Waiting for debugger connection. *** At this point, the oraxsl program is halted and will not proceed to execute until you attach the JDeveloper 3.1 debugger to it. • In your JDeveloper 3.1 project where the source code for your Java XSLT extension functions resides, make sure that your project is set up for remote debugging. To check this setting, select Project Project Properties from the main menu, click the Run/Debug tab, and set the Debug As pop-up list to "Remote Debugging". • Set your desired breakpoints in your extension function source code. • Click the Debug icon in the toolbar. • When the Remote Debugging dialog appears, enter localhost for the machine name and 4000 for the port, then click Attach. When the debugger attaches to the oraxsl process, program execution begins, and you'll hit your breakpoints as soon as the XSLT processor invokes your extension functions. Chapter 17. XSLT-Powered Portals and Applications In this last chapter, we'll work our way through all of the important capabilities of XSLT in the context of building some interesting Oracle XML applications. By the end of this chapter, I predict you will be an incurable XSLT fanatic as its amazing flexibility transforms you into a more productive developer. 17.1 XSLT-Powered Web Store In this section, we'll build a simple site for a web store that offers the basic functionality illustrated in Figure 17.1 . Figure 17.1. Page map of the Everything.com web site Visitors to the site will be able to see featured items on the home page and can click the name of one of our "shops" to see a home page specific to that shop. They can search the site for a product, and whenever a product appears, they can click a link to see other products by the same manufacturer. 17.1.1 Turning HTML Mockup into an XSLT stylesheet All product information needs to be displayed consistently across the web store. Our web design team has provided us with an HTML mockup, shown in Figure 17.2 , of how each product should look on the site. The HTML file for the mockup is shown in Example 17.1 . Figure 17.2. Mockup of product display for our web store Example 17.1. Source for HTML Mockup of Product Information <html> <body> <center> <table border="0"> <tr> <td valign="top"> <b>Java in a Nutshell : A Desktop Quick Reference</b> by David Flanagan <br>Other products by <a href="xxxx">O'Reilly</a> <br> <table border="0"><tr> <td><img src="images/1565924878.gif"></td> <td valign="middle"> <b>List Price:</b><strike>29.95</strike><br> <b>Our Price: <font color="blue">20.97</font></b><br> You Save: <b>8.98</b> </td> </tr></table> </td> </tr> </table> </center> </body> </html> We'll use Dave Raggett's Tidy tool (described in Chapter 6 ) to convert the web designer's HTML source code into an indented, well-formed XML file that will evolve into an XSLT stylesheet that produces the same look and feel. Run Tidy as follows: tidy -asxml -indent ProductMockup.html > Product.xsl The tidy command produces a well-formed XML document in the Product.xsl file, shown in Example 17.2 , which we can use as a starting point for the XSLT transformation. Example 17.2. Tidied HTML Mockup in XML <?xml version="1.0"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta name="generator" content="HTML Tidy, see www.w3.org" /> <title> </title> </head> <body> <center> <table border="0"> <tr> <td valign="top"> <b>Java in a Nutshell : A Desktop Quick Reference</b> by David Flanagan<br /> Other products by <a href="xxxx">O'Reilly</a><br /> <table border="0"> <tr> <td> <img src="images/1565924878.gif" /> </td> <td valign="middle"> <b>List Price:</b><strike>29.95</strike><br /> <b>Our Price: <font color="blue"> 20.97</font></b><br /> You Save: <b>8.98</b> </td> </tr> </table> </td> </tr > </table> </center> </body> </html> We can easily turn this tidied-up HTML into an XSLT stylesheet that uses a single root template. We just need to wrap the entire content of the document by: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <! For best results with HTML, best not to introduce any extra whitespace > <xsl:output method="html" indent="no"/> <xsl:template match="/"> <! Tidied-up HTML document goes here > </xsl:template> </xsl:stylesheet> We don't need the <!DOCTYPE> and/or <META> for our purposes, so we just delete it. At this point we have a valid, functional XSLT stylesheet that will output the static HTML mockup. In order to turn the static template into a page that dynamically formats production information from our database, we need to perform two basic steps: • Build an XSQL page to assemble the dynamic XML data page with all necessary production information • Replace the static sample information in the XSLT stylesheet with XSLT actions to plug our dynamic XML into the template HTML format. First things first; we'll start by building the XSQL page. 17.1.2 Building an XSQL Page to Assemble Data Figure 17.3 illustrates our database schema related to products on the web store. Figure 17.3. Database tables involved in the web store We create the following Store.xsql page to query the product information from the item, author, maker, and shop tables, using an outer join for the optional author information. Note that we've planned ahead and already associated the Product.xsl stylesheet we're building to format products for the Web. <?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="Product.xsl"?> <xsql:query max-rows="1" sid="1" connection="xmlbook" xmlns:xsql="urn:oracle-xsql"> SELECT description, author_name, maker_name, maker.id AS maker_id, shop_name, list_price, price, list_price - price AS yousave, sku FROM item, author, maker, shop WHERE item.author_id = author.id (+) AND item.maker_id = maker.id AND item.shop_id = shop.id AND shop.id = {@sid} </xsql:query> Since we'll just be testing the page initially, we add the following two additional attributes on the <xsql:query> action element: max-rows="1" Limits the product rows retrieved to a single row sid="1" Produces a default value for the "shop id" parameter sid in case none is specified in the request Requesting the Shop.xsql page through our browser, or using the xsql command-line utility, we see that this produces the following raw XML datagram: <?xml version = '1.0'?> <ROWSET> <ROW num="1"> <DESCRIPTION>Manifest Destiny</DESCRIPTION> <AUTHOR_NAME>Daisy Dines</AUTHOR_NAME> <MAKER_NAME>Fly Rite</MAKER_NAME> <MAKER_ID>3</MAKER_ID> <SHOP_NAME>Outdoors</SHOP_NAME> <LIST_PRICE>13.95</LIST_PRICE> <PRICE>11.16</PRICE> <YOUSAVE>2.79</YOUSAVE> <SKU>0140060898</SKU> </ROW> </ROWSET> With the basic data in place, we turn our attention to evolving the tidied-up HTML mockup, which is now an XSLT stylesheet, into a dynamic data display. 17.1.3 Plugging Dynamic Data into the Stylesheet We want to design the stylesheet to handle any number of rows of products that might be produced by the query over the product information. For each <ROW> element in the <ROWSET>, we want to create an HTML table row (<tr>) containing the product formatted in the standard way. So we introduce an <xsl:for-each> element to wrap the repeating HTML table row, with a select="ROWSET/ROW" pattern to select all rows in the dynamic XSQL data page. The contents of the <xsl:for-each> element will be instantiated in the resulting page for each ROWSET/ROW node selected. Inside the <xsl:for-each> loop, the selected <ROW> element is the current node, so any XPath expressions needed to refer to data in the row can use relative patterns. In particular, we do the following, using relative XPath expressions: 1. Replace the static product description: 2. <b>Java in a Nutshell : A Desktop Quick Reference</b> by David Flanagan with the dynamic expression: <b><xsl:value-of select="DESCRIPTION"/></b> by <xsl:value-of select="AUTHOR_NAME"/> 3. Replace the static text and hyperlink href value in: Other products by <a href="xxxx">O'Reilly</a> with: Other products by <a href="Maker.xsql?id={MAKER_ID}"> <xsl:value-of select="MAKER_NAME"/> </a> using an attribute value template {MAKER_ID} to substitute the current row's MAKER_ID into the href attribute value. This will be the id parameter passed to the Maker.xsql page we'll build later showing all products for a given maker ID. 4. Replace the static src attribute's URL: <img src="images/1565924878.gif" /> with: <img src="images/{SKU}.gif" /> 5. Replace the static price information: 6. <b>List Price:</b><strike>29.95</strike><br /> 7. <b>Our Price: <font color="blue">20.97</font></b><br /> You Save: <b>8.98</b> with: <b>List Price:</b><strike> <xsl:value-of select="LIST_PRICE"/> </strike><br/> <b>Our Price: <font color="blue"> <xsl:value-of select="PRICE"/> </font></b><br /> You Save: <b><xsl:value-of select="YOUSAVE"/></b> The resulting XSLT stylesheet is shown in Example 17.3 . Example 17.3. Stylesheet to Format Web Store Product Information <! Product.xsl: Format Web Store product information > <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <! For best results with HTML, best not to introduce extra whitespace > <xsl:output method="html" indent="no"/> <xsl:template match="/"> <html> <body> <center> <table border="0"> <xsl:for-each select="ROWSET/ROW"> <tr> <td valign="top"> <b><xsl:value-of select="DESCRIPTION"/></b> by <xsl:value-of select="AUTHOR_NAME"/><br/> Other products by <a href="Maker.xsql?id={MAKER_ID}"> <xsl:value-of select="MAKER_NAME"/> </a><br/> [...]... will fix one problem: < ?xml version="1.0"?> < ?xml- stylesheet type="text/xsl" href="Product.xsl"?> SELECT description, author_name, maker_name, maker.id as maker_id, shop_name, TO_CHAR(list_price, '99 999 9.00') TO_CHAR(price, '99 999 9.00') AS list_price, AS price, TO_CHAR(list_price - price, '99 999 9.00') AS yousave, sku FROM... of available products: SELECT shop_name, CURSOR( SELECT description, author_name, maker_name, maker.id AS maker_id, shop_name, blurb, TO_CHAR(list_price, '99 999 9.00') TO_CHAR(price, '99 999 9.00') AS list_price, AS price, TO_CHAR(list_price - price, '99 999 9.00') AS yousave, sku FROM item, author, maker WHERE item.author_id = author.id (+) AND item.maker_id = maker.id AND item.shop_id = shop.id ORDER BY shop_name,... shown in Figure 17 .9, leaving StoreTop.xsql for later Figure 17 .9 Map of XSQL pages to implement the web store Basically, these pages differ only in the WHERE clauses of their queries The query in the FeaturedItems.xsql page needs to look like this: SELECT description, author_name, maker_name, maker.id AS maker_id, shop_name, blurb, TO_CHAR(list_price, '99 999 9.00') TO_CHAR(price, '99 999 9.00') AS list_price,... this: SELECT description, author_name, maker_name, maker.id AS maker_id, shop_name, blurb, TO_CHAR(list_price, '99 999 9.00') TO_CHAR(price, '99 999 9.00') AS list_price, AS price, TO_CHAR(list_price - price, '99 999 9.00') AS yousave, sku FROM item, author, maker, shop WHERE item.author_id = author.id (+) AND item.maker_id = maker.id AND item.shop_id = shop.id AND item.id IN ( SELECT itemid FROM featured_items... skip-rows="{@paging-skip}" max-rows="{@paging-max}" The following NewsCategorySimple.xsql example shows how these parameters are used: < ?xml version="1.0"?> < ?xml- stylesheet type="text/xsl" href="NewsCategorySimple.xsl"?> SELECT count(id) FROM site_newsstory WHERE category =... skip-rows="{@paging-skip}" and max-rows="{@paging-max}" attributes on the action element The look and feel of the page is handled by the following simple stylesheet: < ?xml version="1.0"?> structural info into HTML | presentation for "Page N of M" and Next/Prev Links... displayProduct template inside its loop to format the current of product information Example 17.6 Calling Reusable Formatting with Named Templates . blurb, TO_CHAR(list_price,&apos ;99 999 9.00') AS list_price, TO_CHAR(price,&apos ;99 999 9.00') AS price, TO_CHAR(list_price - price,&apos ;99 999 9.00') AS yousave, sku FROM. blurb, TO_CHAR(list_price,&apos ;99 999 9.00') AS list_price, TO_CHAR(price,&apos ;99 999 9.00') AS price, TO_CHAR(list_price - price,&apos ;99 999 9.00') AS yousave, sku FROM. TO_CHAR(list_price,&apos ;99 999 9.00') AS list_price, TO_CHAR(price,&apos ;99 999 9.00') AS price, TO_CHAR(list_price - price,&apos ;99 999 9.00') AS yousave, sku FROM item, author, maker, shop