|
Since this is a
list of orders, we need some way to iterate through the list. We also need a way
to print portions of the list as we iterate through it. The <composer:forEach>
and <composer:value>
tags do just this. Let's take a look at another JSP snippet:
1:
<table border="1">
2:
<tr>
3:
<td><b>Customer</b></td>
4:
<td><b>Order Date</b></td>
5:
<td><b>Items</b></td>
6:
</tr>
7:
<composer:forEach name="orderlist" xpath="/ORDERLIST/ORDER">
8:
<tr>
9:
<td>
10:
<composer:value xpath="./CUSTOMER/NAME" /><br>
11:
<composer:value xpath="./CUSTOMER/ADDRESS" /><br>
12:
<composer:value xpath="./CUSTOMER/CITY" />,
13:
<composer:value xpath="./CUSTOMER/STATE" />
14:
<composer:value xpath="./CUSTOMER/ZIP"
/>
15:
</td>
16:
<td>
17:
<composer:value xpath="./DATE" />
18:
</td>
19:
<ul>
20:
<composer:forEach xpath="./ITEMLIST/ITEM">
21:
<li><composer:value xpath="./TITLE" /></li>
22:
</composer:forEach>
23:
</ul>
24:
</tr>
25:
</composer:forEach>
26:
</table>
In the first
six lines we start the HTML table and create a row with our column headers. On
line 7 we call the <composer:forEach>
tag with two attributes. The name attribute should be the same as the
name that we specified in a previous <composer:execute>
tag. Again, this tells the tag library what service this tag should process
against. The xPath attribute defines the XPath expression that should be
applied to the XML. In <composer:forEach>
tags, this expression should evaluate to a Nodelist ; in our case, it's a list
of <ORDER>
nodes. If the expression does not evaluate to a Nodelist
(or to an empty list of nodes), the <composer:forEach>
body will not be executed.
Since <composer:forEach>
is an iteration tag, the body will execute the same number of times as there are
nodes in the Nodelist generated by the XPath expression. In our example, there
are 2 nodes, so the body will be executed twice. The body content can consist of
JSP, HTML or other custom tags. In the above example, the body first creates a
new HTML table row. It then creates three columns, the first two of which
contain <composer:value>
tags.
The <composer:value>
tag provides a way to print out the result of an XPath expression as a string.
Furthermore, it is aware of the context in which it is being called. If a
relative XPath expression is used, it is evaluated within the context of the
nearest Composer ancestor tag. If none exists, it defaults to the root of
the XML output document. In our example above, because the first <composer:value>
tag is nested within a <composer:forEach>
tag, its relative XPath expression ./CUSTOMER/NAME
will be evaluated in the context of the current /ORDERLIST/ORDER
being iterated on. The same holds true for the other <composer:value>
tags within <composer:forEach>.
It is also
important to note that we've omitted the name attribute from the <composer:value>
tags. As is the case with all the Composer tags, if the name attribute is
missing, the name of the nearest ancestor is used (in our case, the <composer:forEach>
tag). If no ancestor is available, the default name service1 is used. If
there is no corresponding <composer:execute>
tag with name service1, the page will generate an error. Thus, it is a
good practice to qualify tags with the name attribute where it might lead to
confusion.
Going back to
the example, in the third column we use another <composer:forEach>
tag to iterate through the items in order. Note that its XPath expression is
also relative to the expression of the ancestor <composer:forEach>
node. This code generates an unordered HTML list of the items in the order.
|