Java & XML 2nd Edition solutions to real world problems phần 9 pot

42 246 0
Java & XML 2nd Edition solutions to real world problems phần 9 pot

Đ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

Java & XML, 2nd Edition 333 Figure 14-3. XML output from supplyBooks.pl As you can see, this easily turned the library's simple Perl-based application into a component capable of supplying useful information to its clients, including the mytechbooks.com technical bookstore. Additionally, we were able to accomplish this without installing new software, changing the architecture of the library's system or application, or even writing a line of Java! 14.2 mytechbooks.com With the Foobar Public Library allowing access to an XML listing of its new books, mytechbooks.com is moving closer to its goal of providing up-to-date content to its customers. In addition, mytechbooks.com already has an established standard for using Java for application development. This makes the process of accessing and using the XML from the library even easier, as Java has the excellent support for XML we have been looking at throughout this book. You'll need to allow mytechbooks.com to provide an online listing of new books first, and then look at how to get this information out to its customers automatically. 14.2.1 Filtering XML Data If you remember, the Foobar Public Library allowed books on several different subjects to be entered into its system; mytechbooks.com wants only the books about computer-related subjects. Fortunately, the library captured this information in the subject attribute of the book element for each book in its XML data. The first task is to filter out any book whose Java & XML, 2nd Edition 334 subject is not "Computers". Once the technical books have been obtained, they should be formatted into an HTML page that can be shown to customers visiting mytechbooks.com. For this company and application, there is no static HTML, since the page showing new listings must be generated each time it is accessed. I'm going to use a servlet here for handling these responses. Although Apache Cocoon would be an excellent choice for converting the XML data from the library into an HTML response, mytechbooks.com is under tremendous time pressure to make these book listings available, and does not want to introduce such a large change into its system immediately; instead, it would prefer to use XML parsers and processors and then add Cocoon in as a second-phase addition. This means that you'll have to handle conversion from XML to HTML as well as the filtering of the data and the addition of other presentation-specific items, such as a company logo and menu bar. However, taking all the information at your disposal about XML and XSL, you remember that even without Cocoon you can use XSL to transform an XML document into HTML. Applying a transformation would also allow you to filter out the books that do not have the subject criteria that mytechbooks.com desires. With this in mind, it's simple to create an XSL stylesheet that can be applied to the XML response from the Foobar Public Library. Example 14-4 shows the beginning of this stylesheet, which handles generation of the HTML specific to the mytechbooks.com web site. Example 14-4. XSL stylesheet for Foobar Public Library book listings <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" > <xsl:template match="books"> <html> <head> <title>mytechbooks.com - Your Computer Bookstore</title> </head> <body background="/javaxml/techbooks/images/background.gif" link="#FFFFFF" vlink="#FFFFFF" alink="#FFFFFF"> <h1 align="center"> <font face="Arial" color="#00659C"> &lt;mytechbooks.com&gt; </font> </h1> <p align="center"> <i><b> Your source on the Web for computing and technical books. </b></i> </p> <p align="center"> <b><font size="4" color="#00659C"> <u>New Listings</u> </font></b> </p> <table border="0" cellpadding="5" cellspacing="5"> <tr> <td valign="top" align="center" nowrap="nowrap" width="115"> Java & XML, 2nd Edition 335 <p align="center"> <font color="#FFFFFF"><b> <a href="/javaxml/techbooks/">Home</a> </b></font> </p> <p align="center"> <font color="#FFFFFF"><b> <a href="/javaxml/techbooks/current.html">Current Listings</a> </b></font> </p> <p align="center"> <b><font color="#FFFFFF"> <i>New Listings</i> </font></b> </p> <p align="center"> <font color="#FFFFFF"><b> <a href="/javaxml/techbooks/contact.html">Contact Us</a> </b></font> </p> </td> <td valign="top" align="left"> <table border="0" cellpadding="5" cellspacing="5"> <tr> <td width="450" align="left" valign="top"> <p> <b> Welcome to <font face="courier">mytechbooks.com</font>, your source on the Web for computing and technical books. Our newest offerings are listed on the left. To purchase any of these fine books, simply click on the &quot;Buy this Book!&quot; link, and you will be taken to the shopping cart for our store. Enjoy! </b> </p> <p> <b> You should also check out our current listings, information about the store, and you can call us with your questions. Use the links on the menu to the left to access this information. Thanks for shopping! </b> </p> </td> <td align="left"> <! Handle creation of content for each new *computer* book > </td> </tr> </table> </td> </tr> </table> </body> </html> </xsl:template> </xsl:stylesheet> Java & XML, 2nd Edition 336 While this doesn't yet filter the incoming XML data or transform that data, it does take care of the HTML interface for the user. Often it is much easier to take care of these presentation details first, and then add the transformation-specific logic afterwards. When developing XSL stylesheets, particularly for web applications, you should test the results with your XSLT Processor using its command-line capabilities. This can help you ensure that the stylesheet is transforming your document as you expect at each step of its development; trying to debug a large stylesheet's problems once it is complete is much more difficult. For this example, you could access the supplyBooks.pl script in a web browser, save the results to an XML file, and test that and the stylesheet as you follow the examples. Similar to the Foobar Public Library's application, this provides a menu on the left with hyperlinks to other portions of the application, contains some text about the company and its offerings, and then leaves a right column open for the addition of new book listings. Before filtering the content, you need to add a template for outputting HTML content from a single book element's entry. As you recall, an entry looks like this: <book subject="Computers"> <title><![CDATA[Running Linux]]></title> <author><![CDATA[Matt Welsh]]></author> <publisher><![CDATA[O'Reilly & Associates]]></publisher> <numPages>729</numPages> <saleDetails> <isbn> 156592469X</isbn> <price>39.95</price> </saleDetails> <description><![CDATA[In the tradition of all O'Reilly books, Running Linux features clear, step-by-step instructions that always seem to provide just the right amount of information.]]></description> </book> You can then convert this to HTML with the following XSL template: <?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" > <xsl:template match="books"> <! Presentation of User Interface > </xsl:template> Java & XML, 2nd Edition 337 <xsl:template match="book"> <table border="0" cellspacing="1" bgcolor="#000000"> <tr> <td> <table border="0" cellpadding="3" cellspacing="0"> <tr> <td width="100%" bgcolor="#00659C" nowrap="nowrap" align="center"> <b><font color="#FFFFFF"> <xsl:value-of select="title" /> </font></b> </td> </tr> <tr> <td width="100%" align="center" nowrap="nowrap" bgcolor="#FFFFFF"> <font color="#000000"><b> Author: <xsl:value-of select="author" /><br /> Publisher: <xsl:value-of select="publisher" /><br /> Pages: <xsl:value-of select="numPages" /><br /> Price: <xsl:value-of select="saleDetails/price" /><br /> <br /> </b></font> <xsl:element name="a"> <xsl:attribute name="href">/servlets/BuyBookServlet?isbn= <xsl:value-of select="saleDetails/isbn" /> </xsl:attribute> <font color="#00659C">Buy the Book!</font> </xsl:element> </td> </tr> </table> </td> </tr> </table> <br /> </xsl:template> </xsl:stylesheet> This template matches the book element, and then creates a table with a heading in one row, and contents in the second row. The entire table is within another table with a black background, which results in the appearance of the table being surrounded by a beveled black border. The title is inserted into the header of the table, and the information about the book (author, publisher, pages, and price) is added to the content of the table. Finally, a link to a Java servlet, BuyBookServlet, is provided to allow easy access to purchasing the book. The value of the book's isbn element is supplied as an argument to this servlet, which enables it to load the book being purchased. In your XSL stylesheet, you should ensure that the line indicating the use of BuyBookServlet and the line with the xsl:value-of element selecting the book's ISBN number is actually one single line. If not, spaces and a carriage return could be inserted into the resultant URL, causing incorrect information to be passed to the servlet. The example stylesheet has this information broken into two lines because of the space constraints of the printed page. Java & XML, 2nd Edition 338 The last addition you need to make to your stylesheet is to ensure that the new template is applied, and that only books with the subject "Computers" are passed to the new template. You can reference the value of the subject attribute with the @ symbol in your stylesheet, and filter the requests with the select attribute on the xsl:apply-templates element: </td> <td align="left"> <! Handle creation of content for each new *computer* book > <xsl:apply-templates select="book[@subject='Computers']" /> </td> </tr> </table> This references the value of the attribute and compares it to a literal, enclosed within single quotes because the entire XPath expression is enclosed within double quotes. Because you are accessing an attribute of a nested element, you'll need to reference the element by name, and surround the expression on the element's attribute with brackets. This will ensure that only books with a subject of "Computers" have templates applied, and are therefore included in the HTML output. Once the stylesheet is complete, it can be saved as computerBooks.xsl and referenced programmatically by a Java servlet, which I'll show you how to write next. 14.2.2 XSLT from a Servlet With your stylesheet ready for use, you need to add Java code to apply it to the XML data from the Foobar Public Library. This data is accessed easily by using Java's java.net.URL class to make an HTTP request to the library's system. Once you have this set up, all that is left is to actually apply the XSL transformation programmatically. Example 14-5 shows the Java servlet code that loads the XML data from the library, and indicates where the transformation code would be inserted. Example 14-5. Java Servlet for transforming book listings into HTML package com.techbooks; import java.io.FileInputStream; import java.io.InputStream; import java.io.IOException; import java.io.PrintWriter; import java.net.URL; import javax.servlet.*; import javax.servlet.http.*; public class ListBooksServlet extends HttpServlet { /** Host to connect to for books list */ private static final String hostname = "newInstance.com"; /** Port number to connect to for books list */ private static final int portNumber = 80; /** File to request (URI path) for books list */ private static final String file = "/cgi/supplyBooks.pl"; /** Stylesheet to apply to XML */ private static final String stylesheet = "/home/bmclaugh/javaxml/techbooks/XSL/computerBooks.xsl"; Java & XML, 2nd Edition 339 public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); // Connect and get XML listing of books URL getBooksURL = new URL("http", hostname, portNumber, file); InputStream in = getBooksURL.openStream(); // Transform XML for InputStream into HTML output } } This simple servlet requests the Foobar Public Library's application through an HTTP request, and gets the XML response in an InputStream. 1 This stream should then be used as a parameter to the XSLT processor, as well as the XSL stylesheet defined as a constant in the servlet. There is currently no Java API that specifies how XSLT transformations can occur programmatically; however, each processor vendor should have classes that allow a transformation to be invoked from your Java code. I continue to look at using the Apache Xalan processor here; you should consult your processor's vendor for the method or methods to invoke in your own programs. For Apache Xalan, the XSLTProcessor class is provided in the org.apache.xalan.xslt package for just this purpose. It takes as parameters an XSLTInputSource wrapping the XML file to process, an XSLTInputSource wrapping the XSL stylesheet to apply, and an XSLTResultTarget to use for output of the transformation. All three of these helper classes are in the org.apache.xalan.xslt package as well. They can conveniently be created by passing in an InputStream (to XSLTInputSource) or an OutputStream (to XSLTResultTarget). You have the XML document as an InputStream, you can wrap the XSL stylesheet within a FileInputStream, and the servlet API provides easy access to the ServletOutputStream object through the getOutputStream() method on the HttpServletResponse object. The last detail to address is obtaining an instance of XSLTProcessor. Because there are several underlying mechanisms that can be used for processing, this class is not instantiated directly, but rather obtained through the XSLTProcessorFactory class, also in the org.apache.xalan.xslt package. You should be familiar with factory classes by now, so all that is left is to import the classes you'll need and add the processing method calls to the servlet: package com.techbooks; import java.io.FileInputStream; import java.io.InputStream; import java.io.IOException; import java.io.PrintWriter; import java.net.URL; import javax.servlet.*; import javax.servlet.http.*; 1 For more information on the URL class and Java I/O, see Java I/O by Elliotte Rusty Harold (O'Reilly). Java & XML, 2nd Edition 340 // Import Xalan XSLT Processor components import org.apache.xalan.xslt.XSLTInputSource; import org.apache.xalan.xslt.XSLTProcessor; import org.apache.xalan.xslt.XSLTProcessorFactory; import org.apache.xalan.xslt.XSLTResultTarget; public class ListBooksServlet extends HttpServlet { /** Host to connect to for books list */ private static final String hostname = "newInstance.com"; /** Port number to connect to for books list */ private static final int portNumber = 80; /** File to request (URI path) for books list */ private static final String file = "/cgi/supplyBooks.pl"; /** Stylesheet to apply to XML */ private static final String stylesheet = "/home/bmclaugh/javaxml/techbooks/XSL/computerBooks.xsl"; public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); // Connect and get XML listing of books URL getBooksURL = new URL("http", hostname, portNumber, file); InputStream in = getBooksURL.openStream(); // Transform XML for InputStream into HTML output try { XSLTProcessor processor = XSLTProcessorFactory.getProcessor(); // Transform XML with XSL stylesheet processor.process(new XSLTInputSource(in), new XSLTInputSource( new FileInputStream(stylesheet)), new XSLTResultTarget( res.getOutputStream())); } catch (Exception e) { PrintWriter out = res.getWriter(); out.println("Error: " + e.getMessage()); out.close(); } } } I could have also used JAXP 1.1's TrAX API for performing this translation. However, JAXP 1.1 is still pretty new as of this writing, and I see few people adopting it (yet). Additionally, most servlet engines, especially Tomcat, still ship with JAXP 1.0, and many are relying on that default behavior rather than supplying a newer version of JAXP. When this new servlet is requested, it in turn requests the XML data from the Foobar Public Library. This data (a listing of the newly available books) is then transformed and output to the screen as HTML. The response from the servlet should look similar to Figure 14-4. Java & XML, 2nd Edition 341 Figure 14-4. HTML output from mytechbooks.com new book listing Along with the menu links on the left (not implemented in this example), the newest book listings are printed in a very nice format, all with up-to-date information (thanks to the changes at the Foobar Public Library!) as well as links to buy the book with a few mouseclicks. Now mytechbooks.com customers can easily browse the new book listings online; all that is left is to push this information out to these customers, so they don't even have to type in a URL. I'll look at solving this difficult problem next. 14.3 Push Versus Pull So far, I have looked at building applications assuming that the application clients would always pull data and content. In other words, a user had to type a URL into a browser (in the case of the mytechbooks.com new book listings), or an application like the mytechbooks.com servlet had to make an HTTP request for XML data (in the case of the Foobar Public Library). While this is not a problem, it is not always the best way for a company like mytechbooks.com to sell books. Clients pulling data have to remember to visit sites they would buy items from, and often don't revisit those sites for days, weeks, or even months. While those clients may often purchase a large number of goods and services when they do remember, on average, those purchases do not result in as much revenue as if small purchases were made more frequently. Realizing this trend, mytechbooks.com wants to be able to push data to its clients. Pushing data involves letting the client know (without any client action) that new items are available or that specials are being run. This in turn allows the client to make more frequent purchases without having to remember to visit a web page. However, pushing data to clients is difficult Java & XML, 2nd Edition 342 in a web medium, as the Internet does not behave as a thick client: it is harder to send pop-up messages or generate alerts for users. What mytechbooks.com has discovered, though, is the popularity of personalized "start pages" like Netscape's My Netscape and Yahoo's My Yahoo pages. In talking with Netscape, mytechbooks.com has been hearing about a technology called Rich Site Summary (RSS), and thinks that may be the answer to its need to push data out to clients. 14.3.1 Rich Site Summary Rich Site Summary (RSS) is a particular flavor of XML. It has its own DTD, and defines what is called a channel. A channel is a way to represent data about a specific subject, and provides for a title and description of the channel, an image or logo, and then several items within the channel. Each item, then, is something of particular interest about the channel, or a product or service available. Because the allowed elements of an item are fairly generic (title, description, hyperlink), almost anything can be represented as an item of a channel. An RSS channel is not intended to provide a complete site's content, but rather a short blurb about a company or service, suitable for display in a portal-style framework, or as a sidebar on a web site. In fact, the different "widgets" at Netscape's Netcenter are all RSS channels, and Netscape allows the creation of new RSS channels that can be registered with Netcenter. Netscape also has a built-in system for displaying RSS channels in an HTML format, which of course fits into its Netcenter start pages. At this point, you may be a little concerned that RSS is to Netscape as Microsoft's XML parser is to Microsoft: difficult to integrate with other tools or vendors. Although originally developed by Netscape specifically for Netcenter, the XML structure of RSS has made it usable by any application that can read a DTD. In fact, many portal-style web sites and applications are beginning to use RSS, such as the Apache Jetspeed project (http://jakarta.apache.org/jetspeed), an open source Enterprise Information Portal system. Jetspeed takes the same RSS format that Netscape uses, and renders it in a completely different manner. Because of the concise grammar of RSS, this is easily done. As many users have start pages, or homepages, or similar places on the Web that they frequent, mytechbooks.com would like to create an RSS channel that provides new book listings, and then allows interested clients to jump straight to buying an item that catches their eye. This is an effective means to push data, as products like Netcenter will automatically update RSS channel content as often as the user desires. 14.3.2 Creating an XML RSS Document The first thing you need to do to use RSS is create an RSS file. This is almost too simple to be believed: other than referencing the correct DTD and following that DTD, there is nothing at all complicated about creating an RSS document. Example 14-6 shows a sample RSS file that mytechbooks.com has modeled. [...]... $TOMCAT_HOME/webapps/javaxml2/catalog .xml $TOMCAT_HOME/webapps/javaxml2/WEB-INF/lib/castor-0 .9. 2.jar $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/AddItemServlet.class $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/castor/Catalog.class $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/castor/Catalog.class $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/castor/ 363 Java &. .. & XML, 2nd Edition CatalogDescriptor.class $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/castor/ CatalogDescriptor$1.class $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/castor/Item.class $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/castor/ ItemDescriptor.class $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/castor/ ItemDescriptor$1.class $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/castor/... $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/castor/ ItemDescriptor$2.class $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/castor/ ItemDescriptor$3.class $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/castor/ ItemDescriptor$4.class $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/castor/ ItemDescriptor$5.class $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/castor/ ItemDescriptor$6.class $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/castor/types/... java. io.FileWriter; java. io.IOException; java. io.PrintWriter; javax.servlet.ServletException; javax.servlet.http.HttpServlet; javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpServletResponse; // Castor classes import org.exolab.castor .xml. Marshaller; import org.exolab.castor .xml. Unmarshaller; 361 Java & XML, 2nd Edition // Castor generated classes import javaxml2.castor.Catalog; import javaxml2.castor.Item;... class in a practical situation in the next section, so don't worry too much 3 59 Java & XML, 2nd Edition about it just yet You can compile the type files, as well as the other Castor-generated sources, with this simple command: javac -d javaxml2/castor/* .java javaxml2/castor/types/* .java At this point, you have classes that are ready to use I won't show you the source for these files here, because it's... example, to convert an XML element named "item" to a Java variable named "inventory" This allows for different representations of the same data within Java and XML, and can also really help you convert between legacy Java classes Imagine converting an old Java class to a new XML format, and then unmarshalling that new XML back into new Java classes In two easy steps, all of your old Java code is updated to. .. $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/castor/types/ LevelType.class $TOMCAT_HOME/webapps/javaxml2/WEB-INF/classes/javaxml2/castor/types/ LevelTypeDescriptor.class There's a lot more to Castor, as there will be to each of the packages I talk about This short introduction should get you started, and the documentation provided will help you through the rest Of particular interest is the ability to define... errors if your schema has problems) , you will get a directory path correlating to the package you entered In my example, I ended up with a javaxml2 directory, and a castor directory within that Within that directory, I ended up with a Catalog .java and CatalogDescriptor .java source file, and an Item .java and ItemDescriptor .java source file For most situations, you'll only need to worry about working with... classes with Castor is a piece of cake You'll need to use the org.exolab.castor.builder.SourceGenerator class, as shown here: java org.exolab.castor.builder.SourceGenerator -i castor/catalog.xsd -package javaxml2.castor In this example, I'm running the command with my schema in a subdirectory of the current directory, called castor/ I specified the schema with the "-i" flag, and the package to generate... Obviously, you may have XML schemas of your own that you want to try out; as long as they conform to the XML Schema specification, they should work with any examples in this section 358 Java & XML, 2nd Edition At least as of this writing, Castor supported only the October 2000 XML Schema Candidate Recommendation, as opposed to the final version of that specification This could require you to make some small . align="center"> <font color="#FFFFFF"><b> <a href="/javaxml/techbooks/">Home</a> </b></font> </p> <p align="center">. align="center"> <b><font color="#FFFFFF"> <i>New Listings</i> </font></b> </p> <p align="center"> <font color="#FFFFFF"><b>. color="#FFFFFF"><b> <a href="/javaxml/techbooks/contact.html">Contact Us</a> </b></font> </p> </td> <td valign="top"

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

Từ khóa liên quan

Mục lục

  • 14. Content Syndication

    • 14.2 mytechbooks.com

    • 14.3 Push Versus Pull

    • 14.4 What's Next?

    • 15. Data Binding

      • 15.1 First Principles

      • 15.2 Castor

      • 15.3 Zeus

      • 15.4 JAXB

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan