Previous | Next
Prototyping the XMLOnce the requirements and screen flow are well understood, it is possible to move on to a more rigorous design process. Web sites based on XSLT are highly modular, facilitating a design and implementation process that can be farmed out to several members of a development team. Each piece can be developed and tested independently before finally bringing everything together into the completed web application. XHTML PrototypesCreating user interface prototypes is an early task that can be handed off to less experienced developers or perhaps to a dedicated web page designer. At this stage in the game, an overly complex and graphical web interface is not required. The bells and whistles can be added later by merely updating XSLT stylesheets. In fact, too much effort at this early stage can make it more difficult to figure out what the XML and XSLT should look like. Since the front end will be created using XHTML Strict, a separate cascading style sheet (CSS) will be required to make the pages look presentable.[25] The strict variant of XHTML does not allow most of the HTML 4.0 formatting tags, but instead encourages the use of CSS. Example 7-1 contains the complete CSS file used by the discussion forum.
Example 7-1. forum.cssbody { font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; } .box1 { border: 3px solid Navy; text-align: center; padding: 4px; margin : 2px; background-color: #c0c0c0; } .box2 { border: 1px solid Navy; padding: 4px; margin: 2px; background-color: #FFFFCC; } h1 { font-size: 22pt; font-weight: normal; margin: 0px 0px 0px 0px; } h2 { font-size: 18pt; font-weight: normal; margin: 0px 0px 0px 0px; } h3 { font-size: 14pt; font-weight: normal; margin: 0px 0px 0px 0px; } ul { margin-top: 0px; } .msgSummaryLine { font-size: smaller; font-weight: normal; } a:hover { background-color:yellow; } .error { font-weight: bold; color: red; } Each of the XHTML web pages refers to this CSS file using the following syntax: <link rel="stylesheet" href="/forum/forum.css" /> This is a great technique because it keeps the size of the XSLT stylesheets and each XHTML page much smaller. Changes to fonts and colors can be made in the single CSS file and are immediately reflected throughout the web application. The primary obstacle at this time is noncompliant web browsers. Although support for CSS is gradually improving, web pages must be tested on a variety of browsers to identify formatting problems. NOTE: A common theme presented throughout this tutorial is the separation of data and presentation that XSLT supports. CSS expands upon this theme by separating XHTML content from many aspects of its visual presentation. CSS and XSLT are very different technologies that complement one another nicely. Most of the code in a CSS file is fairly self-explanatory. For example, the box2 { border: 1px solid Navy; padding: 4px; margin: 2px; background-color: #FFFFCC; } The dot in <div >Messages for March, 2001</div> The advantage of a style class is that it can be applied to any element in the XHTML. In this case, a thin border and yellow background are applied to any element that has the The web page designers should create basic representations of every page in the application at this point. The home page is shown in Figure 7-2. Figure 7-2. Home page prototypeThe complete XHTML source code for the home page is shown in Example 7-2. As shown, the actual hyperlinks are not valid because the design for the servlets has not been completed, and the final URLs are probably unknown at this point. At any rate, this is only prototype code, because the actual XHTML web pages are dynamic and will be produced as the result of an XSLT transformation from XML data. Example 7-2. Home page XHTML source<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Discussion Forum Home</title> <link href="../docroot/forum.css" rel="stylesheet" /> </head> <body> <div > <h1>Discussion Forum Home</h1> </div> <div > <h2>Java Developing</h2> <div>General developing questions about Java.</div> <div > <p> <a href="link_to_post_message">Post Message</a> to Java Developing</p> <a href="link_to_feb_messages">Feb, 2001</a> | <a href="link_to_mar_messages">Mar, 2001</a> | <a href="link_to_apr_messages">Apr, 2001</a> </div> </div> <div > <h2>XSLT Basics</h2> <div>Writing effective XSLT stylesheets.</div> <div > <p> <a href="link_to_post_message">Post Message</a> to XSLT Basics</p> <a href="link_to_feb_messages">Feb, 2001</a> | <a href="link_to_mar_messages">Mar, 2001</a> | <a href="link_to_apr_messages">Apr, 2001</a> </div> </div> <div > <h2>Sample empty board</h2> <div>This board has no messages.</div> <div > <p> <a href="link_to_post_msg">Post Message</a> to Sample empty board</p> </div> </div> </body> </html>
The next prototype, shown in Figure 7-3, shows what a message board looks like. XHTML source code for the remaining screens is not listed here. Figure 7-3. View Month prototypeMessages that are replies to other messages are indented a few spaces. Later, a simple change to the XSLT stylesheet can be employed to show graphical folders or other icons in front of each message. The next screen, shown in Figure 7-4, shows how users can post new messages to the discussion forum. Figure 7-4. Post Message prototypeThis page is also used to reply to an existing message. Although not shown here, the title changes to "Reply to Message," and the subject and message text are pre-filled with text from the original message. If the user submits this form without filling in all values, the web page is redisplayed with an error message. The final screen prototype is shown in Figure 7-5. This screen allows users to view existing messages. Figure 7-5. View Message prototypeXML SamplesWhile page designers are hard at work on the XHTML prototype screens, someone else can be working on sample XML data for each web page. Although different people may work on these tasks, a certain degree of coordination is critical at this point. The prototype XHTML pages may look great, but the XML must provide the data to enable those pages to be created. The XML designer will also have to work with the people who are designing the back-end data sources to determine if the desired data is even available. When designing XML, the focus should be on data rather than presentation. All of the fonts and colors that are part of the CSS should have absolutely zero impact on the design of the XML. The XML will contain additional data that is not displayed, however. For example, creating hyperlinks requires some sort of identifier for each object. This allows the servlet to figure out which message the user clicked on. The XML data contains the identifier for the message, but the actual XHTML markup for the hyperlink comes from an XSLT stylesheet. The XML data for the home page is shown in Example 7-3. Because the XML does not contain presentation information, it is smaller than the XHTML markup. Example 7-3. home.xml<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="../xslt/home.xslt"?> <home> <board id="0"> <name>Java Developing</name> <description>General developing questions about Java.</description> <messages month="1" year="2001"/> <messages month="2" year="2001"/> <messages month="3" year="2001"/> </board> <board id="1"> <name>XSLT Basics</name> <description>Writing effective XSLT stylesheets</description> <messages month="1" year="2001"/> <messages month="2" year="2001"/> <messages month="3" year="2001"/> </board> <board id="3"> <name>Sample empty board</name> <description>This board has no messages.</description> </board> </home> Do not forget that this is still just a prototype XML file. The actual XML data will be dynamically generated by JDOM once the application is finished; this XML prototype code is used only for testing and development purposes. In this XML data, each message board is represented by a The second line of the XML links to the XSLT stylesheet: <?xml-stylesheet type="text/xsl" href="../xslt/home.xslt"?> This is not used in the final application but is very useful during the prototyping and development process. By linking to the stylesheet, the transformation can be quickly viewed in an XSLT-compatible web browser by simply loading the XML page. The next XML file, shown in Example 7-4, contains data for the "View Month" page. Example 7-4. viewMonth.xml<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="../xslt/viewmonth.xslt"?> <viewMonth month="1" year="2001"> <board id="1"> <name>Java Developing</name> <description>General developing questions about Java.</description> </board> <message id="1" day="1"> <subject>First test message</subject> <authorEmail>burke_e@yahoo.com</authorEmail> <message id="2" day="2"> <subject>Re: First test message</subject> <authorEmail>aidan@nowhere.com</authorEmail> </message> </message> <message id="3" day="4"> <subject>Another test message</subject> <authorEmail>burke_e@yahoo.com</authorEmail> </message> </viewMonth> Moving on to Example 7-5, we have the XML for the "Post/Reply Message" page. Example 7-5. postMsg.xml<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="../xslt/postmsg.xslt"?> <postMsg> <board id="1"> <name>Java Developing</name> <description>The board description...</description> </board> <inResponseTo id="4"> <subject>Test Subject</subject> </inResponseTo> This XML is used for both posting new messages and replying to existing messages because the web pages are virtually identical, and the data is the same in both cases. The And finally, the XML for the "View Message" page is shown in Example 7-6. Example 7-6. viewMsg.xml<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="../xslt/viewmsg.xslt"?> <message id="5" month="1" day="4" year="2001"> <board id="1"> <name>Java Developing</name> </board> <inResponseTo id="4"> <subject>Test Subject</subject> </inResponseTo> <subject>Re: Test Subject</subject> <authorEmail>burke_e@yahoo.com</authorEmail> <text>This is a test of the message text.</text> </message> A quick study of this data reveals that postMsg.xml and viewMsg.xml have many similarities. A few modifications to either XML file will enable us to reuse the same JDOM code later when producing these pages. The alternative is to keep these pages separate, which results in at least one additional Java class later on. The advantage of keeping these files separate is so that the XML generation code does not have to be cluttered up with a lot of XSLT StylesheetsYet another member of the development team can be assigned to the task of creating XSLT stylesheets, although he or she will have to wait until the XML and XHTML prototypes are complete. More often than not, the person designing the XML will be the one creating the initial XSLT stylesheets. At this point in the process, a tool such as XML Spy can be invaluable.[26] The ability to edit the XSLT stylesheet and click on the Refresh button in an IDE makes development a snap. Alternately, an XSLT-compatible web browser can quickly display changes as stylesheets are edited. As explained in "Introduction ", Microsoft's Internet Explorer 5.x supports XSLT, provided that the updated msxml parser is installed using the xmlinst utility.[27]
Example 7-7 shows the XSLT for the discussion forum home page. Example 7-7. XSLT for the home page<?xml version="1.0" encoding="UTF-8"?> <!-- *********************************************************** ** home.xslt ** ** Transforms the home page into XHTML *********************************************************** --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> This stylesheet opens with the usual <xsl:param name="rootDir" select="'../docroot/'"/> The Next, the <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Discussion Forum Home</title> The XSLT processor does not actually deal with the CSS file. From the perspective of XSLT, the The remainder of the stylesheet is pretty basic -- just matching patterns in the XML and producing XHTML content to the result tree. One important thing to point out here is the way that hyperlinks are created: <a href="/forum/main/postmsg?mode=postnewmsg&boardid={@id}">Post Message</a> Since the ampersand character (
Another key piece of this stylesheet shows how to call a utility template:
The utils.printShortMonthName template is part of utils.xslt and is invoked just like a local template. The only difference is that the current stylesheet must import utils.xslt or the code will fail. Prefixing the template name with utils. has nothing to do with the actual filename; it is a convention adopted only for this application that makes the code a little easier to read, reducing the chances for naming conflicts. The reusable XSLT stylesheet, utils.xslt, is shown next in Example 7-8. Example 7-8. Reusable XSLT code<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template name="utils.printShortMonthName"> <xsl:param name="monthNumber"/> <xsl:choose> <xsl:when test="$monthNumber="0"">Jan</xsl:when> <xsl:when test="$monthNumber="1"">Feb</xsl:when> <xsl:when test="$monthNumber="2"">Mar</xsl:when> <xsl:when test="$monthNumber="3"">Apr</xsl:when> <xsl:when test="$monthNumber="4"">May</xsl:when> <xsl:when test="$monthNumber="5"">Jun</xsl:when> <xsl:when test="$monthNumber="6"">Jul</xsl:when> <xsl:when test="$monthNumber="7"">Aug</xsl:when> <xsl:when test="$monthNumber="8"">Sep</xsl:when> <xsl:when test="$monthNumber="9"">Oct</xsl:when> <xsl:when test="$monthNumber="10"">Nov</xsl:when> <xsl:when test="$monthNumber="11"">Dec</xsl:when> </xsl:choose> </xsl:template> <xsl:template name="utils.printLongMonthName"> <xsl:param name="monthNumber"/> <xsl:choose> <xsl:when test="$monthNumber="0"">January</xsl:when> <xsl:when test="$monthNumber="1"">February</xsl:when> <xsl:when test="$monthNumber="2"">March</xsl:when> <xsl:when test="$monthNumber="3"">April</xsl:when> <xsl:when test="$monthNumber="4"">May</xsl:when> <xsl:when test="$monthNumber="5"">June</xsl:when> <xsl:when test="$monthNumber="6"">July</xsl:when> <xsl:when test="$monthNumber="7"">August</xsl:when> <xsl:when test="$monthNumber="8"">September</xsl:when> <xsl:when test="$monthNumber="9"">October</xsl:when> <xsl:when test="$monthNumber="10"">November</xsl:when> <xsl:when test="$monthNumber="11"">December</xsl:when> </xsl:choose> </xsl:template> </xsl:stylesheet> Month numbers are indexed from position 0 to be consistent with the viewMonth.xslt is shown in Example 7-9. It generates an XHTML page that shows all messages in a month for a particular board. Example 7-9. XSLT for the View Month page<?xml version="1.0" encoding="UTF-8"?> <!-- *********************************************************** ** viewMonth.xslt ** ** Shows a month-view of messages in a given board. *********************************************************** --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:import href="utils.xslt"/> <xsl:param name="rootDir" select="'../docroot/'"/> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/> Because viewMonth.xslt shows a summary view of a large number of messages, the actual text content for each message is not included in the output. Instead, the message subject, author, and create date are displayed. These lines are grouped and indented according to replies, making threads of discussion immediately visible. This stylesheet declares a series of global variables. These can be referenced throughout the stylesheet and are designed to make the code more maintainable. Since each variable is prefixed with <xsl:value-of select="$global.boardName"/> NOTE: The
The interesting part of this stylesheet involves construction of the tree of messages. Since messages in the XML are hierarchical, the XSLT must recursively process the data to properly show threads of discussion. Here is another look at a portion of the viewMonth.xml file presented earlier in this chapter: <viewMonth month="1" year="2001"> <board id="1"> <name>Java Developing</name> <description>General developing questions about Java.</description> </board> In the XSLT stylesheet, the first part of the recursive process selects all <xsl:apply-templates select="viewMonth/message"/> This selects messages with ids and , causing the following template to be instantiated: <xsl:template match="message"> <xsl:param name="indent" select="0"/> This template takes a parameter for the level of indentation. If the parameter is not specified, as in this first usage, it defaults to . This code is followed by very basic XSLT code to produce a one-line summary of the current message, and then the template recursively instantiates itself: <xsl:apply-templates select="message"> <xsl:with-param name="indent" select="$indent + 1"/> </xsl:apply-templates> This efficiently selects all Another stylesheet, viewMsg.xslt, is responsible for displaying a single message. This is a simple XSLT stylesheet and can be found in Appendix A, "Discussion Forum Code". The only remaining stylesheet, postMsg.xslt, is shown in Example 7-10. This stylesheet supports two modes of operation. Therefore, it is more complicated than the previous examples. Example 7-10. XSLT for the Post/Reply message page<?xml version="1.0" encoding="UTF-8"?> <!-- *********************************************************** ** postMsg.xslt ** ** Creates the "Post New Message" XHTML page and the ** "Reply to Message" XHTML page. *********************************************************** --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:import href="utils.xslt"/> <!-- pass the root directory as a parameter, thus allowing this stylesheet to refer to the CSS file --> <xsl:param name="rootDir" select="'../docroot/'"/> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"/> <!-- ===== Global Variables ===== --> <xsl:variable name="global.subject" select="/postMsg/prefill/subject"/> <xsl:variable name="global.email" select="/postMsg/prefill/authorEmail"/> <xsl:variable name="global.message" select="/postMsg/prefill/message"/> Since this stylesheet must work for posting new messages as well as for replying to messages, it must determine the appropriate mode of operation. This can be accomplished by checking for the existence of elements that occur only in one mode or the other. For example, the <xsl:variable name="global.title"> <xsl:choose> <xsl:when test="/postMsg/inResponseTo"> <xsl:text>Reply to Message</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>Post New Message</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:variable>
This stylesheet optionally displays an error message when the user partially fills out the XHTML form and submits the data. The servlet redisplays the page with an error message, allowing the user to fix the problem. It does this by inserting the following XML element into the data: <error code="ALL_FIELDS_REQUIRED"/> The XSLT stylesheet tests for the existence of this element as follows: <xsl:if test="postMsg/error/@code="all_fields_required""> <p>All fields are required...</p> </xsl:if> An additional trick used in this stylesheet involves its interaction with a servlet. When the user submits the XHTML form data, the servlet must determine which mode of operation the user was in. For this task, the servlet looks for a request parameter called <xsl:choose> <xsl:when test="/postMsg/inResponseTo"> <input type="hidden" name="origMsgID" value="{postMsg/inResponseTo/@id}"/> <input type="hidden" name="mode" value="replyToMsg"/> </xsl:when> <xsl:otherwise> <input type="hidden" name="mode" value="postNewMsg"/> </xsl:otherwise> </xsl:choose> The stylesheet also inserts a hidden form field that contains the original message ID whenever the mode is public void doGet(HttpServletRequest request, HttpServletResponse response) ... { String mode = request.getParameter("mode"); if ("replyToMsg".equals(mode)) { String origMsgID = request.getParameter("origMsgID"); .... |