Apache Jakarta and Beyond: A Java Programmeramp;#039;s Introduction [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Apache Jakarta and Beyond: A Java Programmeramp;#039;s Introduction [Electronic resources] - نسخه متنی

Larne Pekowsky

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید







18.12. The XML Tags


XML, the Extensible Markup Language, is many things to many people. XML provides a mechanism to store documents in a format that is easy for both programs and humans to understand. XML provides the basis for programs running on different computers and operating systems to talk to each other over the Web. XML is also a language, on top of which a huge number of industry-specific data formats have been created, that describes data ranging from corporate workflow to warehouse inventories to geographic encyclopedias.

To support all these functions, and many more, a plethora of toolkits have become available to simplify the task of creating, processing, and manipulating XML documents. In an important sense XML provides another way to model data, and as such there are great benefits to be had by pairing XML with a view technology such as JSPs. The JSP specification itself, along with a number of tags from the standard tag library, make this pairing possible on a number of levels.

There are a number of JSP tags for manipulating XML, but before examining them, note that because an XML document is just a bunch of text, creating one through a JSP is no harder than creating a196 document. Listing 18.24 shows a JSP that retrieves information from a database and generates an XML version of the CD collection.


Listing 18.24. Generating XML with a JSP


<%@ page contentType="text/xml" %>
<%@ taglib prefix="c "
uri="http://java.sun.com/jstl/core" %>
<jsp:useBean
id="artist"
/>
<jsp:setProperty
name="artist"
property="artistId "
value="0"/>
<collection>
<artist name="<c:out escapeXml="false"
value="${artist.name}"/>">
<c:forEach items="${artist.cds}" var="cd">
<album name="<c:out value="${cd.name}"/>">
<c:forEach items="${cd.tracks}" var="track">
<track name="<c:out value="${track.name}"/>"/>
</c:forEach>
</album>
</c:forEach>
</artist>
</collection>

In almost all respects this example is identical to Listing 18.19, the major difference being the use of XML tags instead o188. Because this page will not be returning a196 document, it is important that it notify the browser what kind of data to expect. This is accomplished by the use of the page directive at the top. Telling the browser that it will be getting an XML document allows the browser to present the data properly; for example, both Mozilla and Internet Explorer have special modes that allows users to interactively open and close portions of XML documents. Mozilla's view of such data is shown in Figure 18.3. In it a + in front of a node indicates that it may be expanded by clicking on it, and a - means the node can be collapsed.


Figure 18.3. The browser view of an XML document.

[View full size image]


18.12.1. Selecting Data from an XML Document


Chapter 9. The most straightforward of these is illustrated in Listing 18.25.


Listing 18.25. Using XPath expressions in a JSP


<%@ taglib prefix="x"
uri="http://java.sun.com/jstl/xml" %>
<%@ taglib prefix="c"
uri="http://java.sun.com/jstl/core" %>
<c:import
url="http://localhost:8080/jspbook/chapter19/collection.jsp"
var="xml"/>
<x:parse xml="${xml}" var="doc"/>
Albums by <x:out select="$doc//artist[1]/@name"/>:<br>
<ul>
<x:forEach select="$doc//artist[1]/album" var="album">
<li><x:out select="$album/@name"/>
</x:forEach>
</ul>

The first thing to notice in this example is that it loads a new portion of the standard tag library, which is imported with the prefix x. The first new tag used in this example, c:import, is not technically a part of the XML tags, but it is often used in conjunction with them. c:import imports the contents of one URL within another page. It can load data from

anywhere , not just the site where the page lives. This makes it possible for sites to include content from other sites, although in general this should only be done with the other site's knowledge and permission. This ability works especially well in conjunction with XML, as will soon be demonstrated.

The c:import stores the data it has read in a variable rather than automatically sending it to the user. This makes it possible to process this data before the user sees it, which is what will be done here. In this case, the data from the collection page from Listing 18.24 has been placed into a variable called xml. This data could then be shown directly to the user with a simple <c:out value= "${xml}"/>.

Rather than display this data, it is instead passed to another tag called x:parse, the first of the new XML tags. This tag takes a block of XML and processes it internally into a form that can be used more efficiently. The results of this conversion are stored in yet another variable, which has been called doc.

Next, data is extracted from this internal representation with the x:out tag. This tag works somewhat like c:out, but it obtains the value to display from a combination of the expression language and an XPath expression. The JSP XML tags allow the beginning of a select expression to start with a number of expression language identifiers, such as the variable doc that was created with the x:parse tag. Immediately following that can be any valid XPath expression, which will be used to pull data from the variable. Here the page gets the name of the first artist in the collection.

Following this is an x:forEach tag, which is to c:forEach what x:out is to c:out. x:forEach will repeat some action for every element returned by an XPath expression, which in this case is all albums from the first artist. As with c:forEach, each time through the loop the current value can be assigned to a variablein this case, one called album.

Within the body of the x:forEach tag is another x:out that displays the value of the name attribute for each album. Because album holds each of the XML album tags, the XPath portion of this second x:out tag does not need the full path starting from the top; it only needs to know how to get to the name attribute from each album tag.

Note that it would also have been possible to write this loop as


<x:forEach select="$doc//artist[1]/album/@name"
var="name">
<li><x:out select="$name"/>
</x:forEach>

This would have the effect of looping over all album names instead of over all albums. This works because all the page will be showing is the name, but if the page had to show both the name and the year the album was released, it would have had to loop over the albums and then used two x:out tags to display the two different attributes.

There are also x:if, x:choose, x:when, and x:otherwise tags. These do essentially the same things as their counterparts from the core library except that each can take an XPath expression instead of a value from the expression language.


18.12.2. Formatting XML


x:forEach. This second parttranslating XML into another formatis so common and so important that a whole new language was developed to make it easier. This language is called

XSLT.

XSLT uses many of the ideas that have already been discussed. To begin, consider what would be needed to find every artists' name from a CD collection in an XML document and output the string "Albums for" followed by the name, enclosed in an h1 tag. This would pose no challenge: Simply specify the set of nodes to loop over with an x:forEach tag, using //artist as the set of items. Then within the x:forEach tag, obtain the desired string using <x:out select="@name"/>.

XSLT takes these same concepts but replaces the idea of selecting a set of tags and then iterating over them with the notion of

patterns. Each clause of an XSLT file specifies a pattern to find in the XML file, such as all artists, or all albums with a given name, or any other possibility XPath provides. An output template is also provided, which may include elements selected from the XML that matched the input. For example, the XSLT that will format artist names as desired is


<xsl:template match="artist">
<h1>Albums by <xsl:value-of select="@name"/></h1>
</xsl:template>

This looks almost exactly like the corresponding JSP code, with xsl:template playing the role of the x:forEach and xsl:value-of replacing the x:out. It is important to note the conceptual difference, however. xsl:template is not an iteration operator; it does not perform an activity for every element of some set. Instead, it provides a rule, stating that whenever and wherever the XPath expression given as match is found, the body will be processed.

A similar clause could be added to put album names in level two headers:


<xsl:template match="album">
<h2><xsl:value-of select="@name"/></h2>
</xsl:template>

However, there is one more thing that must be done to make both of these clauses fit together. The rule given for artist specifies that a certain string should result and no other actions should be taken. To get XSLT to continue examining the rest of the document, it must be told to do so, which can be done by adding


<xsl:apply-templates select="album"/>

after the string. This indicates that XSLT should continue processing the album elements within the artist. Order is important; if xsl:apply-templates appeared before the string, the result would

first show the albums and then the artist.

Listing 18.26 rounds out the set of translations by putting track names in a bulleted list.


Listing 18.26. The full XSLT file


<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="artist">
<h1>Albums by <xsl:value-of select="@name"/></h1>
<xsl:apply-templates select="album"/>
</xsl:template>
<xsl:template match="album">
<h2><xsl:value-of select="@name"/></h2>
<ul>
<xsl:apply-templates select="track"/>
</ul>
</xsl:template>
<xsl:template match="track">
<li><xsl:value-of select="@name"/></li>
</xsl:template>
</xsl:stylesheet>

Notice that the rule for album also needs an xsl:apply-templates to process the tracks.

Once an XSLT file has been defined, using it from a JSP is quite easy. Such a page is shown in Listing 18.27.


Listing 18.27. Using XSLT from a JSP


<%@ taglib prefix="x"
uri="http://java.sun.com/jstl/xml" %>
<%@ taglib prefix="c"
uri="http://java.sun.com/jstl/core" %>
<c:import
url="http://localhost:8080/jspbook/chapter08/collection.jsp"
var="xml"/>
<c:import
url="http://localhost:8080/jspbook/chapter08/style.xsl"
var="xslt"/>
&l202><body>
<x:transform xslt="${xslt}" xml="${xml}"/>
</body></html >

In this example the XML and XSLT files are loaded using c:import tags. Then the transformation is performed and the result displayed with the new x:TRansform tag. Because the final outcome of the transformation i201, there is no need to set the content type, and a browser will be able to render it in the usual way, as shown in Figure 18.4.


Figure 18.4. The result of an XSLT translation.

[View full size image]

In asense, this process has split the view layer into two smaller components: the XML, which provides data from the model to the view, and the XSLT, which contains all the presentation information. Using pure JSPs, these two actions are typically intertwined, with some bean tags getting data from the model and various iteration and conditional tags munging that data into the desired presentation.

Both of these operations may legitimately be considered part of the view, and so having them in the same JSP is not a bad design. However, splitting them into separate components offers some new possibilities. It is often true that splitting pieces of a complex system into separate modules makes it easy to add new functionality.

In this case, one new piece of functionality is the ability to easily change the apparence of a page without changing any of the underlying implementation. Listing 18.28 shows an alternate XSLT file that uses tables to format a CD collection instead of itemized lists.


Listing 18.28. An alternate style


<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="album">
<table border="1">
<tr>
<td><xsl:value-of select="parent::artist/@name"/></td>
<td><xsl:value-of select="@name"/></td>
</tr>
<xsl:apply-templates select="track"/>
</table><p></p>
</xsl:template>
<xsl:template match="track">
<tr><td colspan="2"><xsl:value-of select="@name"/></td></tr>
</xsl:template>
</xsl:stylesheet>

This XSLT file does nothing for artist nodes. When it encounters an album, it creates a new table, the first row of which will have a column for the artist name and another for the album name. The artist name is obtained with a new kind of XSLT expression: parent::artist/@name. The parent:: portion indicates that the value should be obtained from the parent nodethat is, the node that contains the current one. Because album nodes are contained within artist nodes, this will get the artist, and from there getting the name is done as usual.

Now that a second style has been defined, Listing 18.27 can be easily modified to switch between them, based on user preference, as shown in Listing 18.29.


Listing 18.29. Allowing the user to choose a style


<%@ taglib prefix="x"
uri="http://java.sun.com/jstl/xml" %>
<%@ taglib prefix="c"
uri="http://java.sun.com/jstl/core" %>
<c:import
url="http://localhost:8080/jspbook/chapter08/collection.jsp"
var="xml"/>
<c:choose>
<c:when test="${param.style == 'list'}">
<c:import
url="http://localhost:8080/jspbook/chapter08/style.xsl"
var="xslt"/>
</c:when>
<c:otherwise>
<c:import
url="http://localhost:8080/jspbook/chapter08/tablestyle.xsl"
var="xslt"/>
</c:otherwise>
</c:choose>
&l202><body>
<x:transform xslt="${xslt}"xml="${xml}"/>
</body></html>

This example simply uses a c:choose tag to load one of two XSLT files into the xslt variable, which will then be used by the x:transform tag. The result of formatting with the table-based XSLT file is shown in Figure 18.5.


Figure 18.5. An alternate XSLT translation.

[View full size image]


/ 207