:sectnums!:
== Preface

This is the Jakarta Standard Tag
Library {revnumber} specification, developed by the Jakarta Standard Tag Library Team, https://projects.eclipse.org/projects/ee4j.jstl

Oracle, Java, and MySQL are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

== Related Documentation

Implementors of Jakarta Standard Tag Lbrary and authors of Jakarta Server Pages
may find the following documents worth consulting for additional
information:.

[width="100%",cols="50%,50%",]
|===
|Jakarta Server Pages
|https://projects.eclipse.org/projects/ee4j.jsp[Jakarta Server Pages Project] +
https://jakarta.ee/specifications/pages/[Jakarta Server Pages Specification]

|Jakarta Servlet
|https://projects.eclipse.org/projects/ee4j.servlet[Jakarta Servlet Project] +
https://jakarta.ee/specifications/servlet/[Jakarta Servlet Specification]

|Java™, Standard Edition, Version 8.0 API Specification
|https://docs.oracle.com/javase/8/docs/api

|Jakarta EE
|https://jakarta.ee

|JavaBeans
|https://docs.oracle.com/javase/8/docs/technotes/guides/beans

|JDBC
|https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc

|Java Technology and XML
|https://docs.oracle.com/javase/8/docs/technotes/guides/xml

|XPath specification
|http://www.w3.org/TR/xpath

|XML home page at W3C
|http://www.w3.org/XML

|HTML home page at W3C
|http://www.w3.org/MarkUp

|XML.org home page
|http://www.xml.org
|===

== Typographical Conventions



[width="100%",cols="50%,50%",options="header",]
|===
|Font Style |Uses
|Italic |Emphasis,
definition of term.

| _Monospace_ |Syntax,
code examples, attribute names, Java language types, API, enumerated
attribute values.
|===

== Acknowledgments

The Jakarta Standard Tag Library
specification is the result of collaborative work involving many
individuals, all driven by a common goal of designing the best libraries
possible for the Jakarta Server Pages author community.

The current members of the Jakarta Standard Tag Library project in the
Eclipse Foundation can be found at the following location:
https://projects.eclipse.org/projects/ee4j.jstl/who[].

We would like to thank all members of the JSR-52
expert group under the Java Community Process: Nathan Abramson, Shawn Bayern, Hans Bergsten, Paul
Bonfanti, Vince Bonfanti, David Brown, Larry Cable, Tim Dawson, Morgan
Delagrange, Bob Foster, David Geary, Scott Hasse, Hal Hildebrand, Jason
Hunter, Serge Knystautas, Mark Kolb, Wellington Lacerda, Jan Luehe, Geir
Magnusson Jr., Dan Malks, Craig McClanahan, Richard Morgan, Glenn
Nielsen, Rickard Oberg, Joseph B. Ottinger, Eduardo Pelegri-Llopart, Sam
Pullara, Tom Reilly, Brian Robinson, Russ Ryan, Pasi Salminen, Steven
Sargent, Allan Scott, Virgil Sealy, Magnus Stenman, Gael Stevens, James
Strachan, Christine Tomlinson, Norbert von Truchsess, Keyton Weissinger,
Clement Wong, Alex Yiu.

This specification was first initiated by
Eduardo Pelegri-Llopart. Eduardo's leadership in making the Java
platform the best technology available for the web layer has been key in
shaping the vision behind the standard tag library.

Shawn Bayern and Hans Bergsten deserve special
credit for being actively involved in all design issues of this
specification. Their vast expertise and commitment to excellence has had
a profound impact in every single aspect of this specification. Mille
mercis Shawn et Hans! Don't know how we would have done it without you
two.

Many thanks to Jan Luehe for taking ownership of
the internationalization and formatting chapters of this specification
on short notice, and doing an incredible job.

Special mention to Nathan Abramson for being a
driving force behind the expression language introduced in JSTL, to
James Strachan for leading the group in our understanding of XML for
page authors, and to Craig McClanahan for his help on servlet and J2EE
platform related issues.

This specification has drawn a lot of its design
ideas from pioneers in the field of tag libraries. We are grateful to
the Jakarta project at Apache, as well as other efforts in the industry,
where projects led by Craig McClanahan (Struts), James Strachan (XTags),
Morgan Delagrange (DBTags), Tim Dawson (I18N), Glenn Nielsen (many
utility taglibs), Scott Hasse (JPath), Dmitri Plotnikov (JXPath), Pasi
Salminen (O&D Struts), have greatly influenced the design of the JSTL
libraries.

The RI team composed of Shawn Bayern (lead),
Nathan Abramson, Justyna Horwat, and Jan Luehe has done a wonderful job
at turning code faster than the specification could be written.

Quality has been in the capable hands of Ryan
Lubke, lead of the TCK team under the Java Community Process that also includes Lance Andersen. David
Geary's help in doing thorough reviews of the specification was also
greatly appreciated.

We are also grateful to the product team at Sun
Microsystems who helped us sail efficiently through this specification:
Jim Driscoll, Karen Schaffer, George Grigoryev, Stephanie Bodoff,
Vanitha Venkatraman, Prasad Subramanian, and Xiaotan He.

Finally, we'd like to thank the community at
large for their ever increasing interest in this technology. We sure
hope you'll enjoy the Jakarta Standard Tag Library.

== Comments

We are interested in improving this
specification and welcome your comments and suggestions. You can email
your comments to us at:

 jstl-dev@eclipse.org

:sectnums:
== Introduction

The Jakarta Standard Tag Library provides a specification document, API and
TCK that extends the Jakarta Server Pages specification by adding a tag
library of Jakarta Server Pages tags for common tasks, such as XML data
processing, conditional execution, database access, loops and
internationalization.


=== Goals

The ultimate goal of the Jakarta Standard Tag Library is to help simplify Jakarta Server Pages authors' lives.

A page author is someone who is responsible
for the design of a web application's presentation layer using Jakarta Server Pages. Many page authors are not fluent in any programming language.

One of the main difficulties a page author is
faced with is the need to use a scripting language (the default being
the Java programming language) to manipulate the dynamic data within a
Jakarta Server Pages page. Unfortunately, page authors often see scripting languages as
complex and not very well adapted to their needs.

The Jakarta Standard Tag Library offers the following capabilities:

* General-purpose actions +
These actions complement the expression
language by allowing a page author to easily display expressions in the
expression language, set and remove the value of Jakarta Server Pages scoped attributes,
as well as catch exceptions.

* Control flow actions +
Tag-based control flow structures
(conditionals, iterators), which are more natural to page authors.

* Tag library validators (TLVs) +
TLVs allow projects to only allow specific
tag libraries, as well as enforce Jakarta Server Pages coding styles that are free of
scripting elements.

The other key aspect of the Jakarta Standard Tag Library is that it
provides standard actions and standard Expression Language functions
for functionality most often needed by page authors. These cover the
following topics:

* Accessing URL-based resources

* Internationalization (i18n) and text
formatting

* Relational database access (SQL)

* XML processing

* String manipulation

=== Multiple Tag Libraries

A tag library is a collection of actions that
encapsulates functionality to be used from within a Jakarta Server Pages page. The Jakarta Standard Tag Library
includes a wide variety of actions that naturally fit into discrete
functional areas. This is why the Jakarta Standard Tag Library, although referred to as the standard
tag library (singular), is exposed via multiple tag libraries to clearly
identify the functional areas it covers, as well as to give each area
its own namespace. The tables below lists these functional areas along
with the URIs used to reference the libraries. The tables also show the
prefixes used in this specification (although page authors are free to
use any prefix they want).

Jakarta Standard Tag Library Tag Libraries

[width="100%",cols="34%,33%,33%",options="header",]
|===
|Functional Area
|URI |Prefix
|core |
_jakarta.tags.core_ | _c_

|XML processing |
_jakarta.tags.xml_ | _x_

|I18N capable formatting
| _jakarta.tags.fmt_
| _fmt_

|relational db access (SQL)
| _jakarta.tags.sql_
| _sql_

|Functions |
_jakarta.tags.functions_ |fn
|===

=== Container Requirement

Jakarta Standard Tag Library requires a Jakarta Server Pages 3.0 web container.
Please note that the expression language is an individual specification: Jakarta Expression Language 4.0.

== Conventions

This chapter describes the conventions used in
this specification.

=== How Actions are Documented

The Jakarta Standard Tag Library actions are grouped according to their
functionality. These functional groups of actions are documented in
their own chapter using the following structure:

* Motivation +
Describes the motivation for standardizing
the actions.

* Overview +
Provides an overview of the capabilities
provided by the actions. Sample code featuring these actions in their
most common use cases is also provided.

* One section per action, with the following
structure:

** Name +
Tag library prefixes are used in this
specification for all references to Jakarta Standard Tag Library actions (e.g.: <c:if> instead
of <if>).

** Short Description

** Syntax +
The syntax notation is described in
<<Syntax Notation>>.

** Body Content +
This section specifies which type of body
content is supported by the action. As defined by the Jakarta Server Pages specification,
the body content type can be one of _empty_, _JSP_, or _tagdependent_.
The section also specifies if the body content is processed by the
action or is simply ignored by the action and just written to the
current _JspWriter_. If the body content is processed, information is
given on whether or not the body content is trimmed before the action
begins processing it.

** Attributes +
Details in <<Attributes>> below.

** Constraints +
List of additional constraints enforced by
the action.

** Null & Error Handling +
Details on how null and empty values are
processed, as well as on exceptions thrown by the action.

** Description +
This section provides more details on the
action.

** Other sections +
Other sections related to the group of
actions described in the chapter may exist. These include sections on
interfaces and classes exposed by these actions.

==== Attributes

For each attribute, the following information
is given: name, dynamic behavior, type, and description.

The _rtexprvalue_ element defined in a TLD is
covered in this specification with the column titled "Dynamic" that
captures the dynamic behavior of an attribute. The value can be either
true or false. A false value in the dynamic column means that only a
static string value can be specified for the attribute. A true value
means that a _request-time attribute value_ can be specified. As defined
in the Jakarta Server Pages specification, a "request-time attribute value" can be either
a Java expression, an Expression Language expression, or a value set by a
`<jsp:attribute>`.

==== Syntax Notation

[width="100%",cols="50%,50%",]
|===
| _[...]_ |What is
inside the square brackets is optional

| _{option1\|option2\|option3\|...}_
|Only one of the given options can be
selected

| _[underline]#value#_ |The
default value
|===

For example, in the syntax below:

[literal, subs="+quotes, +attributes"]
<c:set var="varName" {blank}[scope="{[underline]#page#|request|session|application}"] value="value"/>

the attribute _scope_ is optional. If it is
specified, its value must be one of _page_, _request_, _session_, or
_application_. The default value is _page_.

=== Scoped Variables

Actions usually collaborate with their
environment in implicit or explicit ways, or both.

Implicit collaboration is often done via a
well defined interface that allows nested tags to work seamlessly with
the ancestor tag exposing that interface. The Jakarta Standard Tag Library iterator tags support
this mode of collaboration.

Explicit collaboration happens when a tag
explicitly exposes information to its environment. Traditionally, this
has been done by exposing a scripting variable with a value assigned
from a Jakarta Server Pages scoped attribute (which was saved by the tag handler).
Because of the expression language, the need for scripting variables is
significantly reduced. This is why all the Jakarta Standard Tag Library tags expose information
only as Jakarta Server Pages scoped attributes (no scripting variable exposed). These
exported Jakarta Server Pages scoped attributes are referred to as scoped variables in
this specification; this helps in preventing too much overloading of the
term "attribute".

==== var and scope

The convention is to use the name _var_ for
attributes that export information. For example, the `<c:forEach>` action
exposes the current item of the customer collection it is iterating over
in the following way:

....
<c:forEach var="customer" items="${customers}">
    Current customer is <c:out value="${customer}"/>
</c:forEach>
....

It is important to note that a name different
than _id_ was selected to stress the fact that only a scoped variable
(Jakarta Server Pages scoped attribute) is exposed, without any scripting variable.

If the scoped variable has at-end visibility
(see <<Visibility>>), the convention also
establishes the attribute _scope_ to set the scope of the scoped
variable.

The _scope_ attribute has the semantics
defined in the Jakarta Server Pages specification, and takes the same values as the ones
allowed in the `<jsp:useBean>` action; i.e. _page_, _request_, _session_, _application_. If no value is specified for _scope_, _page_ scope is
the default unless otherwise specified.

It is also important to note, as per the Jakarta Server Pages
specification, that specifying "session" scope is only allowed if the
page has sessions enabled.

If an action exposes more than one scoped
variable, the main one uses attribute names _var_ and _scope_, while
secondary ones have a suffix added for unique identification. For
example, in the `<c:forEach>` action, the _var_ attribute exposes the
current item of the iteration (main variable exposed by the action),
while the _varStatus_ attribute exposes the current status of the
iteration (secondary variable).

==== Visibility

Scoped variables exported by Jakarta Standard Tag Library actions are
categorized as either nested or at-end.

_Nested_ scoped variables are only
visible within the body of the action and are stored in "page"
scopefootnote:[Since nested scoped variables are always saved in page scope, no scope attribute is associated with them.]. The action must create the variable
according to the semantics of _PageContext.setAttribute(varName,PAGE_SCOPE)_, and it must remove it at the end of the action according
to the semantics of _PageContext.removeAttribute(varName, PAGE_SCOPE)_
.footnote:[It is important to note that the Jakarta Server Pages specification section 1.8.2 says that "A name should refer to a unique object at all points in the execution; that is, all the different scopes really should behave as a single name space." The Jakarta Server Pages specification also says that "A JSP container implementation may or may not enforce this rule explicitly for performance reasons.". Because of this, if a scoped variable with the same name as a nested variable already exists in a scope other than 'page', exactly what happens to that scoped variable depends on how the Jakarta Server Pages container has been implemented. To comply with the Jakarta Server Pages specification, and to avoid non-portable behavior, page authors should therefore avoid using the same name in different scopes.]

At-end scoped variables are only visible at
the end of the action. Their lifecycle is the one associated with their
associated scope.

In this specification, scoped variables
exposed by actions are considered at-end by default. If a scoped
variable is nested, it will be explicitly stated.

=== Static vs Dynamic Attribute Values

Except for the two exceptions described
below, attribute values of Jakarta Standard Tag Library actions can always be specified
dynamically (see <<Attributes>>).

The first exception to this convention is for
the _select_ attribute of XML actions. This attribute is reserved in
the Jakarta Standard Tag Library to specify a _String_ literal that represents an expression in the
XPath language.

The second exception is for attributes that
define the name and scope of scoped variables (as introduced in
<<Attributes>>) exported by Jakarta Standard Tag Library actions.

Restricting these attributes to static values
should benefit development tools, without any impediment to page
authors.

=== White Spaces

Following the Jakarta Server Pages specification (as well as
the XML and XSLT specifications), whitespace characters are _#x20_, _#x9_, _#xD_, or _#xA_.

=== Body Content

If an action accepts a body content, an empty
body is always valid, unless explicitly stated otherwise.

If the body content is used to set the value
of an attribute, then an empty body content sets the attribute value to
an empty string.

If a body content is trimmed prior to being
processed by the action, it is trimmed as defined in method _trim()_ of
the class _java.lang.String_.

=== Naming

The Jakarta Standard Tag Library adopts capitalization conventions of
Java variables for compound words in action and attribute names.
Recommended tag prefixes are kept lowercase. Thus, we have
`<sql:transaction>` and `<c:forEach>`, as well as attributes such as
_docSystemId_ and _varDom_.

In some cases, attribute names for Jakarta Standard Tag Library
actions carry conventional meanings. For instance,
<<var and scope>> discussed the _var_ and
_scope_ attibutes. <<The _select_ Attribute>> discusses the _select_ attribute used in Jakarta Standard Tag Library's
XML-processing tag library.

=== Errors and Exceptions

All syntax errors (as defined in the syntax
section of each action, as well as the syntax of Expression Language expressions) must be reported at translation
time.

Constraints, as defined in the constraints
section of each action, must also be reported at translation time unless
they operate on a dynamic attribute value, in which case errors are
reported at runtime.

The conversion from a _String_ value to the
expected type of an attribute is handled according to the rules defined
in the Jakarta Server Pages specification.

Since it is hard for a page author to deal
with exceptions, the Jakarta Standard Tag Library tries to avoid as many exception cases as
possible, without causing other problems.

For instance, if `<c:forEach>` were to throw an
exception when given a null value for the attribute _items_, it would
be impossible to easily loop over a possibly missing string array that
represents check-box selection in an HTML form (retrieved with an Expression Language
expression like _${paramValues.selections}_). A better choice is to do
nothing in this case.

The conventions used in the Jakarta Standard Tag Library with respect to
errors and exceptions are as follows:

* scope

** Invalid value – translation time validation error

* var

** Empty – translation time validation error

* Dynamic attributes with a fixed set of valid
String values:

** null – use the default value +
A null value can therefore be used to
dynamically (e.g. by request parameter), turn on or off special features
without too much work.

** Invalid value – throw an exception +
If a value is provided but is not valid, it's
likely a typo or another mistake.

* Dynamic attributes without a fixed set of
valid values: +
The rules below assume that if the type of
the value does not match the expected type, the Expression Language will have applied
coercion rules to try to accomodate the input value. Moreover, if the
expected type is one of the types handled by the Expression Language coercion rules, the
Expression Language will in most cases coerce null to an approriate value. For instance,
if the expected type is a _Number_, the Expression Language will coerce a null value to
0, if it's _Boolean_ it will be coerced to false.

** null – behavior specific to the action +
If this rule is applied, it's because the Expression Language
could not coerce the null into an appropriate default value. It is
therefore up to the action to deal with the null value and is documented
in the "Null & Error Handling" section of the action.

** Invalid type – throw an exception

** Invalid value – throw an exception

* Exceptions caused by the body content: +
Always propagate, possibly after handling
them (e.g. `<sql:transaction>`).

* Exceptions caused by the action itself: +
Always propagate, possibly after handling
them.

* Exceptions caused by the Expression Language: +
Always propagate.

* Exceptions caused by XPath: +
Always propagate.

Page authors may catch an exception using
`<c:catch>`, which exposes the exception through its _var_ attribute.
_var_ is removed if no exception has occurred.

When this specification requires an action to
throw an exception, this exception must be an instance of
_jakarta.servlet.jsp.JspException_ or a subclass. If an action catches any
exceptions that occur in its body, its tag handler must provide the
caught exception as the root cause of the _JspException_ it re-throws.

Also, by default, Jakarta Standard Tag Library actions do not catch
or otherwise handle exceptions that occur during evaluation of their
body content. If they do, it is documented in their "Null & Error
Handling" or "Description" section.

=== Configuration Data

Context initialization parameters (see
Servlet specification) are useful to configure the behavior of actions.
For example, it is possible in the Jakarta Standard Tag Library to define the resource bundle used
by I18N actions via the deployment descriptor (web.xml) as follows:

....
<web-app>
...
    <context-param>
        <param-name>jakarta.servlet.jsp.jstl.fmt.localizationContext</param-name>
        <param-value>com.acme.MyResources</param-value>
    </context-param>
...
</web-app>
....

In many cases, it is also useful to allow
configuration data to be overridden dynamically for a particular Jakarta Server Pages
scope (page, request, session, application) via a scoped variable. The Jakarta Standard Tag Library
refers to scoped variables used for that purpose as configuration
variables.

According to the Jakarta Server Pages specification
(Jakarta Server Pages.2.8.2), a scoped variable name should refer to a unique object at
all points in the execution. This means that all the different scopes
(page, request, session, and application) that exist within a
_PageContext_ really should behave as a single name space; setting a
scoped variable in any one scope overrides it in any of the other
scopes.

Given this constraint imposed by the Jakarta Server Pages
specification, and in order to allow a configuration variable to be set
for a particular scope without affecting its settings in any of the
other scopes, the Jakarta Standard Tag Library provides the _jakarta.servlet.jsp.jstl.core.Config_ class. The _Config_ class
transparently manipulates the name of configuration variables so they
behave as if scopes had their own private name space. Details on the
name manipulations involved are voluntarily left unspecified and are
handled transparently by the _Config_ class. This ensures flexibility
should the "scope name space" issue be addressed in the future by the
Jakarta Server Pages specification.

When setting configuration data via the
deployment descriptor, the name associated with the context
initialization parameter (e.g.
jakarta.servlet.jsp.jstl.fmt.localizationContext) must be used and only
_String_ values may be specified. Configuration data that can be set
both through a context initialization parameter and configuration
variables is referred to as a configuration setting in this
specification.

As mentioned above, application developers
may access configuration data through class _jakarta.servlet.jsp.jstl.core.Config_. As a convenience,
constant _String_ values have been defined in the _Config_ class for
each configuration setting supported by the Jakarta Standard Tag Library. The values of these
constants are the names of the context intialization parameters.

Each configuration variable clearly specifies
the Java data type(s) it supports. If the type of the object used as the
value of a configuration variable does not match one of those supported
by the configuration variable, conversion is performed according to the
conversion rules defined in the expression language. Setting a
configuration variable is therefore exactly the same as setting an
attribute value of an action using the Expression Language. A failure of these conversion
rules to determine an appropriate type coersion leads to a
_JspException_ at runtime.

=== Default Values

It is often desirable to display a default
value if the output of an action yields a null value. This can be done
in a generic way in the Jakarta Standard Tag Library by exporting the output of an action via
attribute _var_, and then displaying the value of that scoped variable
with action `<c:out>`.

For example:
....
<fmt:formatDate var="formattedDate" value="${reservationDate}"/>
Date: <c:out value="${formattedDate}" default="not specified"/>
....

== Expression Language Overview

Jakarta Standard Tag Library makes use of the Jakarta Expression Language. 

This chapter provides a simple overview of
the key features of the expression language, it is therefore
non-normative. Please refer to the Jakarta Expression Language specification for the formal
definition of the Expression Language.

=== Expressions and Attribute Values

The Expression Language is invoked exclusively via the
construct _${expr}_. In the sample code below, an Expression Language expression is
used to set the value of attribute _test_, while a second one is used
to display the title of a book.

....
<c:if test="${book.price <= user.preferences.spendingLimit}">
    The book ${book.title} fits your budget!
</c:if>
....

It is also possible for an attribute to
contain more than one Expression Language expression, mixed with static text. For
example, the following would display "Price of productName is
productPrice" for a list of products.

....
<c:forEach var="product" items="${products}">
    <c:out value="Price of ${product.name} is ${product.price}"/>
</c:forEach>
....

=== Accessing Application Data

An identifier in the Expression Language refers to the Jakarta Server Pages
scoped variable returned by a call to
_PageContext.findAttribute(identifier)_. This variable can therefore
reside in any of the four Jakarta Server Pages scopes: page, request, session, or
application. A null value is returned if the variable does not exist in
any of the scopes.

The Expression Language also defines implicit objects to
support easy access to application data that is of interest to a page
author. Implicit objects _pageScope_, _requestScope_, _session_ Scope,
and _applicationScope_ provide access to the scoped variables in each
one of these Jakarta Server Pages scopes. It is also possible to access HTTP request
parameters via the implicit objects _param_ and _paramValues_. The implicit object _param_
is a _Map_ object where _param["foo"]_ returns the first string value
associated with request parameter _foo_, while _paramValues["foo"]_
returns an array of all string values associated with that request
parameter.

The code below displays all request
parameters along with all their associated values.

....
<c:forEach var="aParam"items="${paramValues}">
    param: ${aParam.key}
    values:
    <c:forEach var="aValue" items="${aParam.value}">
        ${aValue}
    </c:forEach>
    <br>
</c:forEach>
....

Request headers are also accessible in a
similar fashion via implicit objects _header_ and _headerValues_.
_initParam_ gives access to context initialization parameters, while
_cookie_ exposes cookies received in the request.

Implicit object _pageContext_ is also
provided for advanced usage, giving access to all properties associated
with the _PageContext_ of a Jakarta Server Pages page such as the _HttpServletRequest_,
_ServletContext_, and _HttpSession_ objects and their properties.

=== Nested Properties and Accessing Collections

The application data that a page author
manipulates in a Jakarta Server Pages page usually consists of objects that comply with
the JavaBeans specification, or that represent collections such as
lists, maps, or arrays.

The Expression Language recognizes the importance of these
data structures and provides two operators, "." and "[]", to make it
easy to access the data encapsulated in these objects.

The "." operator can be used as a convenient
shorthand for property access when the property name follows the
conventions of Java identifiers. For example:

....
Dear ${user.firstName}
from ${user.address.city},
thanks for visiting our website!
....

The "[]" operator allows for more generalized
access, as shown below:

....
<%-- "productDir" is a Map object containing the description of
products, "preferences" is a Map object containing the preferences of a user --%>
product:
${productDir[product.custId]}
shipping preference:
${user.preferences["shipping"]}
....

=== Operators

The operators supported in the Expression Language handle the
most common data manipulations. The standard relational, arithmetic, and
logical operators are provided in the Expression Language. A very useful "empty" operator
is also provided.

The six standard relational operators are
supported: _==_ (or _eq_), _!=_ (or _ne_), _<_ (or _lt_), _>_ (or
_gt_), _<=_ (or _le_), _>=_ (or _ge_). The second versions of the
last 4 operators are made available to avoid having to use entity
references in XML syntax.

Arithmetic operators consist of addition (_+_), subtraction (_-_), multiplication (_*_), division (_/_ or
_div_), and remainder/modulo (_%_ or _mod_).

Logical operators consist of _&&_ (or _and_), _||_ (or _or_), and _!_ (or _not_).

The _empty_ operator is a prefix operator
that can used to determine if a value is null or empty. For example:

....
<c:if test="${empty param.name}">
    Please specify your name.
</c:if>
....

=== Automatic Type Conversion

The application data a page author has access
to may not always exactly match the type expected by the attribute of an
action or the type expected for an Expression Language operator. The Expression Language supports an
exhaustive set of rules to coerce the type of the resulting value to the
expected type.

For example, if request attributes
_beginValue_ and _endValue_ are _Integer_ objects, they will
automatically be coerced to _ints_ when used with the `<c:forEach>`
action.

....
<c:forEach begin="${requestScope.beginValue}"
           end="${requestScope.endValue}">
    ...
</c:forEach>
....

In the example below, the parameter String
value _param.start_ is coerced to a number and is then added to 10 to
yield an int value for attribute _begin_.

....
<c:forEach items="${products}" begin="${param.start + 10}">
    ...
</c:forEach>
....

=== Default Values

Jakarta Server Pages are mostly used in presentation.
Experience suggests that it is important to be able to provide as good a
presentation as possible, even when simple errors occur in the page. To
satisfy this requirement, the Expression Language provides default values rather than
errors when failure to evaluate an expression is deemed "recoverable".
Default values are type-correct values that allow a page to easily
recover from these error conditions.

In the following example, the expression
"${user.address.city}" evaluates to _null_ rather than throwing a
_NullPointerException_ if there is no address associated with the _user_
object. This way, a sensible default value can be displayed without
having to worry about exceptions being thrown by the Jakarta Server Pages page.

....
City: <c:out value="${user.address.city}" default="N/A"/>
....

In the following example, the addition
operator considers the value of _param.start_ to be 0 if it is not
defined, therefore evaluating the expression to 10.

....
<c:forEach items="${products}" begin="${param.start + 10}">
    ...
</c:forEach>
....

== General-Purpose Actions: core tag library

This chapter introduces general purpose
actions to support the manipulation of scoped variables as well as to
handle error conditions.

=== Overview

The `<c:out>` action provides a capability
similar to Jakarta Server Pages expressions such as <%= scripting-language-expression %>
or ${el-expression}. For example:

....
You have <c:out value="${sessionScope.user.itemCount}"/> items.
....

By default, `<c:out>` converts the characters
<, >, ', ", & to their corresponding character entity codes (e.g. < is
converted to &lt;). If these characters are not converted, the page may
not be rendered properly by the browser, and it could also open the door
for cross-site scripting attacks (e.g. someone could post JavaScript
code for closing the window to an online discussion forum). The
conversion may be bypassed by specifying false to the _escapeXml_
attribute.

The `<c:out>` action also supports the notion
of default values for cases where the value of an Expression Language expression is null.
In the example below, the value "unknown" will be displayed if the
property _city_ is not accessible.

....
<c:out value="${customer.address.city}" default="unknown"/>
....

The action `<c:set>` is used to set the value
of a Jakarta Server Pages scoped attribute as follows:

....
<c:set var="foo" value="value"/>
....

It is also possible to set the value of a
scoped variable (Jakarta Server Pages scoped attribute) from the body of the `<c:set>`
action. This solves the problem associated with not being able to set an
attribute value from another action. In the past, a tag developer would
often implement extra "attributes as tags" so the value of these
attributes could be set from other actions.

For example, the action `<acme:att1>` was
created only to support setting the value of _att1_ of the parent tag
`<acme:atag>` from other actions .

....
<acme:atag>

 <acme:att1>

 <acme:foo>mumbojumbo</acme:foo>

 </acme:att1>

</acme:atag>
....

With the `<c:set>` tag, this can be handled
without requiring the extra `<acme:att1>` tag.

....
<c:set var="att1">

 <acme:foo>mumbojumbo</acme:foo>

</c:set>

<acme:atag att1="${att1}"/>
....

In the preceding example, the `<c:set>` action
sets the value of the _att1_ scoped variable to the output of the
`<acme:foo>` action. `<c:set>` – like all Jakarta Standard Tag Library actions that create scoped
attributes – creates scoped attributes in "page" scope by default.

`<c:set>` may also be used to set the property
of a JavaBeans object, or add or set a specific element in a
_java.util.Map_ object. For example:.

....
<!-- set property in JavaBeans object -->
<c:set target="${cust.address}" property="city" value="${city}"/>

<!-- set/add element in Map object -->
<c:set target="${preferences}" property="color" value="${param.color}"/>
....

Finally, `<c:set>` may also be used to set a
deferred-value that can later be evaluated by a tag handler. In this
case, no scope can be specified. For example:

....
<!-- set deferred value -->
<c:set var="d" value="#{handler.everythingDisabled}"/>
...

<h:inputText id="i1" disabled="#\{d}"/>
<h:inputText id="i2" disabled="#\{d}"/>
....

Action `<c:remove>` is the natural companion to
`<c:set>`, allowing the explicit removal of scoped variables. For example:

....
<c:remove var="cachedResult" scope="application"/>
....

Finally, the `<c:catch>` action provides a
complement to the Jakarta Server Pages error page mechanism. It is meant to allow page
authors to recover gracefully from error conditions that they can
control. For example:

....
<c:catch var="exception">
<!-- Execution we can recover from if exception occurs -->
...
</c:catch>
<c:if test="${exception != null}">
Sorry. Processing could not be performed because...
</c:if>
....

<<<

[[c:out]]
=== <c:out>

Evaluates an expression and outputs the result
of the evaluation to the current _JspWriter_ object.

.*Syntax*

_Without a body_

[literal, subs="+quotes, +attributes"]
<c:out value="value" {blank}[escapeXml="{[underline]#true#|false}"]
    {blank}[default="defaultValue"] />

_With a body_

[literal, subs="+quotes, +attributes"]
<c:out value="value" {empty}[escapeXml="{[underline]#true#|false}"]>
    default value
</c:out>

.*Body Content*
Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content, then the action trims it and processes it further.

.*Attributes*
[caption=]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _value_ | _true_
| _Object_
|Expression to be evaluated.

| _escapeXml_ |
_true_ | _boolean_
|Determines whether characters <,>,&,'," in
the resulting string should be converted to their corresponding
character entity codes. Default value is true.

| _default_ |
_true_ | _Object_
|Default value if the resulting value is
null.
|===

.*Null & Error Handling*
If _value_ is null, the default value takes
over. If no default value is specified, it itself defaults to an empty
string.

.*Description*
The expression to be evaluated is specified
via the _value_ attribute.

If the result of the evaluation is not a
_java.io.Reader_ object, then it is coerced to a _String_ and is
subsequently emitted into the current _JspWriter_ object.

If the result of the evaluation is a
_java.io.Reader_ object, data is first read from the _Reader_ object and
then written into the current _JspWriter_ object. This special
processing associated with _Reader_ objects should help improve
performance when large amount of data must be read and then displayed to
the page.

If _escapeXml_ is true, the following
character conversions are applied:



[width="100%",cols="50%,50%",options="header",]
|===
|Character
|Character Entity Code
| _<_ | _\&lt;_

| _>_ | _\&gt;_

| _&_ | _\&amp;_

|' |\&#039;

|" |\&#034;
|===

The default value can be specified either via
the _default_ attribute (using the syntax without a body), or within the
body of the tag (using the syntax with a body). It defaults to an empty
string.

<<<

[[c:set]]
=== <c:set>

Sets the value of a scoped variable or a
property of a target object.

.*Syntax*

_Syntax 1: Set the value of a scoped
variable using attribute value_

[literal, subs="+quotes, +attributes"]
<c:set value="value"
    var="varName" {empty}[scope="{[underline]#page#|request|session|application}"]/>

_Syntax 2: Set the value of a scoped
variable using body content_

[literal, subs="+quotes, +attributes"]
<c:set var="varName" {empty}[scope="{[underline]#page#|request|session|application}"]>
    body content
</c:set>

_Syntax 3: Set a property of a target object
using attribute value_
....
<c:set value="value"
    target="target" property="propertyName"/>
....

_Syntax 4: Set a property of a target object
using body content_
....
<c:set target="target" property="propertyName">
    body content
</c:set>
....

_Syntax 5: Set a deferred value_
....
<c:set var="varName" value="deferred-value"/>
....

.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content, then the action trims it and processes it further.

.*Attributes*
[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _value_ | _true_
| _Object_
|Expression to be evaluated.

| _var_ | _false_
| _String_ |Name
of the exported scoped variable to hold the value specified in the
action. The type of the scoped variable is whatever type the value
expression evaluates to.

| _scope_ |
_false_ | _String_
|Scope for var.

|target |true
|Object |Target
object whose property will be set. Must evaluate to a JavaBeans object
with setter property _property_, or to a _java.util.Map_ object.

|property |true
|String |Name of
the property to be set in the target object.
|===

.*Null & Error Handling*

* Syntax 3 and 4: Throw an exception under any
of the following conditions:

** _target_ evaluates to null

** _target_ is not a _java.util.Map_ object and
is not a JavaBeans object that supports setting property _property_.

* If _value_ is null

** Syntax 1: the scoped variable defined by
_var_ and _scope_ is removed.

*** If attribute _scope_ is specified, the scoped
variable is removed according to the semantics of
_PageContext.removeAttribute(varName, scope)_.

*** Otherwise, there is no way to differentiate
between syntax 1 and syntax 5. The scoped variable is removed according
to the semantics of _PageContext.removeAttribute(varName)_, and the
variable is removed from the VariableMapper as well.

** Syntax 3:

*** if _target_ is a _Map_, remove the entry
with the key identified by _property_.

*** if _target_ is a JavaBean component, set the
property to null.

** Syntax 5:

*** There is no way to differentiate between
syntax 1 (where scope is not specified) and syntax 5. The scoped
variable is removed according to the semantics of
_PageContext.removeAttribute(varName)_, and the variable is removed
from the VariableMapper as well.

.*Description*

Syntax 1 and 2 set the value of a the scoped
variable identified by _var_ and _scope_.

Syntax 3 and 4:

* If the target expression evaluates to a
_java.util.Map_ object, set the value of the element associated with the
key identified by _property_. If the element does not exist, add it to
the _Map_ object.

* Otherwise, set the value of the property
_property_ of the JavaBeans object _target_. If the type of the value
to be set does not match the type of the bean property, conversion is
performed according to the conversion rules defined in the expression
language (see Section 1.23. Type Conversion of the Jakarta Expression Language specification). With the
exception of a null value, setting a bean property with <c:set> is
therefore exactly the same as setting an attribute value of an action
using the Expression Language. A failure of these conversion rules to determine an
appropriate type coersion leads to a _JspException_ at runtime.

Syntax 5:

* Map the deferred-value specified to the "var"
attribute into the Expression Language VariableMapper.

* Some implementation notes illustrating how
the <c:set> tag handler may process a deferred-value specified for the
"value" attribute.

[width="100%",cols="100%",]
|===
|doStartTag() +
... +
 // 'value' is a deferred-value +
 // Get the current Expression Language VariableMapper +
VariableMapper vm = jspContext.getELContext().getVariableMapper(); +
 // Assign the expression to the variable specified +
 // in the 'var' attribute, so any reference to that +
 // variable will be replaced by the expression is +
 // subsequent Expression Language evaluations. +
vm.setVariable(getVar(), (ValueExpression)getValue()); +
...
|===

<<<

=== <c:remove>

Removes a scoped variable.

.*Syntax*

....
<c:remove var="varName"
          [scope="{page|request|session|application}"]/>
....

.*Attributes*
[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _var_ | _false_
| _String_ |Name
of the scoped variable to be removed.

| _scope_ |
_false_ | _String_
|Scope for var.
|===

.*Description*

The `<c:remove>` action removes a scoped
variable.

If attribute _scope_ is not specified, the
scoped variable is removed according to the semantics of
_PageContext.removeAttribute(varName)_. If attribute _scope_ is
specified, the scoped variable is removed according to the semantics of
_PageContext.removeAttribute(varName, scope)_.

<<<

=== <c:catch>

Catches a _java.lang.Throwable_ thrown by any
of its nested actions.

.*Syntax*
....
<c:catch [var="varName"]>
    nested actions
</c:catch>
....

.*Body Content*

Jakarta Server Pages content. The body content is processed by the Jakarta Server Pages
container and the result is written to the current _JspWriter_.

.*Attributes*
[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _var_ | _false_
| _String_ |Name
of the exported scoped variable for the exception thrown from a nested
action. The type of the scoped variable is the type of the exception
thrown.
|===

.*Description*

The `<c:catch>` action allows page authors to
handle errors from any action in a uniform fashion, and allows for error
handling for multiple actions at once.

`<c:catch>` provides page authors with granular
error handling: Actions that are of central importance to a page should
not be encapsulated in a `<c:catch>`, so their exceptions will propagate
to an error page, whereas actions with secondary importance to the page
should be wrapped in a `<c:catch>`, so they never cause the error page
mechanism to be invoked.

The exception thrown is stored in the scoped
variable identified by _var_, which always has page scope. If no
exception occurred, the scoped variable identified by _var_ is removed
if it existed.

If _var_ is missing, the exception is simply
caught and not saved.

== Conditional Actions: core tag library

The output of a Jakarta Server Pages page is often conditional
on the value of dynamic application data. A simple scriptlet with an
_if_ statement can be used in such situations, but this forces a page
author to use a scripting language whose syntax may be troublesome (e.g.
one may forget the curly braces).

The Jakarta Standard Tag Library conditional actions make it easy to
do conditional processing in a Jakarta Server Pages page.

=== Overview

The Jakarta Standard Tag Library conditional actions are designed to
support the two most common usage patterns associated with conditional
processing: _simple_ conditional execution and _mutually exclusive_
conditional execution.

A _simple_ conditional execution action
evaluates its body content only if the test condition associated with it
is true. In the following example, a special greeting is displayed only
if this is a user's first visit to the site:

....
<c:if test="${user.visitCount == 1}">
    This is your first visit. Welcome to the site!
</c:if>
....

With _mutually exclusive_ conditional
execution, only one among a number of possible alternative actions gets
its body content evaluated.

For example, the following sample code shows
how the text rendered depends on a user's membership category.

....
<c:choose>
    <c:when test="${user.category == 'trial'}">
        ...
    </c:when>
    <c:when test="${user.category == 'member'}">
        ...
    </c:when>
    <c:when test="${user.category == 'vip'}">
        ...
    </c:when>
    <c:otherwise>
        ...
    </c:otherwise>
</c:choose>
....

An _if/then/else_ statement can be easily
achieved as follows:

....
<c:choose>
    <c:when test="${count == 0}">
        No records matched your selection.
    </c:when>
    <c:otherwise>
        ${count} records matched your selection.
    </c:otherwise>
</c:choose>
....

=== Custom Logic Actions

It is important to note that the `<c:if>` and
`<c:when>` actions have different semantics. A `<c:if>` action will always
process its body content if its test condition evaluates to true. A
`<c:when>` action will process its body content if it is the first one in
a series of `<c:when>` actions whose test condition evaluates to true.

These semantic differences are enforced by
the fact that only `<c:when>` actions can be used within the context of a
mutually exclusive conditional execution (`<c:choose>` action). This clean
separation of behavior also impacts the way custom logic actions (i.e.
actions who render their bodies depending on the result of a test
condition) should be designed. Ideally, the result associated with the
evaluation of a custom logic action should be usable both in the context
of a simple conditional execution, as well as in a mutually exclusive
conditional execution.

The proper way to enable this is by simply
having the custom logic action export the result of the test condition
as a scoped variable. This boolean result can then be used as the test
condition of a `<c:when>` action.

In the example below, the fictitious custom
action `<acme:fullMoon>` tells whether or not a page is accessed during a
full moon. The behavior of an _if/then/else_ statement is made possible
by having the result of the `<acme:fullMoon>` action exposed as a boolean
scoped variable that is then used as the test condition in the `<c:when>`
action.

....
<acme:fullMoon var="isFullMoon"/>
<c:choose>
    <c:when test="${isFullMoon}">
        ...
    </c:when>
    <c:otherwise>
        ...
    </c:otherwise>
</c:choose>
....

To facilitate the implementation of
conditional actions where the boolean result is exposed as a Jakarta Server Pages scoped
variable, class _jakarta.servlet.jsp.jstl.core.ConditionalTagSupport_ has been defined in this
specification.

<<<

=== <c:if>

Evaluates its body content if the expression
specified with the _test_ attribute is true.

.*Syntax*

_Syntax 1: Without body content_

[literal, subs="+quotes, +attributes"]
<c:if test="testCondition"
    var="varName" {blank}[scope="{[underline]#page#|request|session|application}"]/>


_Syntax 2: With body content_

[literal, subs="+quotes, +attributes"]
<c:if test="testCondition"
        [var="varName"] {blank}[scope="{[underline]#page#|request|session|application}"]>
    body content
</c:if>

.*Body Content*

Jakarta Server Pages content. If the test condition evaluates to true,
the Jakarta Server Pages container processes the body content and then writes it to the
current _JspWriter_.

.*Attributes*
[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _test_ | _true_
| _boolean_ |The
test condition that determines whether or not the body content should be
processed.

| _var_ | _false_
| _String_ |Name
of the exported scoped variable for the resulting value of the test
condition. The type of the scoped variable is _Boolean_.

| _scope_ |
_false_ | _String_
|Scope for var.
|===

.*Constraints*

* If _scope_ is specified, _var_ must also be
specified.

.*Description*

If the test condition evaluates to true, the
body content is evaluated by the Jakarta Server Pages container and the result is output
to the current _JspWriter_.

<<<

=== <c:choose>

Provides the context for mutually exclusive
conditional execution.

.*Syntax*
....
<c:choose>
    body content (<when> and <otherwise> subtags)
</c:choose>
....

.*Body Content*

Jakarta Server Pages content. The body content is processed by the Jakarta Server Pages
container (at most one of the nested actions will be processed) and
written to the current _JspWriter_.

.*Attributes*

None.

.*Constraints*

* The body of the `<c:choose>` action can only
contain:

** White spaces +
May appear anywhere around the `<c:when>` and `<c:otherwise>` subtags.

** 1 or more `<c:when>` actions +
Must all appear before `<c:otherwise>`

** 0 or 1 `<c:otherwise>` action +
Must be the last action nested within `<c:choose>`

.*Description*

The `<c:choose>` action processes the body of
the first `<c:when>` action whose test condition evaluates to true. If
none of the test conditions of nested `<c:when>` actions evaluates to
true, then the body of an `<c:otherwise>` action is processed, if present.

<<<

=== <c:when>

Represents an alternative within a `<c:choose>`
action.

.*Syntax*

....
<c:when test="testCondition">
    body content
</c:when>
....

.*Body Content*

Jakarta Server Pages content. If this is the first <c:when> action to
evaluate to true within <c:choose>, the Jakarta Server Pages container processes the body
content and then writes it to the current _JspWriter_.

.*Attributes*
[caption=]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _test_ | _true_
| _boolean_ |The
test condition that determines whether or not the body content should be
processed.
|===

.*Constraints*

* Must have _<c:choose>_ as an immediate
parent.

* Must appear before an <c:otherwise> action
that has the same parent.

.*Description*

Within a `<c:choose>` action, the body content
of the first `<c:when>` action whose test condition evaluates to true is
evaluated by the Jakarta Server Pages container, and the result is output to the current
_JspWriter_.

<<<

=== <c:otherwise>

Represents the last alternative within a
`<c:choose>` action.

.*Syntax*

....
<c:otherwise>
    conditional block
</c:otherwise>
....

.*Body Content*

Jakarta Server Pages content. If no `<c:when>` action nested within
`<c:choose>` evaluates to true, the Jakarta Server Pages container processes the body
content and then writes it to the current _JspWriter_.

.*Attributes*

None.

.*Constraints*

** Must have `<c:choose>` as an immediate parent.

** Must be the last nested action within
`<c:choose>`.

.*Description*

Within a `<c:choose>` action, if none of the
nested `<c:when>` test conditions evaluates to true, then the body content
of the `<c:otherwise>` action is evaluated by the Jakarta Server Pages container, and the
result is output to the current _JspWriter_.


== Iterator Actions: core tag library

Iterating over a collection of objects is a
common occurrence in a Jakarta Server Pages page. Just as with conditional processing, a
simple scriptlet can be used in such situations. However, this once
again forces a page author to be knowledgeable in many aspects of the
Java programming language (how to iterate on various collection types,
having to cast the returned object into the proper type, proper use of
the curly braces, etc.).

The Jakarta Standard Tag Library iterator actions simplify iterating
over a wide variety of collections of objects.

=== Overview

The `<c:forEach>` action repeats its nested
body content over the collection of objects specified by the _items_
attribute. For example, the Jakarta Server Pages code below creates an HTML table with
one column that shows the default display value of each item in the
collection.

....
<table>
    <c:forEach var="customer" items="${customers}">
        <tr><td>${customer}</td></tr>
    </c:forEach>
</table>
....

The `<c:forEach>` action has the following
features:

* Supports all standard Java SE™ platform collection types. +
A page author therefore does not have to
worry about the specific type of the collection of objects to iterate
over (<<Collections of Objects to Iterate Over>>).

* Exports an object that holds the current item of the iteration. +
Normally, each object exposed by `<c:forEach>`
is an item of the underlying collection being iterated over. There are
two exceptions to this to facilitate access to the information contained
in arrays of primitive types, as well as in _Map_ objects (see
<<Map>>).

* Exports an object that holds information
about the status of the iteration (see <<Iteration Status>>).

* Supports range attributes to iterate over a
subset of the original collection (see <<Range Attributes>>).

* Exposes an interface as well as a base implementation class. +
Developers can easily implement collaborating
subtags as well as their own iteration tags (see
<<Tag Collaboration>>).

`<c:forEach>` is the base iteration action in
the Jakarta Standard Tag Library. It handles the most common iteration cases conveniently. Other
iteration actions are also provided in the tag library to support
specific, specialized functionality not handled by `<c:forEach>` (e.g.
`<c:forTokens>` (<<c:forTokens>>) and
`<x:forEach>` (<<x:forEach>>). Developers
can also easily extend the behavior of this base iteration action to
customize it according to an application's specific needs.

==== Collections of Objects to Iterate Over

A large number of collection types are
supported by `<c:forEach>`, including all implementations of
_java.util.Collection_ (includes _List_, _LinkedList_, _ArrayList_,
_Vector_, _Stack_, _Set_), and _java.util.Map_ (includes _HashMap_,
_Hashtable_, _Properties_, _Provider_, _Attributes_).

Arrays of objects as well as arrays of
primitive types (e.g. _int_) are also supported. For arrays of
primitive types, the current item for the iteration is automatically
wrapped with its standard wrapper class (e.g. _Integer_ for _int_,
_Float_ for _float_, etc.).

Implementations of _java.util.Iterator_ and
_java.util.Enumeration_ are supported as well but these must be used
with caution. _Iterator_ and _Enumeration_ objects are not resettable so
they should not be used within more than one iteration tag.

*Deprecated*: Finally,
_java.lang.String_ objects can be iterated over if the string represents
a list of comma separated values (e.g.
"Monday,Tuesday,Wednesday,Thursday,Friday").footnote:[The proper way to process strings of tokens is via <c:forTokens> or via functions _split_ and _join_.]

Absent from the list of supported types is
_java.sql.ResultSet_ (which includes _javax.sql.RowSet_). The reason
for this is that the SQL actions described in
<<SQL_Action_Overview>> use the
_jakarta.servlet.jsp.jstl.sql.Result_ interface to access the data
returned from an SQL query. Class
_jakarta.servlet.jsp.jstl.sql.ResultSupport_ allows business logic
developers to easily convert a _ResultSet_ object into a
_jakarta.servlet.jsp.jstl.sql.Result_ object, making life much easier for
a page author that needs to manipulate the data returned from a SQL
query.

==== Map

If the _items_ attribute is of type
_java.util.Map_, then the current item will be of type
_java.util.Map.Entry_, which has the following two properties:

* _key_ - the key under which this item is
stored in the underlying _Map_

* _value_ - the value that corresponds to this
key

The following example uses `<c:forEach>` to
iterate over the values of a _Hashtable_:

....
<c:forEach var="entry" items="${myHashtable}">
    Next element is ${entry.value}/>
</c:forEach>
....

==== Iteration Status

`<c:forEach>` also exposes information relative
to the iteration taking place. The example below creates an HTML table
with the first column containing the position of the item in the
collection, and the second containing the name of the product.

....
<table>
    <c:forEach var="product" items="${products}"
            varStatus="status">
        <tr>
            <td>${status.count}</td>
            <td>${product.name}</td>
        </tr>
    </c:forEach>
</table>
....

See the Javadoc for details on the _jakarta.servlet.jsp.jstl.core.LoopTagStatus_ interface exposed by the
_varStatus_ attribute.

==== Range Attributes

A set of range attributes is available to
iterate over a subset of the collection of items. The _begin_ and _end_
indices can be specified, along with a _step_. If the _items_ attribute
is not specified, then the value of the current item is set to the
integer value of the current index. In this example, _i_ would take
values from 100 to 110 (inclusive).

....
<c:forEach var="i" begin="100" end="110">
    ${i}
</c:forEach>
....

==== Tag Collaboration

Custom actions give developers the power to
provide added functionality to a Jakarta Server Pages application without requiring the
page author to use Java code. In this example, an item of the iteration
is processed differently depending upon whether it is an odd or even
element.

....
<c:forEach var="product" items="${products}" varStatus="status">
    <c:choose>
        <c:when test="${status.count % 2 == 0}">
            even item
        </c:when>
        <c:otherwise>
            odd item
        </c:otherwise>
    </c:choose>
</c:forEach>
....

If this type of processing is common, it
could be worth providing custom actions that yield simpler code, as
shown below.

....
<c:forEach var="product" items="${products}">
    <acme:even>
        even item
    </acme:even>
    <acme:odd>
        odd item
    </acme:odd>
</c:forEach>
....

In order to make this possible, custom
actions like `<acme:odd>` and `<acme:even>` leverage the fact that
`<c:forEach>` supports implicit collaboration via the interface _jakarta.servlet.jsp.jstl.core.LoopTag_.

The fact that `<c:forEach>` exposes an
interface also means that other actions with iterative behavior can be
developed using the same interface and will collaborate in the same
manner with nested tags. Class _jakarta.servlet.jsp.jstl.core.LoopTagSupport_ provides a solid base for
doing this.

==== Deferred Values

The unified Expression
Language supports the concept of deferred expressions (using the #{}
syntax), i.e. expressions whose evaluation is deferred to application
code (as opposed to immediate evaluation (using the ${} syntax) where
the expression is evaluated immediately by the container). Deferred
expressions are used mostly with Jakarta Server Faces, a component-based UI
framework for the webtier.

In order for Jakarta Standard Tag Library iteration tags to support
nested actions that access the iteration variable as a deferred-value,
the _items_ attribute must be specified as a deferred-value as well.

For example:

....
<c:forEach var="child" items="#{customer.children}">
    <h:inputText value="#{child.name}"/>
</c:forEach>
....

Because a deferred-value is specified for
items, the iteration tag has access to the original expression and can
make the iteration variable available as a deferred-value with the
proper index into the _items_ collection. This deferred value can then
be evaluated properly by the code associated with the `<h:inputText>`
component.

<<<

[[c:forEach]]
=== <c:forEach>

Repeats its nested body content over a
collection of objects, or repeats it a fixed number of times.

.*Syntax*

_Syntax 1: Iterate over a collection of objects_
....
<c:forEach  [var="varName"] items="collection"
            [varStatus="varStatusName"]
            [begin="begin"] [end="end"] [step="step"]>
    body content
</c:forEach>
....

_Syntax 2: Iterate a fixed number of times_
....
<c:forEach  [var="varName"]
            [varStatus="varStatusName"]
            begin="begin" end="end" [step="step"]>
    body content
</c:forEach>
....

.*Body Content*

Jakarta Server Pages content. As long as there are items to iterate
over, the body content is processed by the Jakarta Server Pages container and written to
the current _JspWriter_.

.*Attributes*
[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _var_ | _false_
| _String_ |Name
of the exported scoped variable for the current item of the iteration.
This scoped variable has nested visibility. Its type depends on the
object of the underlying collection.

| _items_ | _true_
|Any of the supported types described in
Section "Description" below. |Collection
of items to iterate over.

| _varStatus_ |
_false_ | _String_
|Name of the exported scoped variable for the
status of the iteration. Object exported is of type
_jakarta.servlet.jsp.jstl.core.LoopTagStatus_. This scoped variable has
nested visibility.

| _begin_ | _true_
| _int_ a|
If _items_ specified:

Iteration begins at the item located at the
specified index. First item of the collection has index 0.

If _items_ not specified:

Iteration begins with index set at the value
specified.

| _end_ | _true_
| _int_ a|
If _items_ specified:

Iteration ends at the item located at the
specified index (inclusive).

If _items_ not specified:

Iteration ends when index reaches the value
specified.

| _step_ | _true_
| _int_ |Iteration
will only process every _step_ items of the collection, starting with
the first one.
|===

.*Constraints*

* If specified, _begin_ must be >= 0.

* If _end_ is specified and it is less than
_begin_, the loop is simply not executed.

* If specified, _step_ must be >= 1

.*Null & Error Handling*

* If _items_ is null, it is treated as an empty
collection, i.e., no iteration is performed.

.*Description*

If _begin_ is greater than or equal to the
size of _items_, no iteration is performed.

*_Collections Supported & Current Item_*

The data types listed below must be supported
for _items_. With syntax 1, each object exposed via the _var_ attribute
is of the type of the object in the underlying collection, except for
arrays of primitive types and maps (see below). With syntax 2, the
object exported is of type _Integer_.

* Arrays +
This includes arrays of objects as well as
arrays of primitive types. For arrays of primitive types, the current
item for the iteration is automatically wrapped with its standard
wrapper class (e.g. _Integer_ for _int_, _Float_ for _float_, etc.) +
Elements are processed in their indexing
order.

* Implementation of _java.util.Collection_. +
An _Iterator_ object is obtained from the
collection via the _iterator()_ method, and the items of the collection
are processed in the order returned by that _Iterator_ object.

* Implementation of _java.util.Iterator_. +
Items of the collection are processed in the
order returned by the _Iterator_ object.

* Implementation of _java.util.Enumeration_. +
Items of the collection are processed in the
order returned by the _Enumeration_ object.

* Implementation of _java.util.Map_. +
The object exposed via the _var_ attribute is
of type _Map.Entry_. +
A _Set_ view of the mappings is obtained from
the _Map_ via the _entrySet()_ method, from which an _Iterator_ object
is obtained via the _iterator()_ method. The items of the collection are
processed in the order returned by that _Iterator_ object.

* _String_ +
The string represents a list of comma
separated values, where the comma character is the token delimiter.
Tokens are processed in their sequential order in the string.

*_Deferred Values_*

When a deferred-value is specified for the
_items_ attribute, the tag handler now adds at each iteration a mapping
for the _var_ attribute into the Expression Language _VariableMapper_.


Below are some implementation notes
illustrating how an iteration tag handler may process a deferred-value
specified for the _items_ attribute.

....
doStartTag()
    ...
    // 'items' is a deferred-value
    // Get the current Expression Language VariableMapper
    VariableMapper vm = 
        jspContext.getELContext().getVariableMapper();
    // Create an expression to be assigned to the variable
    // specified in the 'var' attribute.
    // 'index' is an iteration counter kept by the tag handler.
    myimpl.IndexedExpression expr =
        new myimpl.IndexExpression(getItems(), index);
    // Assign the expression to the variable specified in
    // the 'var' attribute, so any reference to that variable
    // will be replaced by the expression in subsequent
    // Expression Language evaluations.
    oldMapping = vm.setVariable(getVar(), expr);
    ...

doEndTag()
    ...
    // restore the original state of the VariableMapper
    jspContext.getELContext().getVariableMapper().setVariable(
        getVar(), oldMapping);
    ...
....

The number of items referred to by the
_items_ attribute must be the same when Jakarta Server Faces creates the component tree
and when Jakarta Server Pages executes the iteration tag. Undefined behavior will result
if this is not the case.

<<<

[[c:forTokens]]
=== <c:forTokens>

Iterates over tokens, separated by the
supplied delimiters.

.*Syntax*

....
<c:forTokens items="stringOfTokens" delims="delimiters"
        [var="varName"]
        [varStatus="varStatusName"]
        [begin="begin"] [end="end"] [step="step"]>
    body content
</c:forTokens>
....

.*Body Content*

Jakarta Server Pages content. As long as there are items to iterate
over, the body content is processed by the Jakarta Server Pages container and written to
the current _JspWriter_.

.*Attributes*
[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _var_ | _false_
| _String_ |Name
of the exported scoped variable for the current item of the iteration.
This scoped variable has nested visibility.

| _items_ | _true_
| _String_ |String
of tokens to iterate over.

| _delims_ |
_true_ | _String_
|The set of delimiters (the characters that
separate the tokens in the string).

| _varStatus_ |
_false_ | _String_
|Name of the exported scoped variable for the
status of the iteration. Object exported is of type
_jakarta.servlet.jsp.jstl.core.LoopTagStatus_. This scoped variable has
nested visibility.

| _begin_ | _true_
| _int_ |Iteration
begins at the token located at the specified index. First token has
index 0.

| _end_ | _true_
| _int_ |Iteration
ends at the token located at the specified index (inclusive).

| _step_ | _true_
| _int_ |Iteration
will only process every _step_ tokens of the string, starting with the
first one.
|===

.*Constraints*

* If specified, _begin_ must be >= 0.

* If _end_ is specified and it is less than
_begin_, the loop is simply not executed.

* If specified, _step_ must be >= 1

.*Null & Error Handling*

* If _items_ is null, it is treated as an empty
collection, i.e., no iteration is performed.

* If _delims_ is null, _items_ is treated as a
single monolithic token. Thus, when _delims_ is null, `<c:forTokens>`
iterates exactly zero (if _items_ is also null) or one time.

.*Description*

The tokens of the string are retrieved using
an instance of _java.util.StringTokenizer_ with arguments _items_ (the
string to be tokenized) and _delims_ (the delimiters).

Delimiter characters separate tokens. A token
is a maximal sequence of consecutive characters that are not delimiters.

*_Deferred Values_*

See Section "Deferred Values" for
`<c:forEach>`. Same comments apply here.

== URL Related Actions: core tag library

Linking, importing, and redirecting to URL
resources are features often needed in Jakarta Server Pages. Since dealing with
URLs can often be tricky, the Jakarta Standard Tag Library offers a comprehensive suite of
URL-related actions to simplify these tasks.

=== Hypertext Links

By using the HTML <A> element, a page author
can set a hypertext link as follows:

....
<a href="/register.jsp">Register</a>
....

If the link refers to a local resource and
session tracking is enabled, it is necessary to rewrite the URL so
session tracking can be used as a fallback, should cookies be disabled
at the client.

Morevoer, if query string parameters are
added to the URL, it is important that they be properly URL encoded. URL
encoding refers to the process of encoding special characters in a
string, according to the rules defined in RFC 2396. For example, a space
must be encoded in a URL string as a '+':

....
http://acme.com/app/choose?country=Dominican+Republic
....

As shown in the following example, the
combination of the `<c:url>` and `<c:param>` actions takes care of all
issues related to URL rewriting and encoding: `<c:url>` rewrites a URL if
necessary, and `<c:param>` transparently encodes query string parameters
(both name and value).

....
<c:url value="http://acme.com/exec/register" var="myUrl">
    <c:param name="name" value="${param.name}"/>
    <c:param name="country" value="${param.country}"/>
</c:url>
<a href='<c:out value="${myUrl}"/>'>Register</a>
....

Another important feature of `<c:url>` is that
it transparently prepends the context path to context-relative URLs.
Assuming a context path of "/foo", the following example

....
<c:url value="/ads/logo.html"/>
....

yields the URL _/foo/ads/logo.html_.


=== Importing Resources

There is a wide variety of resources that a
page author might be interested in including and/or processing within a
Jakarta Server Pages page. For instance, the example below shows how the content of the
README file at the FTP site of acme.com could be included within the
page.

....
<c:import url="ftp://ftp.acme.com/README"/>
....

In the Jakarta Server Pages specification, a `<jsp:include>`
action provides for the inclusion of static and dynamic resources
located in the same context as the current page. This is a very
convenient feature that is widely used by page authors.

However, `<jsp:include>` falls short in
flexibility when page authors need to get access to resources that
reside outside of the web application. In many situations, page authors
have the need to import the content of Internet resources specified via
an absolute URL. Moreover, as sites grow in size, they may have to be
implemented as a set of web applications where importing resources
across web applications is a requirement.

`<jsp:include>` also falls short in efficiency
when the content of the imported resource is used as the source for a
companion process/transformation action, because unnecessary buffering
occurs. In the example below, the `<acme:transform>` action uses the
content of the included resource as the input of its transformation.
`<jsp:include>` reads the content of the response, writes it to the body
content of the enclosing `<acme:transform>`, which then re-reads the exact
same content. It would be more efficient if `<acme:transform>` could
access the input source directly and avoid the buffering involved in the
body content of `<acme:transform>`.

....
<acme:transform>
    <jsp:include page="/exec/employeesList"/>
</acme:transform>
....

The main motivation behind `<c:import>` is to
address these shortcomings by providing a simple, straightforward
mechanism to access resources that can be specified via a URL. If
accessing a resource requires specifying more arguments, then a protocol
specific action (e.g. an <http> action) should be used for that purpose.
The Jakarta Standard Tag Library does not currently address these protocol-specific elements but may
do so in future releases.

==== URL

The _url_ attribute is used to specify the
URL of the resource to import. It can either be an absolute URL (i.e.
one that starts with a protocol followed by a colon), a relative URL
used to access a resource within the same context, or a relative URL
used to access a resource within a foreign context. The three different
types of URL are shown in the sample code below.

....
<%-- import a resource with an absolute URL --%>
<c:import url="http://acme.com/exec/customers?country=Japan"/>

<%-- import a resource with a relative URL - same context --%>
<c:import url="/copyright.html"/>

<%-- import a resource with a relative URL - foreign context --%>
<c:import url="/logo.html" context="/master"/>
....

==== Exporting an object: String or Reader

By default, the content of an imported
resource is included inline into the Jakarta Server Pages page.

It is also possible to make the content of
the resource available in two different ways: as a _String_ object
(attribute _var_), or as a _Reader_ object (attribute _varReader_).
Process or Transform tags can then access the resource's content through
that exported object as shown in the following example.

....
<%-- Export the content of the URL resource as a String --%>
<c:import url="http://acme.com/exec/customers?country=USA"
          var="customers"/>
<acme:notify in="${customers}"/>

<%-- Export the content of the URL resource as a Reader --%>

<c:import url="http://acme.com/exec/customers?country=USA"
          varReader="customers">
    <acme:notify in="${customers}"/>
</c:import>
....

Exporting the resource as a _String_ object
caches its content and makes it reusable.

If the imported content is large, some
performance benefits may be achieved by exporting it as a _Reader_
object since the content can be accessed directly without any buffering.
However, the performance benefits are not guaranteed since the reader's
support is implementation dependent. It is also important to note that
the _varReader_ scoped variable has nested visibility; it can only be
accessed within the body content of `<c:import>`.

==== URL Encoding

Just as with `<c:url>`, `<c:param>` can be nested
within `<c:import>` to encode query string parameters.

==== Networking Properties

If the web container executes behind a
firewall, some absolute URL resources may be inaccessible when using
`<c:import>`. To provide access to these resources, the JVM of the
container should be started with the proper networking properties (e.g.
_proxyHost_, _proxyPort_). More details can be found in the Java 2
SDK, Standard Edition Documentation (Networking Features — Networking
Properties).


=== HTTP Redirect

`<c:redirect>` completes the arsenal of URL
related actions to support an HTTP redirect to a specific URL. For
example:

....
<c:redirect url="http://acme.com/register"/>
....

<<<

=== <c:import>

Imports the content of a URL-based resource.

.*Syntax*

_Syntax 1: Resource content inlined or
exported as a String object_

[literal, subs="+quotes, +attributes"]
<c:import url="url" [context="context"]
        [var="varName"] {blank}[scope="{[underline]#page#|request|session|application}"]
        [charEncoding="charEncoding"]>
    optional body content for <c:param> subtags
</c:import>

_Syntax 2: Resource content exported as a
Reader object_

....
<c:import url="url" [context="context"]
        varReader="varReaderName"
        [charEncoding="charEncoding"]>
    body content where varReader is consumed by another action
</c:import>
....

.*Body Content*

Jakarta Server Pages content. The body content is processed by the Jakarta Server Pages
container and the result is written to the current _JspWriter_.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _url_ | _true_
| _String_ |The
URL of the resource to import.

| _context_ |
_true_ | _String_
|Name of the context when accessing a
relative URL resource that belongs to a foreign context.

| _var_ | _false_
| _String_ |Name
of the exported scoped variable for the resource's content. The type of
the scoped variable is _String_.

| _scope_ |
_false_ | _String_
|Scope for var.

| _charEncoding_ |
_true_ | _String_
|Character encoding of the content at the
input resource.

| _varReader_ |
_false_ | _String_
|Name of the exported scoped variable for the
resource's content. The type of the scoped variable is _Reader_.
|===

.*Null & Error Handling*

* If _url_ is null, empty, or invalid, a _JspException_ is thrown.

* If _charEncoding_ is null or empty, it is considered missing.

* For internal resources:

. If a _RequestDispatcher_ cannot be found for the resource, throw a _JspException_ with the resource path included in the message.

. Otherwise, if the _RequestDispatcher.include()_ method throws an _IOException_ or _RuntimeException_, throw a _JspException_ with the caught exception as the root cause.

. Otherwise, if the _RequestDispatcher.include()_ method throws a _ServletException_, look for a root cause.
.. If there's a root cause, throw a
_JspException_ with the root cause message included in the message and
the original root cause as the _JspException_ root cause.

.. Otherwise, same as 2).

. Otherwise, if the resource invoked through
_RequestDispatcher.include()_ method sets a response status code other
than 2xx (i.e. 200-299, the range of success codes in the HTTP response
codes), throw a _JspException_ with the path and status code in the
message.

* For external resources

** If the _URLConnection_ class throws an
_IOException_ or a _RuntimeException_, throw a _JspException_ with the
message from the original exception included in the message and the
original exception as the root cause.

** For an _HttpURLConnection_, if the response
status code is other than 2xx (i.e. 200-299, the range of success codes
in the HTTP response codes), throw a _JspException_ with the path and
status code in the message.

.*Description*

Using syntax 1, the content of the resource
is by default written to the current _JspWriter_. If _var_ is
specified, the content of the resource is instead exposed as a _String_
object.

Using syntax 2, the content of the resource
is exported as a _Reader_ object. The use of the _varReader_ attribute
comes with some restrictions.

It is the responsibility of the `<c:import>`
tag handler to ensure that if it exports a _Reader_, this _Reader_ is
properly closed by the time the end of the page is
reachedfootnote:[If the responsibility was left to the consumer tag, this could lead to resource leaks (e.g. connection left open, memory space for buffers) until garbage collection is activated. This is because a consumer tag might not close the _Reader_, or because the page author might remove the consumer tag while leaving inadvertantly the <c:import> tag in the page.]. Because of this requirement, the Jakarta Standard Tag Library defines
the exported _Reader_ as having nested visibility: it may not currently
be accessed after the end-tag for the `<c:import>`
actionfootnote:[This restriction could eventually be lifted when the Jakarta Server Pages spec supports the notion of page events that actions could register to. On a _pageExit_ event, an <c:import> tag would then simply release its resources if it had not already been done, removing the requirement for nested visibility.]. Implementations that use the
tag-extension API will likely need to implement _TryCatchFinally_ with
their `<c:import>` tag handlers and close the exported Reader in
_doFinally()_.

It is also illegal to use nested `<c:param>`
tags with syntax 2. Since the exposed _Reader_ must be immediately
available to the action's body, the connection to the resource must be
established within the start element of the action. It is therefore
impossible for nested `<c:param>` actions to modify the URL of the
resource to be accessed, thus their illegality with syntax 2. In such a
situation, `<c:url>` may be used to build a URL with query string
parametersfootnote:[It is however important to note that using the output of <c:url> as the _url_ attribute value of <c:import> won't work for context relative URLs (URLs that start with a '/'). That's because in those cases <c:url> prepends the context path to the URL value.]. `<c:import>` will remove any session id
information if necessary (see <<c:url>>).

.*Character Encoding*

`<c:import>` exposes a _String_ or _Reader_
object, both of which are sequences of text characters. It is possible
to specify the character encoding of the input resource via the
_charEncoding_ attribute. The values supported for _charEncoding_ are
the same as the ones supported by the constructor of the Java class
_InputStreamReader_.

If the character encoding is not specified,
the following rules apply:

* If _URLConnection.getContentType()_ has a
non-null result, the character set is retrieved from
_URLConnection.getContentType()_ by parsing this method's result
according to RFC 2045 (section 5.1).

* If this method's result does not include a
character set, or if the character set causes
_InputStreamReader(InputStream in, String charsetName)_ to throw an
_UnsupportedEncodingException_, then use ISO-8859-1 (which is the
default value of _charset_ for the _contentType_ attribute of the Jakarta Server Pages
_page_ directive).

Note that the _charEncoding_ attribute should
normally only be required when accessing absolute URL resources where
the protocol is not HTTP, and where the encoding is not ISO-8859-1.

Also, when dealing with relative URLs and the
HTTP protocol, if the target resource declares a content encoding but
proceeds to write a character invalid in that encoding, the treatment of
that character is undefined.

.*Relative and Absolute URLs*

The exact semantics of the `<c:import>` tag
depends on what type of URL is being accessed.

*_Relative URL – same context_*

This is processed in the exact same way as
the include action of the Jakarta Server Pages specification (`<jsp:include>`). The
resource belongs to the same web application as the including page and
it is specified as a relative URL.

As specified in the Jakarta Server Pages specification, a
relative URL may either be a context-relative path, or a page-relative
path. A context-relative path is a path that starts with a "/". It is to
be interpreted as relative to the application to which the Jakarta Server Pages page
belongs. A page-relative path is a path that does not start with a "/".
It is to be interpreted as relative to the current Jakarta Server Pages page, as defined
by the rules of inclusion of the `<jsp:include>` action in the Jakarta Server Pages
specification.

The semantics of importing a resource
specified with a relative URL in the same context are the same as an
include performed by a _RequestDispatcher_ as defined in the Servlet
specification. This means that the whole environment of the importing
page is available to the target resource (including request and session
attributes, as well as request parameters of the importing page).

*_Relative URL – foreign context_*

The resource belongs to a foreign context
(web application) hosted under the same container as the importing page.
The context name for the resource is specified via attribute _context_.

The relative URL must be context-relative
(i.e. must start with a "/") since the including page does not belong to
the same context. Similarly, the context name must also start with a
"/".

The semantics of importing a resource
specified with a relative URL in a foreign context are the same as an
include performed by a _RequestDispatcher_ on a foreign context as
defined in the Servlet specification. This means that only the request
environment of the importing page is available to the target resource.

It is important to note that importing
resources in foreign contexts may not work in all containers. A security
conscious environment may not allow access to foreign contexts. As a
workaround, a foreign context resource can also be accessed using an
absolute URL. However, it is more efficient to use a relative URL
because the resource is then accessed using _RequestDispatcher_ defined
by the Servlet API.

*_Relative URL – query parameter aggregation rules_*

The query parameter aggregation rules work
the same way they do with `<jsp:include>`; the original parameters are
augmented with the new parameters, with new values taking precedence
over existing values when applicable. The scope of the new parameters is
the import call; the new parameters (and values) will not apply after
the import. The behavior is therefore the same as the one defined for
the _include()_ method of _RequestDispatcher_ in the Servlet
specification.

*_Absolute URL_*

Absolute URLs are retrieved as defined by the
_java.net.URL_ and _java.net.URLConnection_ classes. The `<c:import>`
action therefore supports at a minimum the protocols offered in the Java SE
1.2 platform for absolute URLs. More protocols can be available to a web
application, but this will depend on the the class libraries made
available to the web application by the platform the container runs on.

When using an absolute URL to import a
resource, none of the current execution environment (e.g. request and
session attributes) is made available to the target resource, even if
that absolute URL resolves to the same host and context path. Therefore,
the request parameters of the importing page are not propagated to the
target absolute URL.

When importing an external resource using the
HTTP protocol, `<c:import>` behaves according to the semantics of a GET
request sent via the _java.net.HttpURLConnection_ class, with
_setFollowRedirects_ set to true.

<<<

[[c:url]]
=== <c:url>

Builds a URL with the proper rewriting rules
applied.

.*Syntax*

_Syntax 1: Without body content_

[literal, subs="+quotes, +attributes"]
<c:url value="value" [context="context"]
        [var="varName"] {blank}[scope="{[underline]#page#|request|session|application}"]/>

_Syntax 2: With body content to specify
query string parameters_

[literal, subs="+quotes, +attributes"]
<c:url value="value" [context="context"]
        [var="varName"] {blank}[scope="{[underline]#page#|request|session|application}"]>
    <c:param> subtags
</c:url>

.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content, then the action trims it and processes it further.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _value_ | _true_
| _String_ |URL to
be processed.

| _context_ |
_true_ | _String_
|Name of the context when specifying a
relative URL resource that belongs to a foreign context.

| _var_ | _false_
| _String_ |Name
of the exported scoped variable for the processed url. The type of the
scoped variable is _String_.

| _scope_ |
_false_ | _String_
|Scope for var.
|===

.*Description*

`<c:url>` processes a URL and rewrites it if
necessary. Only relative URLs are rewritten. Absolute URLs are not
rewritten to prevent situations where an external URL could be rewritten
and expose the session ID. A consequence is that if a page author wants
session tracking, only relative URLs must be used with `<c:url>` to link
to local resources.

The rewriting must be performed by calling
method _encodeURL()_ of the Servlet API.

If the URL contains characters that should be
encoded (e.g. space), it is the user's responsibility to encode them.

The URL must be either an absolute URL
starting with a scheme (e.g. "http://server/context/page.jsp") or a
relative URL as defined by Jakarta Server Pages in JSP.2.2.1 "Relative URL
Specification". As a consequence, an implementation must prepend the
context path to a URL that starts with a slash (e.g. "/page2.jsp") so
that such URLs can be properly interpreted by a client browser.

Specifying a URL in a foreign context is
possible through the _context_ attribute. The URL specified must must
start with a / (since this is a context-relative URL). The context name
must also start with a / (since this is a standard way to identify a
context).

Because the URL built by this action may
include session information as a path parameter, it may fail if used
with _RequestDispatcher_ of the Servlet API. The consumer of the
rewritten URL should therefore remove the session ID information prior
to calling _RequestDispatcher_. This situation is properly handled in
`<c:import>`.

By default, the result of the URL processing
is written to the current _JspWriter_. It is also possible to export
the result as a Jakarta Server Pages scoped variable defined via the _var_ and _scope_
attributes.

`<c:param>` subtags can also be specified
within the body of `<c:url>` for adding to the URL query string
parameters, which will be properly encoded if necessary.

<<<

=== <c:redirect>

Sends an HTTP redirect to the client.

.*Syntax*

_Syntax 1: Without body content_

....
<c:redirect url="value" [context="context"]/>
....

_Syntax 2: With body content to specify
query string parameters_

....
<c:redirect url="value" [context="context"]>
    <c:param> subtags
</c:redirect>
....

.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content, then the action trims it and processes it further.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _url_ | _true_
| _String_ |The
URL of the resource to redirect to.

| _context_ |
_true_ | _String_
|Name of the context when redirecting to a
relative URL resource that belongs to a foreign context.
|===

.*Description*

This action sends an HTTP redirect response
to the client and aborts the processing of the page by returning
_SKIP_PAGE_ from _doEndTag()_.

The URL must be either an absolute URL
starting with a scheme (e.g. "http://server/context/page.jsp") or a
relative URL as defined by Jakarta Server Pages in JSP.2.2.1 "Relative URL
Specification". As a consequence, an implementation must prepend the
context path to a URL that starts with a slash (e.g. "/page2.jsp") if
the behavior is implemented using the
_HttpServletResponse.sendRedirect()_ method.

Redirecting to a resource in a foreign
context is possible through the _context_ attribute. The URL specified
must must start with a "/" (since this is a context-relative URL). The
context name must also start with a "/" (since this is a standard way to
identify a context).

`<c:redirect>` follows the same rewriting rules
as defined for `<c:url>`.

<<<

=== <c:param>

Adds request parameters to a URL. Nested
action of `<c:import>`, `<c:url>`, `<c:redirect>`.

.*Syntax*


_Syntax 1: Parameter value specified in
attribute "value"_

....
<c:param name="name" value="value"/>
....

_Syntax 2: Parameter value specified in the
body content_

....
<c:param name="name">
    parameter value
</c:param>
....

.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content, then the action trims it and processes it further.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _name_ | _true_
| _String_ |Name
of the query string parameter.

| _value_ | _true_
| _String_ |Value
of the parameter.
|===

.*Null & Error Handling*

* If _name_ is null or empty, no action is
performed. It is not an error.

* If _value_ is null, it is processed as an
empty value.

.*Description*

Nested action of `<c:import>`, `<c:url>`,
`<c:redirect>` to add request parameters to a URL. `<c:param>` also URL
encodes both _name_ and _value_.

One might argue that this is redundant given
that a URL can be constructed to directly specify the query string
parameters. For example:

....
<c:import url="/exec/doIt">
    <c:param name="action" value="register"/>
</c:import>
....

is the same as:

....
<c:import url="/exec/doIt?action=register"/>
....

It is indeed redundant, but is consistent
with `<jsp:include>`, which supports nested `<jsp:param>` sub-elements.
Moreover, it has been designed such that the attributes _name_ and
_value_ are automatically URL encoded.


== Internationalization (i18n) Actions: I18n-capable formatting tag library

With the explosion of application development
based on web technologies, and the deployment of such applications on
the Internet, applications must be able to adapt to the languages and
formatting conventions of their clients. This means that page authors
must be able to tailor page content according to the client's language
and cultural formatting conventions. For example, the number 345987.246
should be formatted as 345 987,246 for France, 345.987,246 for Germany,
and 345,987.246 for the U.S.

The process of designing an application (or
page content) so that it can be adapted to various languages and regions
without requiring any engineering changes is known as
internationalization, or i18n for short. Once a web application has been
internationalized, it can be adapted for a number of regions or
languages by adding locale-specific components and text. This process is
known as localization.

There are two approaches to
internationalizing a web application:

* Provide a version of the Jakarta Server Pages in each of
the target locales and have a controller servlet dispatch the request to
the appropriate page (depending on the requested locale). This approach
is useful if large amounts of data on a page or an entire web
application need to be internationalized.

* Isolate any locale-sensitive data on a page
(such as error messages, string literals, or button labels) into
resource bundles, and access the data via i18n actions, so that the
corresponding translated message is fetched automatically and inserted
into the page.

The Jakarta Standard Tag Library i18n-capable formatting actions
support either approach: They assist page authors with creating
internationalized page content that can be localized into any locale
available in the Jakarta Server Pages container (this addresses the second approach), and
allow various data elements such as numbers, currencies, dates and times
to be formatted and parsed in a locale-sensitive or customized manner
(this may be used in either approach).

The Jakarta Standard Tag Library's i18n actions are covered in this
chapter. The formatting actions are covered in
<<Formatting Actions: I18n-capable formatting tag library>>.

=== Overview

There are three key concepts associated with
internationalization: locale, resource bundle, and basename.

A locale represents a specific geographical,
political, or cultural region. A locale is identified by a language
code, along with an optional country codefootnote:[A variant code may also be specified, although rarely used.].

* Language code +
The language code is the lower-case
two-letter code as defined by ISO-639 (e.g. "ca" for Catalan, "zh" for
Chinese). The full list of these codes can be found at a number of
sites, such as: +
http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt

* Country code +
The country code is the upper-case two-letter
code as defined by ISO-3166 (e.g. "IT" for Italy, "CR" for Costa Rica).
The full list of these codes can be found at a number of sites, such
as: +
http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html.

Note that the semantics of locales in the Jakarta Standard Tag Library
are the same as the ones defined by the class _java.util.Locale_. A
consequence of this is that, as of Java SE 1.4, new language codes defined
in ISO 639 (e.g. _he_, _yi_, _id_) will be returned as the old codes
(e.g. _iw_, _ji_, _in_). See the documentation of the
_java.util.Locale_ class for more details.

A resource bundle contains locale-specific
objects. Each message in a resource bundle is associated with a key.
Since the set of messages contained in a resource bundle can be
localized for many locales, the resource bundles that translate the same
set of messages are identified by the same basename. A specific resource
bundle is therefore uniquely identified by combining its basename with a
locale.

For instance, a web application could define
the registration resource bundles with basename _Registration_ to
contain the messages associated with the registration portion of the
application. Assuming that French and English are the only languages
supported by the application, there will be two resource bundles:
_Registration_fr_ (French language) and _Registration_en_ (English
language). Depending on the locale associated with the client request,
the key "greeting" could be mapped to the message "Bonjour" (French) or
"Hello" (English).

==== <fmt:message>

It is possible to internationalize the Jakarta Server Pages of a web application simply by using the `<fmt:message>` action as
shown below:

....
<fmt:message key="greeting"/>
....

In this case, `<fmt:message>` leverages the
default i18n localization context, making it extremely simple for a page
author to internationalize Jakarta Server Pages.

`<fmt:message>` also supports compound
messages, i.e. messages that contain one or more variables. Parameter
values for these variables may be supplied via one or more `<fmt:param>`
subtags (one for each parameter value). This procedure is referred to as
parametric replacement.

....
<fmt:message key="athletesRegistered">
    <fmt:param>
        <fmt:formatNumber value="${athletesCount}"/>
    </fmt:param>
</fmt:message>
....

Depending on the locale, this example could
print the following messages:

....
 french: Il y a 10 582 athletes enregistres.
english: There are 10,582 athletes registered.
....

=== I18n Localization Context

I18n actions use an i18n localization context
to localize their data. An i18n localization context contains two pieces
of information: a resource bundle and the locale for which the resource
bundle was found.

An i18n action determine its i18n
localization context in one of several ways, which are described in
order of precedence:

* `<fmt:message>` _bundle_ attribute +
If attribute _bundle_ is specified in `<fmt:message>`, the i18n localization context associated with it is used for localization.

* `<fmt:bundle>` action +
If `<fmt:message>` actions are nested inside a
`<fmt:bundle>` action, the i18n localization context of the enclosing
`<fmt:bundle>` action is used for localization. The `<fmt:bundle>` action
determines the resource bundle of its i18n localization context
according to the resource bundle determination algorithm in
<<Determinining the Resource Bundle for an i18n Localization Context>>, using the basename attribute as the
resource bundle basename.

* I18n default localization context +
The i18n localization context whose resource
bundle is to be used for localization is specified via the
_jakarta.servlet.jsp.jstl.fmt.localizationContext_ configuration setting
(see <<Internationalization_Actions_I18n_Localization_Context>>). If
the configuration setting is of type _jakarta.servlet.jsp.jstl.fmt.LocalizationContext_ its resource bundle
component is used for localization. Otherwise, the configuration setting
is of type _String_, and the action establishes its own i18n
localization context whose resource bundle component is determined
according to the resource bundle determination algorithm in
<<Determinining the Resource Bundle for an i18n Localization Context>>, using the configuration setting as the
resource bundle basename.

The example below shows how the various
localization contexts can be established to define the resource bundle
used for localization.

....
<%-- Use configuration setting --%>
<fmt:message key="Welcome" />

<fmt:setBundle basename="Errors" var="errorBundle" />
<fmt:bundle basename="Greetings">
    <%-- Localization context established by
         parent <fmt:bundle> tag --%>
    <fmt:message key="Welcome" />
    <%-- Localization context established by attribute bundle --%>
    <fmt:message key="WrongPassword" bundle="${errorBundle}" />
</fmt:bundle>
....

==== Preferred Locales

If the resource bundle of an i18n
localization context needs to be determined, it is retrieved from the
web application's resources according to the algorithm described in
Section <<Determinining the Resource Bundle for an i18n Localization Context>>. This algorithm requires two pieces of information:
the basename of the resource bundle (as described in the previous
section) and the preferred locales.

The method for setting the preferred locales
is characterized as either application-based or browser-based.

Application-based locale setting has priority
over browser-based locale setting. In this mode, the locale is set via
the _jakarta.servlet.jsp.jstl.fmt.locale_ configuration setting (see
<<Locale>>). Setting the locale this way
is useful in situations where an application lets its users pick their
preferred locale and then sets the scoped variable accordingly. This may
also be useful in the case where a client's preferred locale is
retrieved from a database and installed for the page using the
`<fmt:setLocale>` action.

The `<fmt:setLocale>` action may be used to set
the _jakarta.servlet.jsp.jstl.fmt.locale_ configuration variable as
follows:

....
<fmt:setLocale value="en_US" />
....

In the browser-based locale setting, the
client determines via its browser settings which locale(s) should be
used by the web application. The action retrieves the client's locale
preferences by calling _ServletRequest.getLocales()_ on the incoming
request. This returns a list of the locales (in order of preference)
that the client wants to use.

Whether application- or browser-based locale
setting is used, an ordered list of preferred locales is fed into the
algorithm described in section <<Determinining the Resource Bundle for an i18n Localization Context>> to
determine the resource bundle for an i18n localization context.

=== Determinining the Resource Bundle for an i18n Localization Context

Given a basename and an ordered set of
preferred locales, the resource bundle for an i18n localization context
is determined according to the algorithm described in this section.

Tthis algorithm is also exposed as a general
convenience method in the _jakarta.servlet.jsp.jstl.fmt.LocaleSupport_ class so that it may be used by
any tag handler implementation that needs to produce localized messages.
For example, this is useful for exception messages that are intended
directly for user consumption on an error page.

==== Resource Bundle Lookup

Localization in the Jakarta Standard Tag Library is based on the same
mechanisms offered in the Java SE platform. Resource bundles contain
locale-specific objects, and when an i18n action requires a
locale-specific resource, it simply loads it from the appropriate
resource bundle.

The algorithm of
<<Resource Bundle Determination Algorithm>> describes how the proper resource bundle is determined. This
algorithm calls for a resource bundle lookup, where an attempt is made
at fetching a resource bundle associated with a specific basename and
locale.

The Jakarta Standard Tag Library leverages the semantics of the
java.util.ResourceBundle method
....
getBundle(String basename, java.util.Locale locale)
....
for resource bundle lookup, with one important modification.

As stated in the documentation for
_ResourceBundle_, a resource bundle lookup searches for classes and
properties files with various suffixes on the basis of:

. The specified locale

. The current default locale as returned by
_Locale.getDefault()_

. The root resource bundle (basename)

In the Jakarta Standard Tag Library, the search is limited to the first
level; i.e. the specified locale. Steps 2 and 3 are removed so that
other locales may be considered before applying the Jakarta Standard Tag Library fallback
mechanism described in <<Resource Bundle Determination Algorithm>>. Only if no fallback mechanism exists, or the
fallback mechanism fails to determine a resource bundle, is the root
resource bundle considered.

Resource bundles are therefore searched in
the following order:

basename + "_" + language + "_" + country + "_" + variant +
basename + "_" + language + "_" + country +
basename + "_" + language

==== Resource Bundle Determination Algorithm

Notes:

* When there are multiple preferred locales,
they are processed in the order they were returned by
_ServletRequest.getLocales()_.

* The algorithm stops as soon as a resource
bundle has been selected for the localization context.

Step 1: Find a match within the ordered set
of preferred locales

A resource bundle lookup (see <<Resource Bundle Lookup>>) is performed
for each one of the preferred locales until a match is found. If a match
is found, the locale that led to the match and the matched resource
bundle are stored in the i18n localization context.

Step 2: Find a match with the fallback locale

A resource bundle lookup (see
<<Resource Bundle Lookup>>) is performed
for the fallback locale specified in the
_jakarta.servlet.jsp.jstl.fmt.fallbackLocale_ configuration setting. If a
match is found, the fallback locale and the matched resource bundle are
stored in the i18n localization context.

If no match is found following the above two
steps, an attempt is made to load the root resource bundle with the
given basename. If such a resource bundle exists, it is used as the
resource bundle of an i18n localization context that does not have any
locale. Otherwise, the established i18n localization context contains
neither a resource bundle nor a locale. It is then up to the i18n action
relying on this i18n localization context for the localization of its
data to take a proper corrective action.

It is important to note that this algorithm
gives higher priority to a language match over an exact match that would
have occurred further down the list of preferred locales. For example,
if the browser-based locale settings are "en" and "fr_CA", with resource
bundles "Messages_en" and "Messages_fr_CA", the Messages_en bundle will
be selected as the resource bundle for the localization context.

The definition of a fallback locale along
with its associated resource bundles is the only portable way a web
application can ensure the proper localization of all its
internationalized pages. The algorithm of this section never considers
the default locale associated with the Java runtime of the container
because this would result in a non-portable behavior.

The behavior is implementation-specific if
the set of available resource bundles changes during execution of the
page. Implementations may thus cache whatever information they deem
necessary to improve the performance of the algorithm presented in this
section.

==== Examples

The following examples demonstrate how the
resource bundle is determined for an i18n localization context.

.*Example 1*

[underline]#Settings# +
Basename: _Resources_ +
Ordered preferred locales: _en_GB, fr_CA_ +
Fallback locale: _fr_CA_ +
Resource bundles: _Resources_en, Resources_fr_CA_

[underline]#Algorithm Trace# +
Step 1: Find a match within the ordered set of preferred locales +
{nbsp}{nbsp}{nbsp}{nbsp} _en_GB_ match with _Resources_en_

[underline]#Result# +
Resource bundle selected: _Resources_en_ +
Locale: _en_GB_

.*Example 2*

[underline]#Settings# +
Basename: _Resources_ +
Ordered preferred locales: _de, fr_ +
Fallback locale: _en_ +
Resource bundles: _Resources_en_ +

[underline]#Algorithm Trace# +
Step 1: Find a match within the ordered set of preferred locales +
{nbsp}{nbsp}{nbsp}{nbsp} _de_ no match +
{nbsp}{nbsp}{nbsp}{nbsp} _fr_ no match


Step 2: Find a match with the fallback locale +
{nbsp}{nbsp}{nbsp}{nbsp} _en_ exact match with _Resources_en_

[underline]#Result# +
Resource bundle selected: _Resources_en_ +
Locale: _en_

.*Example 3*

[underline]#Settings# +
Basename: _Resources_ +
Ordered preferred locales: _ja, en_GB, en_US, en_CA, fr_ +
Fallback locale: _en_ +
Resource bundles: _Resources_en, Resources_fr, Resources_en_US_

[underline]#Algorithm Trace# +
Step 1: Find a match within the ordered set of preferred locales +
{nbsp}{nbsp}{nbsp}{nbsp} _ja_ no match +
{nbsp}{nbsp}{nbsp}{nbsp} _en_GB_ match with _Resources_en_

[underline]#Result#

Resource bundle selected: _Resources_en_ +
Locale: _en_GB_

.*Example 4*

[underline]#Settings#
Basename: _Resources_ +
Ordered preferred locales: _fr, sv_ +
Fallback locale: _en_ +
Resource bundles: _Resources_fr_CA, Resources_sv, Resources_en_ +

[underline]#Algorithm Trace#

Step 1: Find a match within the ordered set of preferred locales +
{nbsp}{nbsp}{nbsp}{nbsp} _fr_ no match +
{nbsp}{nbsp}{nbsp}{nbsp} _sv_ match with _Resources_sv_

[underline]#Result# +
Resource bundle selected: _Resources_sv_ +
Locale: _sv_

This example shows that whenever possible, a
resource bundle for a specific language and country ( _Resources_fr_CA_
) should be backed by a resource bundle covering just the language (
_Resources_fr_). If the country-specific differences of a language are
too significant for there to be a language-only resource bundle, it is
expected that clients will specify both a language and a country as
their preferred language, in which case an exact resource bundle match
will be found.


=== Response Encoding

Any i18n action that establishes a
localization context is responsible for setting the response's locale of
its page, unless the localization context that was established does not
have any locale. This is done by calling method
_ServletResponse.setLocale()_ with the locale of the localization
context. Unless a response character encoding has been explicitly
defined by other Jakarta Server Pages elements (or by direct calls to the Servlet API),
calling _setLocale()_ also sets the character encoding for the response
(see the Jakarta Server Pages and Servlet specifications for details).

This assumes that the response is buffered
with a big enough buffer size, since _ServletResponse.setLocale()_ must
be called before _ServletResponse.getWriter()_ in order for the
specified locale to affect the construction of the writer.

More specifically, the response's
_setLocale()_ method is always called by the `<fmt:setLocale>` action (see <<fmt:setLocale>>). In addition, it is
called by the following actions:

* Any `<fmt:bundle>` (see <<fmt:bundle>>) and `<fmt:setBundle>` (see
<<fmt:setBundle>>) action.

* Any `<fmt:message>` action that establishes an
i18n localization context

* Any formatting action that establishes a
formatting locale on its own (see <<Establishing a Formatting Locale>>).

After an action has called
_ServletResponse.setLocale()_, if a session exists and has not been
invalidated, it must determine the character encoding associated with
the response locale (by calling _ServletResponse.getCharacterEncoding()_
) and store it in the scoped variable
_jakarta.servlet.jsp.jstl.fmt.request.charset_ in session scope. This
attribute may be used by the `<fmt:requestEncoding>` action (see
<<fmt:requestEncoding>>) in a page
invoked by a form included in the response to set the request charset to
the same as the response charset. This makes it possible for the
container to decode the form parameter values properly, since browsers
typically encode form field values using the response's charset.

The rules related to the setting of an HTTP
response character encoding, Content-Language header, and Content-Type
header are clearly defined in the Servlet specification. To avoid any
ambiguity, the Jakarta Standard Tag Library and Jakarta Server Pages specifications define behavior related to a
response's locale and character encoding exclusively in terms of Servlet
API calls.

It is therefore important to note that, as
defined in the Servlet spec, a call to _ServletResponse.setLocale()_
modifies the character encoding of the response only if it has not
already been set explicitely by calls to
_ServletResponse.setContentType()_ (with CHARSET specified) or
_ServletResponse.setCharacterEncoding()_.

Page authors should consult the Jakarta Server Pages
specification to understand how page directives related to locale and
character encoding setting translate into Servlet API calls, and how
they impact the final response settings.

<<<

[[fmt:setLocale]]
=== <fmt:setLocale>

Stores the specified locale in the
_jakarta.servlet.jsp.jstl.fmt.locale_ configuration variable.

.*Syntax*

[literal, subs="+quotes, +attributes"]
<fmt:setLocale value="locale"
            [variant="variant"]
            {blank}[scope="{[underline]#page#|request|session|application}"]/>

.*Body Content*

Empty.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _value_ | _true_
a|
_String or_

java.util.Locale

|A _String_ value is interpreted as the
printable representation of a locale, which must contain a two-letter
(lower-case) language code (as defined by ISO-639), and may contain a
two-letter (upper-case) country code (as defined by ISO-3166). Language
and country codes must be separated by hyphen ('-') or underscore ('_').

| _variant_ |
_true_ | _String_ |
Vendor- or browser-specific variant.

See the _java.util.Locale_ Javadocs for more information on variants.

| _scope_ |
_false_ | _String_
|Scope of the locale configuration variable.
|===

.*Null & Error Handling*

* If _value_ is null or empty, use the runtime
default locale.

.*Description*

The `<fmt:setLocale>` action stores the locale
specified by the _value_ attribute in the
_jakarta.servlet.jsp.jstl.fmt.locale_ configuration variable in the scope
given by the _scope_ attribute. If _value_ is of type _java.util.Locale_
, _variant_ is ignored.


As a result of using this action,
browser-based locale setting capabilities are disabled. This means that
if this action is used, it should be declared at the beginning of a
page, before any other i18n-capable formatting actions.

<<<

[[fmt:bundle]]
=== <fmt:bundle>

Creates an i18n localization context to be
used by its body content.

.*Syntax*
....
<fmt:bundle basename="basename"
            [prefix="prefix"]>
    body content
</fmt:bundle>
....

.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content and then writes it to the current _JspWriter_. The action
ignores the body content.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _basename_ |
_true_ | _String_
|Resource bundle base name. This is the
bundle's fully-qualified resource name, which has the same form as a
fully-qualified class name, that is, it uses "." as the package
component separator and does not have any file type (such as ".class" or
".properties") suffix.

|prefix | _true_
|String |Prefix to
be prepended to the value of the message key of any nested `<fmt:message>`
action.
|===

.*Null & Error Handling*

* If _basename_ is null or empty, or a resource
bundle cannot be found, the _null_ resource bundle is stored in the i18n
localization context.

.*Description*

The `<fmt:bundle>` action creates an i18n
localization context and loads its resource bundle into that context.
The name of the resource bundle is specified with the _basename_
attribute.

The specific resource bundle that is loaded
is determined according to the algorithm presented in
<<Resource Bundle Determination Algorithm>>.

The scope of the i18n localization context is
limited to the action's body content.

The _prefix_ attribute is provided as a
convenience for very long message key names. Its value is prepended to
the value of the message _key_ of any nested `<fmt:message>` actions.

For example, using the _prefix_ attribute,
the key names in:

....
<fmt:bundle basename="Labels">
    <fmt:message key="com.acme.labels.firstName"/>
    <fmt:message key="com.acme.labels.lastName"/>
</fmt:bundle>
....

may be abbreviated to:

....
<fmt:bundle basename="Labels" prefix="com.acme.labels.">
    <fmt:message key="firstName"/>
    <fmt:message key="lastName"/>
</fmt:bundle>
....

<<<

[[fmt:setBundle]]
=== <fmt:setBundle>

Creates an i18n localization context and
stores it in the scoped variable or the
_jakarta.servlet.jsp.jstl.fmt.localizationContext_ configuration variable.

.*Syntax*

[literal, subs="+quotes, +attributes"]
<fmt:setBundle basename="basename"
               [var="varName"]
               {blank}[scope="{[underline]#page#|request|session|application}"]/>

.*Body Content*

Empty.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _basename_ |
_true_ | _String_
|Resource bundle base name. This is the
bundle's fully-qualified resource name, which has the same form as a
fully-qualified class name, that is, it uses "." as the package
component separator and does not have any file type (such as ".class" or
".properties") suffix.

| _var_ | _false_
| _String_ |Name
of the exported scoped variable which stores the i18n localization
context of type _jakarta.servlet.jsp.jstl.fmt.LocalizationContext_.

| _scope_ |
_false_ | _String_
|Scope of _var_ or the localization context
configuration variable.
|===

.*Null & Error Handling*

* If _basename_ is null or empty, or a resource
bundle cannot be found, the _null_ resource bundle is stored in the i18n
localization context.

.*Description*

The `<fmt:setBundle>` action creates an i18n
localization context and loads its resource bundle into that context.
The name of the resource bundle is specified with the _basename_
attribute.

The specific resource bundle that is loaded
is determined according to the algorithm presented in
<<Resource Bundle Determination Algorithm>>.

The i18n localization context is stored in
the scoped variable whose name is given by _var_. If _var_ is not
specified, it is stored in the
_jakarta.servlet.jsp.jstl.fmt.localizationContext_ configuration variable,
thereby making it the new default i18n localization context in the given
scope.

<<<

[[fmt:message]]
=== <fmt:message>

Looks up a localized message in a resource
bundle.

.*Syntax*
_Syntax 1: without body content_

[literal, subs="+quotes, +attributes"]
<fmt:message key="messageKey"
             [bundle="resourceBundle"]
             [var="varName"]
             {blank}[scope="{[underline]#page#|request|session|application}"]/>

_Syntax 2: with a body to specify message
parameters_

[literal, subs="+quotes, +attributes"]
<fmt:message key="messageKey"
             [bundle="resourceBundle"]
             [var="varName"]
             {blank}[scope="{[underline]#page#|request|session|application}"]>
    <fmt:param> subtags
</fmt:message>

_Syntax 3: with a body to specify key and
optional message parameters_

[literal, subs="+quotes, +attributes"]
<fmt:message [bundle="resourceBundle"]
             [var="varName"]
             {blank}[scope="{[underline]#page#|request|session|application}"]>
    key
    optional <fmt:param> subtags
</fmt:message>

.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content, then the action trims it and processes it further.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _key_ | _true_
| _String_
|Message key to be looked up.

|bundle | _true_
|LocalizationContext
|Localization context in whose resource
bundle the message key is looked up.

| _var_ | _false_
| _String_ |Name
of the exported scoped variable which stores the localized message.

| _scope_ |
_false_ | _String_
|Scope of var.
|===

.*Constraints*

* If _scope_ is specified, _var_ must also be
specified.

.*Null & Error Handling*

* If _key_ is null or empty, the message is
processed as if undefined; that is, an error message of the form
"??????" is produced.

* If the i18n localization context that this
action determines does not have any resource bundle, an error message of
the form "???<key>???" is produced

.*Description*

The `<fmt:message>` action looks up the
localized message corresponding to the given message key.

The message key may be specified via the
_key_ attribute or from the tag's body content. If this action is nested
inside a `<fmt:bundle>` action, and the parent `<fmt:bundle>` action
contains a _prefix_ attribute, the specified prefix is prepended to the
message key.

`<fmt:message>` uses the resource bundle of the
i18n localization context determined according to
<<I18n Localization Context>>.

If the given key is not found in the resource
bundle, or the i18n localization context does not contain any resource
bundle, the result of the lookup is an error message of the form
"???<key>???" (where <key> is the name of the undefined message key).

If the message corresponding to the given key
is compound, that is, contains one or more variables, it may be supplied
with parameter values for these variables via one or more `<fmt:param>`
subtags (one for each parameter value). This procedure is referred to as
parametric replacement. Parametric replacement takes place in the order
of the `<fmt:param>` subtags.

In the presence of one or more `<fmt:param>`
subtags, the message is supplied to the _java.text.MessageFormat_ method
_applyPattern()_, and the values of the `<fmt:param>` tags are collected
in an _Object[]_ and supplied to the _java.text.MessageFormat_ method
_format()_. The locale of the _java.text.MessageFormat_ is set to the
appropriate localization context locale before _applyPattern()_ is
called. If the localization context does not have any locale, the locale
of the _java.text.MessageFormat_ is set to the locale returned by the
formatting locale lookup algorithm of 
<<Establishing a Formatting Locale>>, except that the available formatting
locales are given as the intersection of the number- and date-
formatting locales. If this algorithm does not yield any locale, the
locale of the _java.text.MessageFormat_ is set to the runtime's default
locale.

If the message is compound and no `<fmt:param>`
subtags are specified, it is left unmodified (that is,
_java.text.MessageFormat_ is not used).

The `<fmt:message>` action outputs its result
to the current _JspWriter_ object, unless the _var_ attribute is
specified, in which case the result is stored in the named Jakarta Server Pages
attribute.

<<<

=== <fmt:param>

Supplies a single parameter for parametric
replacement to a containing `<fmt:message>` (see
<<fmt:message>>) action.

.*Syntax*

_Syntax 1: value specified via attribute "value"_
....
<fmt:param value="messageParameter"/>
....

_Syntax 2: value specified via body content_
....
<fmt:param>
    body content
</fmt:param>
....

.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content, then the action trims it and processes it further.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _value_ | _true_
| _Object_
|Argument used for parametric replacement.
|===

.*Constraints*

* Must be nested inside a `<fmt:message>` action.

.*Description*

The `<fmt:param>` action supplies a single
parameter for parametric replacement to the compound message given by
its parent `<fmt:message>` action.

Parametric replacement takes place in the
order of the `<fmt:param>` tags. The semantics of the replacement are
defined as in the class _java.text.MessageFormat_:

the compound message given by the parent
`<fmt:message>` action is used as the argument to the _applyPattern()_
method of a _java.text.MessageFormat_ instance, and the values of the
`<fmt:param>` tags are collected in an _Object[]_ and supplied to that
instance's _format()_ method.

The argument value may be specified via the
_value_ attribute or inline via the tag's body content.

<<<

[[fmt:requestEncoding]]
=== <fmt:requestEncoding>

Sets the request's character encoding.

.*Syntax*
....
<fmt:requestEncoding [value="charsetName"]/>
....

.*Body Content*

Empty.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _value_ | _true_
| _String_ |Name
of character encoding to be applied when decoding request parameters.
|===

.*Description*

The `<fmt:requestEncoding>` action may be used
to set the request's character encoding, in order to be able to
correctly decode request parameter values whose encoding is different
from ISO-8859-1.

This action is needed because most browsers
do not follow the HTTP specification and fail to include a
_Content-Type_ header in their requests.

More specifically, the purpose of the
`<fmt:requestEncoding>` action is to set the request encoding to be the
same as the encoding used for the response containing the form that
invokes this page.

This action calls the
_setCharacterEncoding()_ method on the servlet request with the
character encoding name specified in the _value_ attribute. It must be
used before any parameters are retrieved, either explicitly or through
the use of an Expression Language expression.

If the character encoding of the request
parameters is not known in advance (since the locale and thus character
encoding of the page that generated the form collecting the parameter
values was determined dynamically), the _value_ attribute must not be
specified. In this case, the `<fmt:requestEncoding>` action first checks
if there is a charset defined in the request _Content-Type_ header. If
not, it uses the character encoding from the
_jakarta.servlet.jsp.jstl.fmt.request.charset_ scoped variable which is
searched in session scope. If this scoped variable is not found, the
default character encoding (ISO-8859-1) is used.


=== Configuration Settings

This section describes the i18n-related
configuration settings. Refer to <<Configuration Data>> for more information on how the Jakarta Standard Tag Library processes
configuration data.

==== Locale


[width="100%",cols="50%,50%",]
|===
| _Variable name_
| _jakarta.servlet.jsp.jstl.fmt.locale_

|Java Constant |
_Config.FMT_LOCALE_

|Type |String or
java.util.Locale

|Set by
|<fmt:setLocale>

|Used by
|`<fmt:bundle>`, `<fmt:setBundle>`,
`<fmt:message>`, `<fmt:formatNumber>`, `<fmt:parseNumber>`, `<fmt:formatDate>`,
`<fmt:parseDate>`
|===

Specifies the locale to be used by the
i18n-capable formatting actions, thereby disabling browser-based
locales. A _String_ value is interpreted as defined in action
<fmt:setLocale> (see <<fmt:setLocale>>).

==== Fallback Locale


[width="100%",cols="50%,50%",]
|===
| _Variable name_
| _jakarta.servlet.jsp.jstl.fmt.fallbackLocale_

|Java Constant |
_Config.FMT_FALLBACK_LOCALE_

|Type |String or
java.util.Locale

|Set by |

|Used by
|`<fmt:bundle>`, `<fmt:setBundle>`,
`<fmt:message>`, `<fmt:formatNumber>`, `<fmt:parseNumber>`, `<fmt:formatDate>`,
`<fmt:parseDate>`
|===

Specifies the fallback locale to be used by
the i18n-capable formatting actions if none of the preferred match any
of the available locales. A _String_ value is interpreted as defined in
action `<fmt:setLocale>` (see <<fmt:setLocale>>).

[[Internationalization_Actions_I18n_Localization_Context]]
==== I18n Localization Context
[width="100%",cols="50%,50%",]
|===
| _Variable name_
|
_jakarta.servlet.jsp.jstl.fmt.localizationContext_

|Java Constant |
_Config.FMT_LOCALIZATION_CONTEXT_

|Type |String or
jakarta.servlet.jsp.jstl.fmt.LocalizationContext

|Set by
|`<fmt:setBundle>`

|Used by
|`<fmt:message>`, `<fmt:formatNumber>`,
`<fmt:parseNumber>`, `<fmt:formatDate>`, `<fmt:parseDate>`
|===

Specifies the default i18n localization
context to be used by the i18n-capable formatting actions. A _String_
value is interpreted as a resource bundle basename.



== Formatting Actions: I18n-capable formatting tag library

The Jakarta Standard Tag Library formatting actions allow various
data elements in a Jakarta Server Pages page, such as numbers, dates and times, to be
formatted and parsed in a locale-sensitive or customized manner.


=== Overview

==== Formatting Numbers, Currencies, and Percentages

The <fmt:formatNumber> action allows page
authors to format numbers, currencies, and percentages according to the
client's cultural formatting conventions.

For example, the output of:

....
<fmt:formatNumber value="9876543.21" type="currency"/>
....

varies with the page's locale (given in
parentheses), as follows:

{nbsp}{nbsp}{nbsp}{nbsp} _SFr. 9'876'543.21 (fr_CH)_ +
{nbsp}{nbsp}{nbsp}{nbsp} _$9,876,543.21 (en_US)_

While the previous example uses the default
formatting pattern (for currencies) of the page's locale, it is also
possible to specify a customized formatting pattern. For example, a
pattern of ".000" will cause any numeric value formatted with it to be
represented with 3 fraction digits, adding trailing zeros if necessary,
so that:

....
<fmt:formatNumber value="12.3" pattern=".000"/>
....

will output "12.300".

Likewise, a pattern of #'"+#,#00.0#+"'# specifies
that any numeric value formatted with it will be represented with a
minimum of 2 integer digits, 1 fraction digit, and a maximum of 2
fraction digits, with every 3 integer digits grouped. Applied to
"123456.7891", as in:

....
<fmt:formatNumber value="123456.7891" pattern="#,#00.0#"/>
....

the formatted output will be "123,456.79"
(note that rounding is handled automatically).

The following example formats a numeric value
as a currency, stores it in a scoped variable, parses it back in, and
outputs the parsed result (which is the same as the original numeric
value):

....
<fmt:formatNumber value="123456789" type="currency" var="cur"/>
<fmt:parseNumber value="${cur}" type="currency"/>
....

A similar sequence of actions could have been
used to retrieve a currency-formatted value from a database, parse its
numeric value, perform an arithmetic operation on it, reformat it as a
currency, and store it back to the database.

==== Formatting Dates and Times

The `<fmt:formatDate>` action allows page
authors to format dates and times according to the client's cultural
formatting conventions.

For example, assuming a current date of _Oct 22, 2001_ and a current time of _4:05:53PM_, the following action:

....
<jsp:useBean id="now" class="java.util.Date"/>
<fmt:formatDate value="${now}" timeStyle="long" dateStyle="long"/>
....

will output

_October 22, 2001 4:05:53 PM PDT_

for the U.S. and

_22 octobre 2001 16:05:53 GMT-07:0_

for the French locale.

Page authors may also specify a customized
formatting style for their dates and times. Assuming the same current
date and time as in the above example, this action:

....
<fmt:formatDate value="${now}" pattern="dd.MM.yy"/>_
....

will output

_22.10.01_

for the U.S. locale.

Time information on a page may be tailored to
the preferred time zone of a client. This is useful if the server
hosting the page and its clients reside in different time zones. If time
information is to be formatted or parsed in a time zone different from
that of the Jakart Server Pages container, the `<fmt:formatDate>` and `<fmt:parseDate>`
action may be nested inside a `<fmt:timeZone>` action or supplied with a
_timeZone_ attribute.

In the following example, the current date
and time are formatted in the "GMT+1:00" time zone:

....
<fmt:timeZone value="GMT+1:00">
    <fmt:formatDate value="${now}" type="both" dateStyle="full"
        timeStyle="full"/>
</fmt:timeZone>
....

=== Formatting Locale

A formatting actionfootnote:[Four formatting actions localize their data: <fmt:formatNumber>, <fmt:parseNumber>, <fmt:formatDate>, <fmt:parseDate>.] may
leverage an i18n localization context to determine its formatting locale
or establish a formatting locale on its own, by following these steps:

* <fmt:bundle> action +
If a formatting action is nested inside a
<fmt:bundle> action (see <<fmt:bundle>>), the locale of the i18n localization context of the
enclosing <fmt:bundle> action is used as the formatting locale. The
<fmt:bundle> action determines the resource bundle of its i18n
localization context according to the resource bundle determination
algorithm in 
<<Determinining the Resource Bundle for an i18n Localization Context>>, using the basename attribute
as the resource bundle basename. If the i18n localization context of the
enclosing <fmt:bundle> action does not contain any locale, go to the
next step.

* I18n default localization context +
The default i18n localization context may be
specified via the jakarta.servlet.jsp.jstl.fmt.localizationContext
configuration setting. If such a configuration setting exists, and its
value is of type _LocalizationContext_, its locale is used as the
formatting locale. Otherwise, if the configuration setting is of type
_String_, the formatting action establishes its own i18n localization
context and uses its locale as the formatting locale (in this case, the
resource bundle component of the i18n localization context is determined
according to the resource bundle determination algorithm in
<<Determinining the Resource Bundle for an i18n Localization Context>>, using the configuration setting as the
resource bundle basename). If the i18n localization context determined
in this step does not contain any locale, go to the next step.

* Formatting locale lookup +
The formatting action establishes a locale
according to the algorithm described in
<<Establishing a Formatting Locale>>. This algorithm requires the preferred
locales. The way the preferred locales are set is exactly the same as
with i18n actions and is described in <<Preferred Locales>>.

The following example shows how the various
localization contexts can be established to define the formatting
locale.

....
<jsp:useBean id="now" class="java.util.Date"/>

<%-- Formatting locale lookup --%>
<fmt:formatDate value="${now}" />

<fmt:bundle basename="Greetings">
    <%-- I18n localization context from parent <fmt:bundle> tag --%>
    <fmt:message key="Welcome" />
    <fmt:formatDate value="${now}" />
</fmt:bundle>
....


=== Establishing a Formatting Locale

If a formatting action fails to leverage an
i18n localization context for its formatting locale – either because the
formatting action has no way of referring to an i18n localization
context, or the i18n localization context does not have any locale – it
must establish the formatting locale on its own, given an ordered set of
preferred locales, according to the formatting locale lookup algorithm
described in this section.

==== Locales Available for Formatting Actions

The algorithm described in
<<Formatting Locale Lookup Algorithm>>
compares preferred locales against the set of locales that are available
for a specific formatting action.

The locales available for actions
`<fmt:formatNumber>` and `<fmt:parseNumber>` are determined by a call to
_java.text.NumberFormat.getAvailableLocales()_.

The locales available for `<fmt:formatDate>`
and `<fmt:parseDate>` are determined by a call to
_java.text.DateFormat.getAvailableLocales()_.

==== Locale Lookup

The algorithm of <<Formatting Locale Lookup Algorithm>>
describes how the proper locale is determined. This algorithm calls for
a locale lookup: it attempts to find among the available locales, a
locale that matches the specified one.

The locale lookup is similar to the resource
bundle lookup described in <<Resource Bundle Lookup>>, except that instead of trying to match a resource
bundle, the locale lookup tries to find a match in a list of available
locales. A match of the specified locale against an available locale is
therefore attempted in the following order:

* Language, country, and variant are the same

* Language and country are the same

* Language is the same and the available locale does not have a country

==== Formatting Locale Lookup Algorithm

Notes:

* When there are multiple preferred locales,
they are processed in the order they were returned by a call to
_ServletRequest.getLocales()_.

* The algorithm stops as soon as a locale has
been selected for the localization context.

Step 1: Find a match within the ordered set
of preferred locales

A locale lookup (see <<Locale Lookup>>) is performed for each
one of the preferred locales until a match is found. The first match is
used as the formatting locale.

Step 2: Find a match with the fallback locale

A locale lookup (see
<<Locale Lookup>>) is performed for the
fallback locale specified in the
_jakarta.servlet.jsp.jstl.fmt.fallbackLocale_ configuration setting. If a
match exists, it is used as the formatting locale.

If no match is found after the above two
steps, it is up to the formatting action to take a corrective action.

The result of the formatting locale lookup
algorithm may be cached, so that subsequent formatting actions that need
to establish the formatting locale on their own may leverage it.


=== Time Zone

Time information on a page may be tailored to
the preferred time zone of a client. This is useful if the server
hosting the page and its clients reside in different time zones (page
authors could be advised to always use the "long" time format which
includes the time zone, but that would still require clients to convert
the formatted time into their own time zone).

When formatting time information using the
`<fmt:formatDate>` action (see <<fmt:formatDate>>), or parsing time information
that does not specify a time zone using the `<fmt:parseDate>` action (see <<fmt:parseDate>>), the time zone to use is determined as follows and in this order:

* Use the time zone from the action's _timeZone_ attribute.

* If attribute _timeZone_ is not specified and
the action is nested inside an `<fmt:timeZone>` action, use the time zone
from the enclosing `<fmt:timeZone>` action.

* Use the time zone given by the
_jakarta.servlet.jsp.jstl.fmt.timeZone_ configuration setting.

* Use the Jakarta Server Pages container's time zone.

<<<

[[fmt:timeZone]]
=== <fmt:timeZone>

Specifies the time zone in which time
information is to be formatted or parsed in its body content.

.*Syntax*

....
<fmt:timeZone value="timeZone">
    body content
</fmt:timeZone>
....

.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content and then writes it to the current _JspWriter_. The action
ignores the body content.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _value_ | _true_
a|
_String_ or

java.util.TimeZone

|The time zone. A _String_ value is
interpreted as a time zone ID. This may be one of the time zone IDs
supported by the Java platform (such as "America/Los_Angeles") or a
custom time zone ID (such as "GMT-8"). See _java.util.TimeZone_ for more
information on supported time zone formats.
|===

.*Null & Error Handling*

* If _value_ is null or empty, the GMT timezone
is used.

.*Description*

The `<fmt:timeZone>` action specifies the time
zone in which to format or parse the time information of any nested time
formatting (see <<fmt:formatDate>>) or parsing (see <<fmt:parseDate>>) actions.

If the time zone is given as a string, it is
parsed using _java.util.TimeZone.getTimeZone()_.


=== <fmt:setTimeZone>

Stores the specified time zone in a scoped
variable or the time zone configuration variable.

.*Syntax*

[literal, subs="+quotes, +attributes"]
<fmt:setTimeZone value="timeZone"
                 [var="varName"]
                 {blank}[scope="{[underline]#page#|request|session|application}"]/>

.*Body Content*

Empty.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _value_ | _true_
a|
_String_ or

java.util.TimeZone

|The time zone. A _String_ value is
interpreted as a time zone ID. This may be one of the time zone IDs
supported by the Java platform (such as "America/Los_Angeles") or a
custom time zone ID (such as "GMT-8"). See java.util.TimeZone for more
information on supported time zone formats.

| _var_ | _false_
| _String_ |Name
of the exported scoped variable which stores the time zone of type
_java.util.TimeZone_.

| _scope_ |
_false_ | _String_
|Scope of _var_ or the time zone
configuration variable.
|===

.*Null & Error Handling*

* If _value_ is null or empty, the GMT timezone
is used.

.*Description*

The `<fmt:setTimeZone>` action stores the given
time zone in the scoped variable whose name is given by _var_. If _var_
is not specified, the time zone is stored in the
_jakarta.servlet.jsp.jstl.fmt.timeZone_ configuration variable, thereby
making it the new default time zone in the given scope.

If the time zone is given as a string, it is
parsed using _java.util.TimeZone.getTimeZone()_.

<<<

=== <fmt:formatNumber>

Formats a numeric value in a locale-sensitive
or customized manner as a number, currency, or percentage.

.*Syntax*

_Syntax 1: without a body_

[literal, subs="+quotes, +attributes"]
<fmt:formatNumber value="numericValue"
                  {blank}[type="{[underline]#number#|currency|percent}"]
                  [pattern="customPattern"]
                  [currencyCode="currencyCode"]
                  [currencySymbol="currencySymbol"]
                  {blank}[groupingUsed="{[underline]#true#|false}"]
                  [maxIntegerDigits="maxIntegerDigits"]
                  [minIntegerDigits="minIntegerDigits"]
                  [maxFractionDigits="maxFractionDigits"]
                  [minFractionDigits="minFractionDigits"]
                  [var="varName"]
                  {blank}[scope="{[underline]#page#|request|session|application}"]/>
 
_Syntax 2: with a body to specify the
numeric value to be formatted_

[literal, subs="+quotes, +attributes"]
<fmt:formatNumber {blank}[type="{[underline]#number#|currency|percent}"]
                  [pattern="customPattern"]
                  [currencyCode="currencyCode"]
                  [currencySymbol="currencySymbol"]
                  {blank}[groupingUsed="{[underline]#true#|false}"]
                  [maxIntegerDigits="maxIntegerDigits"]
                  [minIntegerDigits="minIntegerDigits"]
                  [maxFractionDigits="maxFractionDigits"]
                  [minFractionDigits="minFractionDigits"]
                  [var="varName"]
                  {blank}[scope="{[underline]#page#|request|session|application}"]>
    numeric value to be formatted
</fmt:formatNumber>

.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content, then the action trims it and processes it further.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _value_ | _true_
| _String or Number_
|Numeric value to be formatted.

|type | _true_
|String |Specifies
whether the value is to be formatted as number, currency, or percentage.

|pattern | _true_
|String |Custom
formatting pattern.

|currencyCode
|true |String
|ISO 4217 currency code. Applied only when
formatting currencies (i.e. if _type_ is equal to "currency"); ignored
otherwise.

|currencySymbol
|true |String
|Currency symbol. Applied only when
formatting currencies (i.e. if _type_ is equal to "currency"); ignored
otherwise.

|groupingUsed
|true |boolean
|Specifies whether the formatted output will
contain any grouping separators.

|maxIntegerDigits
|true |int
|Maximum number of digits in the integer
portion of the formatted output.

|minIntegerDigits
|true |int
|Minimum number of digits in the integer
portion of the formatted output.

|maxFractionDigits
|true |int
|Maximum number of digits in the fractional
portion of the formatted output.

|minFractionDigits
|true |int
|Minimum number of digits in the fractional
portion of the formatted output.

| _var_ | _false_
| _String_ |Name
of the exported scoped variable which stores the formatted result as a
String.

| _scope_ |
_false_ | _String_
|Scope of var.
|===

.*Constraints*

* If _scope_ is specified, _var_ must also be
specified.

* The value of the _currencyCode_ attribute
must be a valid ISO 4217 currency code.

.*Null & Error Handling*

* If _value_ is null or empty, nothing is
written to the current JspWriter object and the scoped variable is
removed if it is specified (see attributes _var_ and _scope_).

* If this action fails to determine a
formatting locale, it uses _Number.toString()_ as the output format.

* If the attribute _pattern_ is null or empty,
it is ignored.

* If an exception occurs during the parsing of
a string value, it must be caught and rethrown as a _JspException_. The
message of the rethrown _JspException_ must include the string value,
and the caught exception must be provided as the root cause.

.*Description*

The numeric value to be formatted may be
specified via the _value_ attribute; if missing, it is read from the
tag's body content.

The formatting pattern may be specified via
the _pattern_ attribute, or is looked up in a locale-dependent fashion.

A pattern string specified via the _pattern_
attribute must follow the pattern syntax specified by the class
_java.text.DecimalFormat_.

If looked up in a locale-dependent fashion,
the formatting pattern is determined via a combination of the formatting
locale, which is determined according to
<<Formatting Locale>>, and the _type_
attribute. Depending on the value of the _type_ attribute, the given
numeric value is formatted as a number, currency, or percentage. The
locale's default formatting pattern for numbers, currencies, or
percentages is determined by calling the _java.text.NumberFormat_ method
_getNumberInstance_, _getCurrencyInstance_, or _getPercentInstance_,
respectively, with the formatting locale.

The _pattern_ attribute takes precedence over
_type_. In either case, the formatting symbols (such as decimal
separator and grouping separator) are given by the formatting locale.

The (specified or locale-dependent)
formatting pattern may be further fine-tuned using the formatting
options described below.

If the numeric value is given as a string
literal, it is first parsed into a _java.lang.Number_. If the string
does not contain any decimal point, it is parsed using
_java.lang.Long.valueOf()_, or _java.lang.Double.valueOf()_ otherwise.

The formatted result is output to the current
_JspWriter_ object, unless the _var_ attribute is given, in which case
it is stored in the named scoped variable.

*Formatting Options*

The _groupingUsed_ attribute specifies
whether the formatted ouput will contain any grouping separators. See
the _java.text.NumberFormat_ method _setGroupingUsed()_ for more
information.

The minimum and maximum number of digits in
the integer and fractional portions of the formatted output may be given
via the _minIntegerDigits_, _maxIntegerDigits_, _minFractionDigits_,
and _maxFractionDigits_ attributes, respectively. See the
_java.text.NumberFormat_ methods _setMinimumIntegerDigits()_,
_setMaximumIntegerDigits()_, _setMinimumFractionDigits()_, and
_setMaximumFractionDigits()_ for more information.

*Formatting Currencies*

When formatting currencies using the
specified or locale-dependent formatting pattern for currencies, the
currency symbol of the formatting locale is used by default. It can be
overridden by using the _currencySymbol_ or _currencyCode_ attributes,
which specify the currency symbol or currency code, respectively, of the
currency to use.

If both _currencyCode_ and _currencySymbol_
are present, _currencyCode_ takes precedence over _currencySymbol_ if
the _java.util.Currency_ class is defined in the container's runtime
(that is, if the container's runtime is Java SE 1.4 or greater), and
_currencySymbol_ takes precendence otherwise. If only _currencyCode_ is
given, it is used as a currency symbol if _java.util.Currency_ is not
defined.

<<<

=== <fmt:parseNumber>

Parses the string representation of numbers,
currencies, and percentages that were formatted in a locale-sensitive or
customized manner.

.*Syntax*

_Syntax 1: without a body_

[literal, subs="+quotes, +attributes"]
<fmt:parseNumber value="numericValue"
                {blank}[type="{[underline]#number#|currency|percent}"]
                [pattern="customPattern"]
                [parseLocale="parseLocale"]
                {blank}[integerOnly="{true|[underline]#false#}"]
                [var="varName"]
                {blank}[scope="{[underline]#page#|request|session|application}"]/>

_Syntax 2: with a body to specify the
numeric value to be parsed_

[literal, subs="+quotes, +attributes"]
<fmt:parseNumber {blank}[type="{[underline]#number#|currency|percent}"]
                [pattern="customPattern"]
                [parseLocale="parseLocale"]
                {blank}[integerOnly="{true|[underline]#false#}"]
                [var="varName"]
                {blank}[scope="{[underline]#page#|request|session|application}"]>
    numeric value to be parsed
</fmt:parseNumber>


.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content, then the action trims it and processes it further.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _value_ | _true_
| _String_ |String
to be parsed.

|type | _true_
|String |Specifies
whether the string in the _value_ attribute should be parsed as a
number, currency, or percentage.

|pattern | _true_
|String |Custom
formatting pattern that determines how the string in the _value_
attribute is to be parsed.

|parseLocale |
_true_ a|
String or

java.util.Locale

|Locale whose default formatting pattern (for
numbers, currencies, or percentages, respectively) is to be used during
the parse operation, or to which the pattern specified via the _pattern_
attribute (if present) is applied.

|integerOnly |true
|boolean
|Specifies whether just the integer portion
of the given value should be parsed.

| _var_ | _false_
| _String_ |Name
of the exported scoped variable which stores the parsed result (of type
_java.lang.Number_).

| _scope_ |
_false_ | _String_
|Scope of var.
|===

.*Constraints*

* If _scope_ is specified, _var_ must also be
specified.

.*Null & Error Handling*

* If the numeric string to be parsed is null or
empty, the scoped variable defined by attributes _var_ and _scope_ is
removed. This allows "empty" input to be distinguished from "invalid"
input, which causes an exception.

* If _parseLocale_ is null or empty, it is
treated as if it was missing.

* If an exception occurs during the parsing of
the value, it must be caught and rethrown as a _JspException_. The
message of the rethrown _JspException_ must include the value that was
to be parsed, and the caught exception must be provided as the root
cause.

* If this action fails to determine a
formatting locale, it must throw a _JspException_ whose message must
include the value that was to be parsed.

* If the attribute _pattern_ is null or empty,
it is ignored.

.*Description*

The numeric value to be parsed may be
specified via the _value_ attribute; if missing, it is read from the
action's body content.

The parse pattern may be specified via the
_pattern_ attribute, or is looked up in a locale-dependent fashion.

A pattern string specified via the _pattern_
attribute must follow the pattern syntax specified by
_java.text.DecimalFormat_.

If looked up in a locale-dependent fashion,
the parse pattern is determined via a combination of the _type_ and
_parseLocale_ attributes. Depending on the value of the _type_
attribute, the given numeric value is parsed as a number, currency, or
percentage. The parse pattern for numbers, currencies, or percentages is
determined by calling the _java.text.NumberFormat_ method
_getNumberInstance_, _getCurrencyInstance_, or _getPercentInstance_,
respectively, with the locale specified via _parseLocale_. If
_parseLocale_ is missing, the formatting locale, which is obtained
according to <<Formatting Locale>>, is
used as the parse locale.

The _pattern_ attribute takes precedence over
_type_. In either case, the formatting symbols in the pattern (such as
decimal separator and grouping separator) are given by the parse locale.

The _integerOnly_ attribute specifies whether
just the integer portion of the given value should be parsed. See the
_java.text.NumberFormat_ method _setParseIntegerOnly()_ for more
information.

If the _var_ attribute is given, the parse
result (of type _java.lang.Number_) is stored in the named scoped
variable. Otherwise, it is output to the current _JspWriter_ object
using _java.lang.Number.toString()_.

<<<

[[fmt:formatDate]]
=== <fmt:formatDate>

Allows the formatting of dates and times in a
locale-sensitive or customized manner.

.*Syntax*

[literal, subs="+quotes, +attributes"]
<fmt:formatDate value="date"
                {blank}[type="{time|[underline]#date#|both}"]
                {blank}[dateStyle="{[underline]#default#|short|medium|long|full}"]
                {blank}[timeStyle="{[underline]#default#|short|medium|long|full}"]
                [pattern="customPattern"]
                [timeZone="timeZone"]
                [var="varName"]
                {blank}[scope="{[underline]#page#|request|session|application}"]/>

.*Body Content*

Empty.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _value_ | _true_
a|
_java.util._

_Date_

|Date and/or time to be formatted.

|type | _true_
|String |Specifies
whether the time, the date, or both the time and date components of the
given date are to be formatted.

|dateStyle |true
|String
|Predefined formatting style for dates.
Follows the semantics defined in class _java.text.DateFormat_. Applied
only when formatting a date or both a date and time (i.e. if _type_ is
missing or is equal to "date" or "both"); ignored otherwise.

|timeStyle |true
|String
|Predefined formatting style for times.
Follows the semantics defined in class _java.text.DateFormat_. Applied
only when formatting a time or both a date and time (i.e. if _type_ is
equal to "time" or "both"); ignored otherwise.

|pattern | _true_
|String |Custom
formatting style for dates and times.

|timeZone | _true_
a|
String or java.util.

TimeZone

|Time zone in which to represent the
formatted time.

| _var_ | _false_
| _String_ |Name
of the exported scoped variable which stores the formatted result as a
_String_.

| _scope_ |
_false_ | _String_
|Scope of var.
|===

.*Constraints*

* If _scope_ is specified, _var_ must also be
specified.

.*Null & Error Handling*

* If _value_ is null or empty, nothing is
written to the current JspWriter object and the scoped variable is
removed if it is specified (see attributes _var_ and _scope_).

* If _timeZone_ is null or empty, it is handled
as if it was missing.

* If this action fails to determine a
formatting locale, it uses _java.util.Date.toString()_ as the output
format.

.*Description*

Depending on the value of the _type_
attribute, only the time, the date, or both the time and date components
of the date specified via the _value_ attribute or the body content are
formatted, using one of the predefined formatting styles for dates
(specified via the _dateStyle_ attribute) and times (specified via the
_timeStyle_ attribute) of the formatting locale, which is determined
according to <<Formatting Locale>>.

_dateStyle_ and _timeStyle_ support the
semantics defined in _java.text.DateFormat_.

Page authors may also apply a customized
formatting style to their times and dates by specifying the _pattern_
attribute, in which case the _type_, _dateStyle_, and _timeStyle_
attributes are ignored. The specified formatting pattern must use the
pattern syntax specified by _java.text.SimpleDateFormat._

In order to format the current date and time,
a `<jsp:useBean>` action may be used as follows:

....
<jsp:useBean id="now" class="java.util.Date"/>
<fmt:formatDate value="${now}" />
....

If the string representation of a date or
time needs to be formatted, the string must first be parsed into a
_java.util.Date_ using the `<fmt:parseDate>` action, whose parsing result
may then be supplied to the `<fmt:formatDate>` action:

....
<fmt:parseDate value="4/13/02" pattern="M/d/yy" var="parsed"/>
<fmt:formatDate value="${parsed}" dateStyle="full"/>
....

The action's result is output to the current
_JspWriter_ object, unless the _var_ attribute is specified, in which
case it is stored in the named scoped variable.

<<<

[[fmt:parseDate]]
=== <fmt:parseDate>

Parses the string representation of dates and
times that were formatted in a locale-sensitive or customized manner.

.*Syntax*

_Syntax 1: without a body_

[literal, subs="+quotes, +attributes"]
<fmt:parseDate value="dateString"
            {blank}[type="{time|[underline]#date#|both}"]
            {blank}[dateStyle="{[underline]#default#|short|medium|long|full}"]
            {blank}[timeStyle="{[underline]#default#|short|medium|long|full}"]
            [pattern="customPattern"]
            [timeZone="timeZone"]
            [parseLocale="parseLocale"]
            [var="varName"]
            {blank}[scope="{[underline]#page#|request|session|application}"]/>

_Syntax 2: with a body to specify the date
value to be parsed_

[literal, subs="+quotes, +attributes"]
<fmt:parseDate {blank}[type="{time|[underline]#date#|both}"]
            {blank}[dateStyle="{[underline]#default#|short|medium|long|full}"]
            {blank}[timeStyle="{[underline]#default#|short|medium|long|full}"]
            [pattern="customPattern"]
            [timeZone="timeZone"]
            [parseLocale="parseLocale"]
            [var="varName"]
            {blank}[scope="{[underline]#page#|request|session|application}"]>
    date value to be parsed
</fmt:parseDate>

.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content, then the action trims it and processes it further.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _value_ | _true_
| _String_ |Date
string to be parsed.

|type | _true_
|String |Specifies
whether the date string in the _value_ attribute is supposed to contain
a time, a date, or both.

|dateStyle |true
|String
|Predefined formatting style for days which
determines how the date component of the date string is to be parsed.
Applied only when formatting a date or both a date and time (i.e. if
_type_ is missing or is equal to "date" or "both"); ignored otherwise.

|timeStyle |true
|String
|Predefined formatting styles for times which
determines how the time component in the date string is to be parsed.
Applied only when formatting a time or both a date and time (i.e. if
_type_ is equal to "time" or "both"); ignored otherwise.

|pattern | _true_
|String |Custom
formatting pattern which determines how the date string is to be parsed.

|timeZone | _true_
|String or java.util.TimeZone
|Time zone in which to interpret any time
information in the date string.

|parseLocale |
_true_ a|
String or

java.util.Locale

|Locale whose predefined formatting styles
for dates and times are to be used during the parse operation, or to
which the pattern specified via the _pattern_ attribute (if present) is
applied.

| _var_ | _false_
| _String_ |Name
of the exported scoped variable in which the parsing result (of type
_java.util.Date_) is stored.

| _scope_ |
_false_ | _String_
|Scope of var.
|===

.*Constraints*

* If _scope_ is specified, _var_ must also be
specified.

.*Null & Error Handling*

* If the date string to be parsed is null or
empty, the scoped variable defined by _var_ and _scope_ is removed. This
allows "empty" input to be distinguished from "invalid" input, which
causes an exception.

* If _timeZone_ is null or empty, it is treated
as if it was missing.

* If _parseLocale_ is null or empty, it is
treated as if it was missing.

* If an exception occurs during the parsing of
the value, it must be caught and rethrown as a _JspException_. The
message of the rethrown _JspException_ must include the value that was
to be parsed, and the caught exception must be provided as the root
cause.

* If this action fails to determine a
formatting locale, it must throw a _JspException_ whose message must
include the value that was to be parsed.

.*Description*

The date string to be parsed may be specified
via the _value_ attribute or via the tag's body content.

Depending on the value of the _type_
attribute, the given date string is supposed to contain only a time,
only a date, or both. It is parsed according to one of the predefined
formatting styles for dates (specified via the _dateStyle_ attribute)
and times (specified via the _timeStyle_ attribute) of the locale
specified by the _parseLocale_ attribute. If the _parseLocale_ attribute
is missing, the formatting locale, which is determined according to
<<Formatting Locale>>, is used as the
parse locale.

If the given date string uses a different
format, the pattern required to parse it must be specified via the
_pattern_ attribute, which must use the pattern syntax specified by
_java.text.SimpleDateFormat_. In this case, the _type_, _dateStyle_,
and _timeStyle_ attributes are ignored. Parsing is non-lenient, i.e. the
given date string must strictly adhere to the parsing format.

If the given time information does not
specify a time zone, it is interpreted in the time zone determined
according to Section <<Time Zone>>.

If the _var_ attribute is given, the parsing
result (of type _java.util.Date_ ) is stored in the named scoped
variable. Otherwise, it is output to the current _JspWriter_ using the
_java.util.Date_ method _toString()_.


=== Configuration Settings

This section describes the formatting-related
configuration settings. Refer to <<Configuration Data>> for more information on how the Jakarta Standard Tag Library processes
configuration data.

==== TimeZone

[width="100%",cols="50%,50%",]
|===
| _Variable name_
| _jakarta.servlet.jsp.jstl.fmt.timeZone_

|Java Constant |
_Config.FMT_TIMEZONE_

|Type |String or
java.util.TimeZone

|Set by
|`<fmt:setTimeZone>`

|Used by
|`<fmt:formatDate>`, `<fmt:parseDate>`
|===

Specifies the application's default time
zone. A _String_ value is interpreted as defined in action
`<fmt:timeZone>` (see <<fmt:timeZone>>).


== SQL Actions: sql tag library


Many web applications need to access
relational databases as the source of dynamic data for their
presentation layer. While it is generally preferred to have database
operations handled within the business logic of a web application
designed with an MVC architecture, there are situations where page
authors require this capability within their Jakarta Server Pages (e.g.
prototyping/testing, small scale/simple applications, lack of developer
resources).

The Jakarta Standard Tag Library SQL actions provide the basic
capabilities to easily interact with relational databases.

[[SQL_Action_Overview]]
=== Overview

The Jakarta Standard Tag Library SQL actions allow page authors to:

* Perform database queries (_select_)

* Easily access query results

* Perform database updates (_insert_,
_update_, _delete_)

* Group several database operations into a
transaction

==== Data Source

SQL actions operate on a data source, as
defined by the Java class _javax.sql.DataSource_. A _DataSource_ object
provides connections to the physical data source it represents. Within
the context of a _Connection_ retrieved from the _DataSource_, SQL
statements are executed and results are returned.

A data source can be specified explicitly via
the _dataSource_ attribute in SQL actions, or it can be totally
transparent to a page author by taking advantage of the data source
configuration setting (_jakarta.servlet.jsp.jstl.sql.dataSource_).

There are two ways a data source can be
specified as a string.

The first way is through a JNDI relative
path, assuming a container supporting JNDI. For example, with the
absolute JNDI resource path _java:comp/env/jdbc/myDatabase_, the JNDI
relative path to the data source resource would simply be
_jdbc/myDatabase_, given that _java:comp/env_ is the standard JNDI root
for a J2EE application.

The second way is by specifying the
parameters needed by the JDBC _DriverManager_ class, using the following
syntax (see <<sql:setDataSource>> for
details on the JDBC parameters)

{nbsp}{nbsp}{nbsp}{nbsp} _url[,[driver][,[user][,password]]]_

For example,


{nbsp}{nbsp}{nbsp}{nbsp} _jdbc:mysql://localhost/,org.gjt.mm.mysql.Driver_

where the database has been setup for access
without any username or password. If the ',' character occurs in any of
the JDBC parameters, it can be escaped by '\'. The character '\' itself
can be escaped in the same way.

While the JDBC _DriverManager_ class provides
a low cost way to use SQL actions, it is not recommended to use it other
than for prototyping purposes because it does not provide connection
management features one can expect from a properly designed _DataSource_
object.

==== Querying a Database

The most common use of the database actions
is to query a database and display the results of the query.

The following sample code selects all
customers from China from the customers table in the database, orders
them by last name, and finally displays their last name, first name, and
address in an HTML table.

....
<sql:query var="customers" dataSource="${dataSource}">
    SELECT * FROM customers
    WHERE country = 'China'
    ORDER BY lastname
</sql:query>

<table>
    <c:forEach var="row" items="${customers.rows}">
        <tr>
            <td><c:out value="${row.lastName}"/></td>
            <td><c:out value="${row.firstName}"/></td>
            <td><c:out value="${row.address}"/></td>
        </tr>
    </c:forEach>
</table>
....

This next example shows a generic way to
display the results of a query with column names as headers:


....
<table>
    <!-- column headers -->
    <tr>
        <c:forEach var="columnName" items="${result.columnNames}">
            <th><c:out value="${columnName}"/></th>
        </c:forEach>
    </tr>
    <!-- column data -->
    <c:forEach var="row" items="${result.rowsByIndex}">
        <tr>
            <c:forEach var="column" items="${row}">
                <td><c:out value="${column}"/></td>
            </c:forEach>
        </tr>
    </c:forEach>
</table>
....

==== Updating a Database

The `<sql:update>` action updates a database.
To ensure database integrity, several updates to a database may be
grouped into a transaction by nesting the `<sql:update>` actions inside a
`<sql:transaction>` action.

For example, the following code transfers
money between two accounts in one transaction:

....
<sql:transaction dataSource="${dataSource}">
    <sql:update>
        UPDATE account
        SET Balance = Balance - ?
        WHERE accountNo = ?
        <sql:param value="${transferAmount}"/>
        <sql:param value="${accountFrom}"/>
    </sql:update>
    <sql:update>
        UPDATE account
        SET Balance = Balance + ?
        WHERE accountNo = ?
        <sql:param value="${transferAmount}"/>
        <sql:param value="${accountTo}"/>
    </sql:update>
</sql:transaction>
....

==== SQL Statement Parameters

The Jakarta Standard Tag Library database actions support
substituting parameter values for parameter markers ("?") in SQL
statements (as shown in the previous example). This form of parametric
replacement is exposed by the _jakarta.servlet.jsp.jstl.sql.SQLExecutionTag_ interface.

The _SQLExecutionTag_ interface is
implemented by the tag handlers for `<sql:query>` and `<sql:update>`. It is
exposed in order to support custom parameter actions. These custom
actions may retrieve their parameters from any source and process them
before substituting them for a parameter marker in the SQL statement of
the enclosing _SQLExecutionTag_ action.

For example, a GUI front end may have a user
enter a date as three separate fields (year, month, and day), and use
this information in a database query. If the database table being
accessed provides only a single column for the complete date, action
`<acme:dateParam>` could assemble the three separate input parameters into
one and pass it to the _addSQLParameter()_ method of its enclosing
_SQLExecutionTag_ action:

....
<sql:update>
    UPDATE PersonalInfo
    SET BirthDate = ?
    WHERE clientId = ?
    <acme:dateParam year="${year}" month="${month}" day="${day}"/>
    <sql:param value="${clientId}"/>
</sql:update>
....

The Jakarta Standard Tag Library formatting tags may be used to parse
the string representation of dates and numbers into instances of
_java.util.Date_ and _java.lang.Number_, respectively, before supplying
them to an enclosing _SQLExecutionTag_ for parametric replacement:

....
<sql:update sql="${sqlUpdateStmt}" dataSource="${dataSource}">
    <fmt:parseDate var="myDate" value="${someDate}"/>
    <sql:param value="${myDate}"/>
</sql:update>
....


=== Database Access

This section describes the algorithm used by
the SQL actions (`<sql:query>`, `<sql:update>`, `<sql:transaction>`) to access
a database.

* Try to get a reference to a data source as
follows:

** If the attribute _dataSource_ is specified,
use the value specified for that attribute as the data source.

** Otherwise, get the configuration setting
associated with _jakarta.servlet.jsp.jstl.sql.dataSource_ using
_Config.find()_ (see <<Configuration Data>>). Use the value found as the data source if it is not null.

* If a data source is obtained from the
previous step:

** If it is a _DataSource_ object, this is the
data source used by the action to access the database.

** Otherwise, if it is a _String_:

*** Assume this is a JNDI relative path and
retrieve the data source from the container's JNDI naming context by
concatenating the specified relative path to the J2EE defined root (_java:comp/env/_).

*** If the previous step fails (data source not
found), assume the string specifies JDBC parameters using the syntax
described in <<Data Source>> and do as
follows:

*** If driver is specified, ensure it is loaded

*** Access the named URL through the
_DriverManager_ class, using an empty string for _user_ or _password_ if
they are not specified.

** If the previous step fails, throw an
exception.

* Otherwise, throw an exception.

An implementation need not create new objects
each time a SQL action is called and the algorithm above does not yield
a _DataSource_ object directly; i.e when a JNDI path or parameters for
the JDBC _DriverManager_ class are used. It may reuse objects that it
previously created for identical arguments.

It is important to note that actions that
open a connection to a database must close the connection as well as
release any other associated resources (for example, _Statement_,
_PreparedStatement_ and _ResultSet_ objects) by the time the action
completes. This ensures that no connections are left open and that leaks
are avoided when these actions are used with pooling mechanisms.

<<<

[[sql:query]]
=== <sql:query>

Queries a database.

.*Syntax*

_Syntax 1: Without body content_

[literal, subs="+quotes, +attributes"]
<sql:query sql="sqlQuery"
        var="varName" {blank}[scope="{[underline]#page#|request|session|application}"]
        [dataSource="dataSource"]
        [maxRows="maxRows"]
        [startRow="startRow"]/>

_Syntax 2: With a body to specify query
arguments_

[literal, subs="+quotes, +attributes"]
<sql:query sql="sqlQuery"
        var="varName" {blank}[scope="{[underline]#page#|request|session|application}"]
        [dataSource="dataSource"]
        [maxRows="maxRows"]
        [startRow="startRow"]>
    <sql:param> actions
</sql:query>

_Syntax 3: With a body to specify query and
optional query parameters_

[literal, subs="+quotes, +attributes"]
<sql:query var="varName"
        {blank}[scope="{[underline]#page#|request|session|application}"]
        [dataSource="dataSource"]
        [maxRows="maxRows"]
        [startRow="startRow"]>
    query
    optional <sql:param> actions
</sql:query>

.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content, then the action trims it and processes it further.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _sql_ |true
|String |SQL query
statement.

| _dataSource_
|true
|javax.sql.DataSource or String
|Data source associated with the database to
query. A _String_ value represents a relative path to a JNDI resource or
the parameters for the _DriverManager_ class.

| _maxRows_ |true
|int |The maximum
number of rows to be included in the query result. If not specified, or
set to -1, no limit on the maximum number of rows is enforced.

|startRow |true
|int |The returned
_Result_ object includes the rows starting at the specified index. The
first row of the original query result set is at index 0. If not
specified, rows are included starting from the first row at index 0.

|var |false
|String a|
Name of the exported scoped variable for the
query result. The type of the scoped variable is

_jakarta.servlet.jsp.jstl.sql.Result_.

|scope |false
|String |Scope of
_var_.
|===

.*Constraints*

* If _dataSource_ is specified, this
action must not be nested inside a
<sql:transaction>.footnote:[<sql:transaction> is responsible for setting the data source in a transaction.]

* _maxRows_ must be >= -1

.*Null & Error Handling*

* If _dataSource_ is null, a _JspException_ is
thrown.

* If an exception occurs during the execution
of this action, it must be caught and rethrown as a _JspException_. The
message of the rethrown _JspException_ must include the SQL statement,
and the caught exception must be provided as the root cause.

.*Description*

The `<sql:query>` action queries a database and
returns a single result set containing rows of data that it stores in
the scoped variable identified by the _var_ and _scope_ attributes.

If the query produces no results, an empty
_Result_ object (of size zero) is returned.

The SQL query statement may be specified by
the _sql_ attribute or from the action's body content.

The query statement may contain parameter
markers ("?") identifying JDBC _PreparedStatement_ parameters, whose
values must be supplied by nested parameter actions (such as
<<sql:param>>). The
`<sql:query>` action implements the _jakarta.servlet.jsp.jstl.sql.SQLExecutionTag_ interface, allowing parameter values
to be supplied by custom parameter actions.

*maxRows and startRow*

The maximum number of rows to be included in
the query result may be specified by the _maxRows_ attribute (for a
specific `<sql:query>` action) or by the configuration setting
_jakarta.servlet.jsp.jstl.sql.maxRows_ (see
<<Configuration Data>> and
<<SQL_Actions_Configuration_Settings>>). Attribute
_maxRows_ has priority over the configuration setting. A value of -1
means that no limit is enforced on the maximum number of rows.

The _startRow_ attribute may be used to
specify the index of the first row to be included in the returned
_Result_ object. For example, if given a value of 10, the returned
Result object will start with the row located at index 10 (i.e. rows 0
through 9 of the original query result set are skipped). All remaining
rows of the original query result set are included.

If both _startRow_ and _maxRows_ are
specified, a maximum of _startRow + maxRows_ rows are retrieved from the
database. All rows up to _startRow_ are then discarded, and the
remaining rows (from _startRow_ through _startRow + maxRows_) are
included in the result.

When using _startRow_, it is important to
note that the order in which rows are returned is not guaranteed between
RDBMS implementations unless an "order by" clause is specified in the
query.

_maxRows_ and _startRow_ protect against
so-called "runaway queries", allow efficient access to the top rows of
large result sets, and also provide a "poor-man's way" of paging through
a large query result by increasing _startRow_ by _maxRows_ over a
previous page.

*Obtaining and Releasing a Connection*

If `<sql:query>` is nested inside an
`<sql:transaction>` action, the _Connection_ object is obtained from that
parent `<sql:transaction>` which is reponsible for managing access to the
database.

Otherwise, access to the database is
performed according to the algorithm described in
<<Database Access>>. A _Connection_ object
is obtained and released before the action completes.

<<<

=== <sql:update>

Executes an SQL _INSERT_, _UPDATE_, or
_DELETE_ statement. In addition, SQL statements that return nothing,
such as SQL DDL statements, can be executed.

.*Syntax*

_Syntax 1: Without body content_

[literal, subs="+quotes, +attributes"]
<sql:update sql="sqlUpdate"
        [dataSource="dataSource"]
        [var="varName"]
        {blank}[scope="{[underline]#page#|request|session|application}"]/>

_Syntax 2: With a body to specify update
parameters_

[literal, subs="+quotes, +attributes"]
<sql:update sql="sqlUpdate"
        [dataSource="dataSource"]
        [var="varName"]
        {blank}[scope="{[underline]#page#|request|session|application}"]>
    <sql:param> actions
</sql:update>

_Syntax 3: With a body to specify update
statement and optional update parameters_

[literal, subs="+quotes, +attributes"]
<sql:update [dataSource="dataSource"]
        [var="varName"] {blank}[scope="{[underline]#page#|request|session|application}"]>
    update statement
    optional <sql:param> actions
</sql:update>

.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content, then the action trims it and processes it further.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _sql_ |true
|String |SQL
update statement.

|dataSource |true
a|
javax.sql.

DataSource or String

|Data source associated with the database to
update. A String value represents a relative path to a JNDI resource or
the parameters for the JDBC _DriverManager_ class.

| _var_ |false
|String |Name of
the exported scoped variable for the result of the database update. The
type of the scoped variable is _java.lang.Integer_.

| _scope_ |false
|String |Scope of
_var_.
|===

.*Constraints*

* If _scope_ is specified, _var_ must also be
specified.

* If _dataSource_ is specified, this action
must not be nested inside a `<sql:transaction>`.

.*Null & Error Handling*

* If _dataSource_ is null, a _JspException_ is
thrown.

* If an exception occurs during the execution
of this action, it must be caught and rethrown as a _JspException_. The
message of the rethrown _JspException_ must include the SQL statement,
and the caught exception must be provided as the root cause.

.*Description*

The SQL update statement may be specified by
the _sql_ attribute or from the action's body content.

The update statement may contain parameter
markers ("?") identifying JDBC _PreparedStatement_ parameters, whose
values must be supplied by nested parameter actions (such as
<<sql:param>>). The
`<sql:update>` action implements the _jakarta.servlet.jsp.jstl.sql.SQLExecutionTag_ interface, allowing the parameter
values to be supplied by custom parameter tags.

The connection to the database is obtained in
the same manner as described for <<sql:query>>.

The result of an `<sql:update>` action is
stored in a scoped variable named by the _var_ attribute, if that
attribute was specified. That result represents the number of rows that
were affected by the update. Zero is returned if no rows were affected
by _INSERT_, _DELETE_, or _UPDATE_, and for any SQL statement that
returns nothing (such as SQL DDL statements). This is consistent with
method _executeUpdate()_ of the JDBC class _Statement_.

<<<

=== <sql:transaction>

Establishes a transaction context for
`<sql:query>` and `<sql:update>` subtags.

.*Syntax*
....
<sql:transaction [dataSource="dataSource"]
        [isolation=isolationLevel]>
    <sql:query> and <sql:update> statements
</sql:transaction>

isolationLevel ::= "read_committed"
                | "read_uncommitted"
                | "repeatable_read"
                | "serializable"
....

.*Body Content*

Jakarta Server Pages content. The Jakart Server Pages container processes the body
content and then writes the result to the current _JspWriter_. The
action ignores the body content.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _dataSource_
|true a|
javax.sql.

DataSource

or String

|DataSource associated with the database to
access. A String value represents a relative path to a JNDI resource or
the parameters for the JDBC DriverManager facility.

|isolation |true
|String
|Transaction isolation level. If not
specified, it is the isolation level the DataSource has been configured
with.
|===

.*Constraints*

* Any nested `<sql:query>` and `<sql:update>`
actions must not specify a _dataSource_ attribute.

.*Null & Error Handling*

* If _dataSource_ is null, a _JspException_ is
thrown.

* Any exception occurring during the execution
of this action must be caught and rethrown after the transaction has
been rolled back (see description below for details).

.*Description*

The `<sql:transaction>` action groups nested
`<sql:query>` and `<sql:update>` actions into a transaction.

The transaction isolation levels are defined
by _java.sql.Connection_.

The tag handler of the `<sql:transaction>`
action must perform the following steps in its lifecycle methods:

* _doStartTag()_:

** Determines the transaction isolation level
the DBMS is set to (using the _Connection_ method
_getTransactionIsolation()_). +
If transactions are not supported (that is,
the transaction isolation level is equal to _TRANSACTION_NONE_), an
exception is raised, causing the transaction to fail. +
For any other transaction isolation level,
the auto-commit mode is is saved (so it can later be restored), and then
disabled by calling _setAutoCommit(false)_ on the _Connection_.

** If the _isolation_ attribute is specified and
differs from the connection's current isolation level, the current
transaction isolation level is saved (so it can later be restored) and
set to the specified level (using the _Connection_ method
_setTransactionIsolation()_).

* _doEndTag()_: Calls the _Connection_ method
_commit()_.

* _doCatch()_: Calls the _Connection_ method
_rollback()_.

* _doFinally()_:

** If a transaction isolation level has been
saved, it is restored using the _Connection_ method
_setTransactionIsolation()_.

** Restore auto-commit mode to its saved value
by calling _setAutoCommit()_ on the _Connection_.

** Closes the connection.

The _Connection_ object is obtained and
managed in the same manner as described for `<sql:query>` (see <<sql:query>>), except that it is never
obtained from a parent tag (`<sql:transaction>` tags can not be nested as
a means to propagate a _Connection_).

Note that the `<sql:transaction>` tag handler
commits or rollbacks the transaction (if it catches an exception) by
calling the JDBC _Connection commit()_ and _rollback()_ methods
respectively. Executing the corresponding SQL statements using
`<sql:update>`, e.g. `<sql:update sql="rollback" />`, within the
`<sql:transaction>` element body is not supported and the result of doing
so is unpredictable.

Finally, the behavior of the
`<sql:transaction>` action is undefined if it executes in the context of a
larger JTA user transaction.

<<<

[[sql:setDataSource]]
=== <sql:setDataSource>

Exports a data source either as a scoped
variable or as the data source configuration variable (_jakarta.servlet.jsp.jstl.sql.dataSource_).

.*Syntax*

[literal, subs="+quotes, +attributes"]
<sql:setDataSource
        {dataSource="dataSource" |
            url="jdbcUrl"
            [driver="driverClassName"]
            [user="userName"]
            [password="password"]}
        [var="varName"]
        {blank}[scope="{[underline]#page#|request|session|application}"]/>

.*Body Content*

Empty.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _dataSource_
|true |String or
javax.sql.DataSource |Data source. If
specified as a string, it can either be a relative path to a JNDI
resource, or a JDBC parameters string as defined in
<<Data Source>>.

| _driver_ |true
|String |JDBC
parameter: driver class name.

|url |true
|String |JDBC
parameter: URL associated with the database.

|user |true
|String |JDBC
parameter: database user on whose behalf the connection to the database
is being made.

|password |true
|String |JDBC
parameter: user password

|var |false
|String |Name of
the exported scoped variable for the data source specified. Type can be
_String_ or _DataSource_.

| _scope_ |false
|String |If _var_
is specified, scope of the exported variable. Otherwise, scope of the
data source configuration variable.
|===

.*Null & Error Handling*

* If _dataSource_ is null, a _JspException_ is
thrown.

.*Description*

If the _var_ attribute is specified, the
`<sql:setDataSource>` action exports the data source specified (either as
a _DataSource_ object or as a String) as a scoped variable. Otherwise,
the data source is exported in the
_jakarta.servlet.jsp.jstl.sql.dataSource_ configuration variable.

The data source may be specified either via
the _dataSource_ attribute (as a _DataSource_ object, JNDI relative
path, or JDBC parameters string), or via the four JDBC parameters
attributes. These four attributes are provided as a simpler alternative
to the JDBC parameters string syntax defined in
<<Data Source>> that would have to be used
with the _dataSource_ attribute.

As mentioned in
<<Data Source>>, using JDBC's
_DriverManager_ class to access a database is intended for prototyping
purposes only because it does not provide connection management features
one can expect from a properly designed _DataSource_ object.

[[sql:param]]
=== <sql:param>

Sets the values of parameter markers ("?") in
a SQL statement. Subtag of _SQLExecutionTag_ actions such as `<sql:query>`
and `<sql:update>`.

.*Syntax*

_Syntax 1: Parameter value specified in
attribute "value"_
....
<sql:param value="value"/>
....

_Syntax 2: Parameter value specified in the
body content_
....
<sql:param>
    parameter value
</sql:param>
....

.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content, then the action trims it and processes it further.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _value_ |true
|Object |Parameter
value.
|===

.*Constraints*

* Must be nested inside an action whose tag
handler is an instance of _jakarta.servlet.jsp.jstl.sql.SQLExecutionTag_.

.*Null & Error Handling*

* If _value_ is null, the parameter is set to
the SQL value NULL.

.*Description*

The `<sql:param>` action substitutes the given
parameter value for a parameter marker("?") in the SQL statement of its
enclosing _SQLExecutionTag_ action.

Parameters are substituted in the order
in which they are specified.

The `<sql:param>` action locates its nearest
ancestor that is an instance of _SQLExecutionTag_ and calls its
_addSQLParameter()_ method, supplying it with the given parameter value.

It is important to note that the semantics of
_SQLExecutionTag.addSQLParameter()_ are such that supplying a parameter
with a _String_ value (e.g. when using syntax 2) only works for columns
of text type (_CHAR_, _VARCHAR_ or _LONGVARCHAR_).

<<<

=== <sql:dateParam>

Sets the values of parameter markers ("?") in
a SQL statement for values of type _java.util.Date_. Subtag of
_SQLExecutionTag_ actions, such as `<sql:query>` and `<sql:update>`.

.*Syntax*

[literal, subs="+quotes, +attributes"]
<sql:dateParam value="value" {blank}[type="{[underline]#timestamp#|time|date}"]/>

.*Body Content*

Empty.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _value_ |true
|java.util.Date
|Parameter value for DATE, TIME, or TIMESTAMP
column in a database table.

|type |true
|String |One of
"date", "time" or "timestamp".
|===

.*Constraints*

* Must be nested inside an action whose tag
handler is an instance of _jakarta.servlet.jsp.jstl.sql.SQLExecutionTag_.

.*Null & Error Handling*

* If _value_ is null, the parameter is set to
the SQL value NULL.

.*Description*

This action converts the provided
_java.util.Date_ instance to one of _java.sql.Date_, _java.sql.Time_ or
_java.sql.Timestamp_ as defined by the _type_ attribute as follows:

* If the _java.util.Date_ object provided by
the _value_ attribute is an instance of _java.sql.Time_,
_java.sql.Date_, or _java.sql.Timestamp_, and the _type_ attribute
matches this object's type, then it is passed as is to the database.

* Otherwise, the object is converted to the
appropriate type by calling that type's constructor with a parameter of
_date.getTime()_, where _date_ is the value of the _value_ attribute.

The `<sql:dateParam>` action substitutes the
given parameter value for a parameter marker("?") in the SQL statement
of its enclosing _SQLExecutionTag_ action.

Parameters are substituted in the order
in which they are specified.

The `<sql:dateParam>` action locates its
nearest ancestor that is an instance of _SQLExecutionTag_ and calls its
_addSQLParameter()_ method, supplying it with the given parameter value.

[[SQL_Actions_Configuration_Settings]]
=== Configuration Settings

This section describes the configuration
settings used by the SQL actions. Refer to
<<Configuration Data>> for more
information on how the Jakarta Standard Tag Library processes configuration data.

==== DataSource

[width="100%",cols="50%,50%",]
|===
| _Variable name_
| _jakarta.servlet.jsp.jstl.sql.dataSource_

|Java Constant |
_Config.SQL_DATA_SOURCE_

|Type |String or
javax.sql.DataSource

|Set by
|`<sql:setDataSource>`, Deployment Descriptor,
Config class

|Used by
|`<sql:query>`, `<sql:update>`, `<sql:transaction>`
|===

The data source to be accessed by the SQL
actions. It can be specified as a string representing either a JNDI
relative path or a JDBC parameters string (as defined in
<<Data Source>>), or as a
_javax.sql.DataSource_ object.

==== MaxRows

[width="100%",cols="50%,50%",]
|===
| _Variable name_
| _jakarta.servlet.jsp.jstl.sql.maxRows_

|Java Constant |
_Config.SQL_MAX_ROWS_

|Type |Integer

|Set by
|Deployment Descriptor, Config class

|Used by
|`<sql:query>`
|===

The maximum number of rows to be included in
a query result. If the maximum number of rows is not specified, or is
-1, it means that no limit is enforced on the maximum number of rows.
Value must be >= -1.


== XML Core Actions: xml tag library

Enterprise data used in the web tier is
increasingly XML these days — when companies cooperate over the web, XML
is the data format of choice for exchanging information.

XML is therefore becoming more and more
important in a page author's life. The set of XML actions specified in
the Jakarta Standard Tag Library is meant to address the basic XML needs a page author is likely to
encounter.

The XML actions are divided in three
categories: XML core actions (this chapter), XML flow control actions
(<<XML Flow Control Actions: xml tag library>>), and XML transform actions
(<<XML Transform Actions: xml tag library>>).


=== Overview

A key aspect of dealing with XML documents is
to be able to easily access their content. XPath, a W3C recommendation
since 1999, provides a concise notation for specifying and selecting
parts of an XML document. The XML set of actions in the Jakarta Standard Tag Library is therefore
based on XPath.

The introduction of XPath for the XML tagset
expands the notion of expression language. XPath is an expression
language that is used locally for the XML actions. Below are the rules
of integration that XPath follows as a local expression language. These
rules ensure that XPath integrates nicely within the Jakarta Standard Tag Library environment.

==== XPath Context

In XPath, the context for evaluating an
expression consists of:

* A node or nodeset

* Variable bindings (see below)

* Function library +
The default function library comes with the
XPath engine. Some engines provide extension functions or allow
customization to add new functions. The XPath function library in the Jakarta Standard Tag Library
is limited to the core function library of the XPath specification.

* Namespace prefix definitions which allow
namespace prefixes to be used within an XPath expression.

==== XPath Variable Bindings

The XPath engine supports the following
scopes to easily access web application data within an XPath expression.
These scopes are defined in exactly the same way as their implicit
object counterparts in the Jakarta Standard Tag Library expression language (see Section 2.4 Implicit Objects in the Jakarta Server Pages specification).



[width="100%",cols="50%,50%",options="header",]
|===
|Expression
|Mapping
| _$foo_ |
_pageContext.findAttribute("foo")_

| _$param:foo_ |
_request.getParameter("foo")_

| _$header:foo_ |
_request.getHeader("foo")_

| _$cookie:foo_ |
_maps to the cookie's value for name foo_

| _$initParam:foo_
| _application.getInitParameter("foo")_

| _$pageScope:foo_ a|
_pageContext.getAttribute(_ +
{nbsp}{nbsp}{nbsp}{nbsp} _"foo", PageContext.PAGE_SCOPE)_

| _$requestScope:foo_ a|
_pageContext.getAttribute(_ +
{nbsp}{nbsp}{nbsp}{nbsp} _"foo", PageContext.REQUEST_SCOPE)_

| _$sessionScope:foo_ a|
_pageContext.getAttribute(_ +
{nbsp}{nbsp}{nbsp}{nbsp} _"foo", PageContext.SESSION_SCOPE)_

| _$applicationScope:foo_ a|
_pageContext.getAttribute(_ +
{nbsp}{nbsp}{nbsp}{nbsp} _"foo", PageContext.APPLICATION_SCOPE)_

|===

Through these mappings, Jakarta Server Pages scoped variables,
request parameters, headers, and cookies, as well as context init
parameters can all be used inside XPath expressions easily. For example:

....
/foo/bar[@x=$param:name]
....

would find the "bar" element with an
attribute "x" equal to the value of the http request parameter "name".



==== Java to XPath Type Mappings

An XPath variable must reference a
_java.lang.Object_ instance in one of the supported scopes, identified
by namespace prefix. The following mappings must be supported:



[width="100%",cols="50%,50%",options="header",]
|===
|Java Type |XPath
Type
| _java.lang.Boolean_
| _boolean_

| _java.lang.Number_
| _number_

| _java.lang.String_
| _string_

|Object exported by `<x:parse>`
| _node-set_
|===

A compliant implementation must allow an
XPath variable to address objects exposed by that implementation's
handlers for `<x:set>` and `<x:forEach>`. For example, while an
implementation of `<x:set>` may expose, for a node-set S, an object of any
valid Java type, subsequent XPath evaluations must interpret this object
as the node-set S.

An XPath expression must also treat variables
that resolve to implementations of standard DOM interfaces as
representing nodes of the type bound to that interface by the DOM
specification.

XPath variable references that address
objects of other types result in implementation-defined behavior. (An
implementation may throw an exception if it encounters an unrecognized
type.) Following the XPath specification (section 3.1), a variable name
that is not bound to any value results in an exception.

==== XPath to Java Type Mappings

Evaluation of XPath expressions evaluate to
XPath types. Their mapping to Java objects is defined as follows:



[width="100%",cols="50%,50%",options="header",]
|===
|XPath Type |Java
Type
a|
 _boolean_

true or false

| _java.lang.Boolean_

a|
 _number_

a floating-point number

| _java.lang.Number_

a|
 _string_

a sequence of UCS characters

| _java.lang.String_

a|
 _node-set_

an unordered collection of nodes without
duplicates

|Type usable by Jakarta Standard Tag Library XML-manipulation tags in
the same Jakarta Standard Tag Library implementation. The specific Java type representing
node-sets may thus vary by implementation.
|===

==== The _select_ Attribute

In all the XML actions of the Jakarta Standard Tag Library, XPath
expressions are always specified using the _select_ attribute. _select_
is therefore always specified as a string literal that is evaluated by
the XPath engine.

This clear separation, where only the
_select_ attribute of XML actions evaluates XPath expressions, helps
avoid confusion between XPath (expression language that is local to the
XML actions) and the Jakarta Standard Tag Library expression language (global to all actions
with dynamic attributes in the Expression Language version of the tag library).

==== Default Context Node

The context node for every XPath expression
evaluation in the Jakarta Standard Tag Library that does not appear in the body of an `<x:forEach>`
tag is the root of an empty document. Page authors wishing to work with
documents must therefore suply their own node(s) using an XPath variable
(see <<XPath Variable Bindings>>).

Action `<x:forEach>` establishes for its nested
actions a specific context for XPath expressions evaluation. See
<<x:forEach>> for details.

==== Resources Access

XML actions such as `<x:parse>` and
`<x:transform>` allow the specification of XML and/or XSLT documents as
_String_ or _Reader_ objects. Accessing a resource through a URL is
therefore handled through the `<c:import>` action that works seamlessly
with the XML tags as shown below:

....
<c:import url="http://acme.com/productInfo" var="doc">
    <c:param name="productName" value="${product.name}"/>
</c:import>
<x:parse doc="${doc}" var="parsedDoc"/>
....

To resolve references to external entities,
the _systemId_ (`<x:parse>`) and _docSystemId_ / _xsltSystemId_
(`<x:transform>`) attributes can be used. For these attributes:

* Absolute URLs are passed to the parser
directly

* Relative URLs are treated as references to
resources (e.g., loaded via _ServletContext.getResource()_) and loaded
using an _EntityResolver_ and _URIResolver_ as necessary

==== Core Actions

The XML core actions provide "expression
language support" for XPath. These actions are therefore similar to the
Expression Language support actions `<c:out>` and `<c:set>` covered in
<<General-Purpose Actions: core tag library>>, except that they apply to XPath
expressions.

The core XML actions feature one additional
action, `<x:parse>`, to parse an XML document into a data structure that
can then be processed by the XPath engine. For example:

....
<!-- parse an XML document -->
<c:import url="http://acme.com/customer?id=76567" var="doc"/>
<x:parse doc="${doc}" var="parsedDoc"/>

<!-- access XML data via XPath expressions -->
<x:out select="$parsedDoc/name"/>
<x:out select="$parsedDoc/address"/>

<!-- set a scoped variable -->
<x:set var="custName" scope="request" select="$parsedDoc/name"/>
....

The context for the evaluation of an XPath
Expression can be set either directly within the XPath expression (as
shown in the example above), or via an ancestor tag that sets a context
that can be used by nested tags. An example of this is with action
`<x:forEach>` (see <<x:forEach>>).

....
<!-- context set by ancestor tag <x:forEach> -->
<x:forEach select="$parsedDoc//customer">
    <x:out select="name"/>
</x:forEach>
....

<<<

=== <x:parse>

Parses an XML document.

.*Syntax*

_Syntax 1: XML document specified via a
String or Reader object_

[literal, subs="+macros"]
<x:parse {doc="XMLDocument"|xmlfootnote:[Deprecated.]="XMLDocument"}
    {var="var" [scope="scope"]|varDom="var" [scopeDom="scope"]}
    [systemId="systemId"]
    [filter="filter"]/>

_Syntax 2: XML document specified via the
body content_
....
<x:parse
    {var="var" [scope="scope"]|varDom="var" [scopeDom="scope"]}
    [systemId="systemId"]
    [filter="filter"]>
        XML Document to parse
</x:parse>
....


where scope is
{[underline]#page#|request|session|application}



.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content, then the action trims it and processes it further.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _doc_ | _true_
| _String, Reader_
|Source XML document to be parsed.

| _xml_ | _true_
| _String, Reader_
| _Deprecated_ footnote:[Names beginning with the string "xml" are reserved by the XML specification.]. Use
attribute _doc_ instead.

|systemId |true
|String |The
system identifier (URI) for parsing the XML document.

| _filter_ |
_true_ a|
_org.xml.sax.XMLFilter_

|Filter to be applied to the source document.

| _var_ | _false_
| _String_ |Name
of the exported scoped variable for the parsed XML document. The type of
the scoped variable is implementation dependent.

| _scope_ |
_false_ | _String_
|Scope for var.

| _varDom_ |
_false_ | _String_
|Name of the exported scoped variable for the
parsed XML document. The type of the scoped variable is
_org.w3c.dom.Document_.

| _scopeDom_ |
_false_ | _String_
|Scope for _varDom._
|===

.*Null & Error Handling*

* If the source XML document is null or empty,
a _JspException_ is thrown.

* If _filter_ is null, filtering is not
performed.

.*Description*

The `<x:parse>` action parses an XML document
and saves the resulting object in the scoped variable specified by
attribute _var_ or _varDom_. It does not perform any validation against
DTDs or Schemas.

The XML document can be specified either with
the _doc_ attribute, or inline via the action's body content.

*_var_ and _varDom_*

If _var_ is used, the type of the resulting
object is not defined by this specification. This allows implementations
to use whatever they deem best for an efficient implementation of the
XML tagset. _varDom_ exposes a DOM document, allowing collaboration with
custom actions. Objects exposed by _var_ and _varDom_ can both be used
to set the context of an XPath expression.

*Filtering for Performance Benefits*

If an implementation of the XML tagset is
based on DOM-like structures, there will be a significant performance
impact when dealing with large XML documents. To help with this,
attribute _filter_ can be used to allow filtering of the input data
prior to having it parsed by the implementation into a DOM-like
structure.

For example, if one is interested in
processing only the "European" customers which represent only 10% of the
original XML document received as input, it will greatly reduce the size
and complexity of the resulting DOM structure if all non-European
customers are pruned from the XML document prior to parsing.

....
<c:import url="http://acme.com/customers" var="doc"/>
    <x:parse doc="${doc}" filter="${filterEuropeanCust}"
            var="parsedDoc"/>
....

The _filter_ attribute accepts an object of
type _org.xml.sax.XMLFilter_.

If configuration of the filter is desirable,
it is suggested that the developer of the filter provides a custom tag
for easy configuration by a page author.

=== <x:out>

Evaluates an XPath expression and outputs the
result of the evaluation to the current _JspWriter_ object.

.*Syntax*

[literal, subs="+quotes, +attributes"]
<x:out select="XPathExpression" {blank}[escapeXml="{[underline]#true#|false}"]/>

.*Body Content*

Empty.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _select_ |
_false_ | _String_
|XPath expression to be evaluated.

| _escapeXml_ |
_true_ | _boolean_
|Determines whether characters <,>,&,'," in
the resulting string should be converted to their corresponding
character entity codes. Default value is true.
|===

.*Description*

The expression to be evaluated is specified
via attribute _select_ and must be in XPath syntax. The result of the
evaluation is converted to a _String_ as if the XPath _string()_
function were applied, and is subsequently written to the current
_JspWriter_ object.

This action is the equivalent of _<%=...%>_
(display the result of an expression in the Jakarta Server Pages syntax) and _<c:out>_
(display the result of an expression in the expression language syntax).

If _escapeXml_ is true, the following
character conversions are applied:



[width="100%",cols="50%,50%",options="header",]
|===
|Character
|Character Entity Code
| _<_ | \&lt;

| _>_ | \&gt;

| _&_ | \&amp;

|' |\&#039;

|" |\&#034;
|===

<<<

=== <x:set>

Evaluates an XPath expression and stores the
result into a scoped variable.

.*Syntax*

[literal, subs="+quotes, +attributes"]
<x:set select="XPathExpression"
    var="varName" {blank}[scope="{[underline]#page#|request|session|application}"]/>

.*Body Content*

Empty.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _select_ |
_false_ | _String_
|XPath expression to be evaluated.

| _var_ | _false_
| _String_ |Name
of the exported scoped variable to hold the value specified in the
action. The type of the scoped variable is whatever type the _select_
expression evaluates to.

| _scope_ |
_false_ | _String_
|Scope for var.
|===

.*Description*

Evaluates an XPath expression (specified via
attribute _select_) and stores the result into a scoped variable
(specified via attributes _var_ and _scope_).

The mapping of XPath types to Java types is
described in <<XPath to Java Type Mappings>>.


== XML Flow Control Actions: xml tag library

The core set of XML actions provides the
basic functionality to easily parse and access XML data. Another
important piece of functionality is the ability to iterate over elements
in an XML document, as well as conditionally process Jakarta Server Pages code fragments
depending on the result of an XPath expression. The XML flow control
actions provide these capabilities.


=== Overview

The XML flow control actions provide flow
control based on the value of XPath expressions. These actions are
therefore similar to the Expression Language flow control actions (`<c:if>`, `<c:choose>`,
and <`c:forEach>`), except that they apply to XPath expressions.

The _<x:if>_ action has a _select_ attribute
that specifies an XPath expression. The expression is evaluated and the
resulting object is converted to a _boolean_ according to the semantics
of the XPath _boolean()_ function:

* A number is true if an only if it is neither
positive or negative zero nor NaN

* A node-set is true if and only if it is
non-empty

* A string is true if and only if its length is
non-zero

`<x:if>` renders its body if the result is
true. For example:

....
<x:if select="$customer/[location='UK']">
    UK based customer
</x:if>
....

The `<x:choose>` action selects one among a
number of possible alternatives. It consists of a sequence of `<x:when>`
elements followed by an optional `<x:otherwise>`. Each <x:when> element
has a single attribute, _select_, which specifies an XPath expression.
When a `<x:choose>` element is processed, each of the `<x:when>` elements
has its expression evaluated in turn, and the resulting object is
converted to a boolean according to the semantics of the XPath boolean
function. The body of the first, and only the first, `<x:when>` whose
result is true is rendered.

If none of the test conditions of nested
`<x:when>` tags evaluates to true, then the body of an `<x:otherwise>` tag
is evaluated, if present.

....
<x:choose>
    <x:when select="$customer/firstName">
        Hello <x:out select="$customer/firstName"/>
    </x:when>
    <x:otherwise>
        Hello my friend
    </x:otherwise>
</x:choose>
....

The _<x:forEach>_ action evaluates the given
XPath expression and iterates over the result, setting the context node
to each element in the iteration. For example:

....
<x:forEach select="$doc//author">
    <x:out select="@name"/>
</x:forEach>
....

<<<

=== <x:if>

Evaluates the XPath expression specified in
the _select_ attribute and renders its body content if the expression
evaluates to true.

.*Syntax*

_Syntax 1: Without body content_

[literal, subs="+quotes, +attributes"]
<x:if select="XPathExpression"
        var="varName" {blank}[scope="{[underline]#page#|request|session|application}"]/>

_Syntax 2: With body content_

[literal, subs="+quotes, +attributes"]
<x:if select="XPathExpression"
        [var="varName"] {blank}[scope="{[underline]#page#|request|session|application}"]>
    body content
</x:if>

.*Body Content*

Jakarta Server Pages content. If the test condition evaluates to true,
the Jakarta Server Pages container processes the body content and then writes it to the
current _JspWriter_.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _select_ |
_false_ | _String_
|The test condition that tells whether or not
the body content should be processed.

| _var_ | _false_
| _String_ |Name
of the exported scoped variable for the resulting value of the test
condition. The type of the scoped variable is _Boolean_.

| _scope_ |
_false_ | _String_
|Scope for var.
|===

.*Constraints*

* If _scope_ is specified, _var_ must also be
specified.

.*Description*

The XPath expression specified via attribute
_select_ is evaluated, and the resulting object is converted to a
_boolean_ according to the semantics of the XPath _boolean()_ function.
If true, the body content is evaluated by the Jakarta Server Pages container and the
result is written to the current _JspWriter_.

<<<

=== <x:choose>

Provides the context for mutually exclusive
conditional execution.

.*Syntax*
....
<x:choose>
    body content (<x:when> and <x:otherwise> subtags)
</x:choose>
....

.*Body Content*

Jakarta Server Pages content. The body content is processed by the Jakarta Server Pages
container (at most one of the nested elements will be processed) and
written to the current _JspWriter_.

.*Constraints*

* The body of the `<x:choose>` action can only
contain:

** White spaces +
May appear anywhere around the `<x:when>` and
`<x:otherwise>` subtags.

** 1 or more `<x:when>` actions

** Must all appear before `<x:otherwise>`

** 0 or 1 `<x:otherwise>` action +
Must be the last action nested within
`<x:choose>`

.*Description*

The `<x:choose>` action processes the body of
the first _<x:when>_ action whose test condition evaluates to true. If
none of the test conditions of nested _<x:when>_ actions evaluates to
true, then the body of an _<x:otherwise>_ action is processed, if
present.

<<<

=== <x:when>

Represents an alternative within an
`<x:choose>` action.

.*Syntax*
....
<x:when select="XPathExpression">
    body content
</x:when>
....

.*Body Content*

Jakarta Server Pages content. If this is the first _<x:when>_ action
to evaluate to true within _<x:choose>_, the Jakarta Server Pages container processes
the body content and then writes it to the current _JspWriter_.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _select_ |
_false_ | _String_
|The test condition that tells whether or not
the body content should be processed
|===

.*Constraints*

* Must have _<x:choose>_ as an immediate
parent.

* Must appear before an _<x:otherwise>_ action
that has the same parent.

.*Description*

The XPath expression specified via attribute
_select_ is evaluated, and the resulting object is converted to a
_boolean_ according to the semantics of the XPath _boolean()_ function.
If this is the first _<x:when>_ action to evaluate to true within
_<x:choose>_, the Jakarta Server Pages container processes the body content and then
writes it to the current _JspWriter_.

<<<

=== <x:otherwise>

Represents the last alternative within a
`<x:choose>` action.

.*Syntax*
....
<x:otherwise>
    conditional block
</x:otherwise>
....

.*Body Content*

Jakarta Server Pages content. If no `<x:when>` action nested within
`<x:choose>` evaluates to true, the Jakarta Server Pages container processes the body
content and then writes it to the current _JspWriter_.

.*Attributes*

None.

.*Constraints*

* Must have `<x:choose>` as an immediate parent.

* Must be the last nested action within
`<x:choose>`.

.*Description*

Within a `<x:choose>` action, if none of the
nested `<x:when>` test conditions evaluates to true, then the body content
of the `<x:otherwise>` action is evaluated by the Jakarta Server Pages container, and the
result is written to the current _JspWriter_.

<<<

[[x:forEach]]
=== <x:forEach>

Evaluates the given XPath expression and
repeats its nested body content over the result, setting the context
node to each element in the iteration.

.*Syntax*
....
<x:forEach [var="varName"] select="XPathExpression">
        [varStatus="varStatusName"]
        [begin="begin"] [end="end"] [step="step"]>
    body content
</x:forEach>
....

.*Body Content*

Jakarta Server Pages content. As long as there are items to iterate
over, the body content is processed by the Jakarta Server Pages container and written to
the current _JspWriter_.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _var_ | _false_
| _String_ |Name
of the exported scoped variable for the current item of the iteration.
This scoped variable has nested visibility. Its type depends on the
result of the XPath expression in the _select_ attribute.

| _select_ |
_false_ | _String_
|XPath expression to be evaluated.

| _varStatus_ |
_false_ | _String_
|Name of the exported scoped variable for the
status of the iteration. Object exported is of type
_jakarta.servlet.jsp.jstl.core.LoopTagStatus_. This scoped variable has
nested visibility.

| _begin_ | _true_
| _int_ |Iteration
begins at the item located at the specified index. First item of the
collection has index 0.

| _end_ | _true_
| _int_ |Iteration
ends at the item located at the specified index (inclusive).

| _step_ | _true_
| _int_ |Iteration
will only process every _step_ items of the collection, starting with
the first one.
|===

.*Constraints*

* If specified, _begin_ must be >= 0.

* If _end_ is specified and it is less than
_begin_, the loop is simply not executed.

* If specified, _step_ must be >= 1

.*Null & Error Handling*

* If _select_ is empty, a _JspException_ is
thrown.

.*Description*

Inside the body of the tag, the context for
XPath expression evaluations is obtained as follows:

* variable, function, and namespace bindings
operate as in the rest of the Jakarta Standard Tag Library

* the context node is the node whose
representation would be exposed by 'var' (whether or not the 'var'
attribute is specified)

* the context position is the iteration 'count'
(with the same meaning as in `<c:forEach>`)

* the context size is equal to the number of
nodes in the node-set over which `<x:forEach>` is iterating


== XML Transform Actions: xml tag library

The transformation of XML documents using
XSLT stylesheets is popular in many web applications. The XML transform
actions provide this capability so XSLT transformations can be performed
within Jakarta Server Pages.

=== Overview

The XML transform actions support the
transformation of XML documents with XSLT stylesheets.

In the example below, an external XML
document (retrieved from an absolute URL) is transformed by a local XSLT
stylesheet (context relative path). The result of the transformation is
written to the page.

....
<c:import url="http://acme.com/customers" var="doc"/>
<c:import url="/WEB-INF/xslt/customerList.xsl" var="xslt"/>
<x:transform doc="${doc}" xslt="${xslt}"/>
....

It is possible to set transformation
parameters via nested `<x:param>` actions. For example:

....
<x:transform doc="${doc}" xslt="${xslt}">
    <x:param name="foo" value="foo-value"/>
</x:transform>
....

It is sometimes the case that the same
stylesheet transformation needs to be applied multiple times to
different source XML documents. A more efficient approach is to process
the transformation stylesheet once, and then save this "transformer"
object for successive transformations. The specification allows
implementations to support transparent caching of transformer objects to
improve performance.

<<<

=== <x:transform>

Applies an XSLT stylesheet transformation to
an XML document.

.*Syntax*

_Syntax 1: Without body contentt_

[literal, subs="+macros"]
<x:transform
        {doc="XMLDocument"|xmlfootnote:deprecated[Deprecated.]="XMLDocument"} xslt="XSLTStylesheet"
        [{docSystemId="XMLSystemId"|xmlSystemIdfootnote:deprecated[]="XMLSystemId"}]
        [xsltSystemId="XSLTSystemId"]
        [{var="varName" [scope="scopeName"]|result="resultObject"}]

_Syntax 2: With a body to specify
transformation parameters_

[literal, subs="+macros"]
<x:transform
        {doc="XMLDocument"|xml1="XMLDocument"} xslt="XSLTStylesheet"
        [{docSystemId="XMLSystemId"|xmlSystemIdfootnote:deprecated[]="XMLSystemId"}]
        [xsltSystemId="XSLTSystemId"]
        [{var="varName" [scope="scopeName"]|result="resultObject"}]
    <x:param> actions
</x:transform>

_Syntax 3: With a body to specify XML
document and optional transformation parameters_

[literal, subs="+macros"]
<x:transform
        xslt="XSLTStylesheet"
        [{docSystemId="XMLSystemId"|xmlSystemIdfootnote:deprecated[]="XMLSystemId"}]
        xsltSystemId="XSLTSystemId"
        [{var="varName" [scope="scopeName"]|result="resultObject"}]
    XML Document to parse
    optional <x:param> actions
</x:transform>


where scopeName is
{[underline]#page#|request|session|application}

.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content, then the action trims it and processes it further.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dyn
|Type |Description
| _doc_ | _true_
| _String, Reader,
javax.xml.transform.Source, org.w3c.dom.Document, or object exported by
<x:parse>, <x:set>_. |Source XML document to
be transformed. (If exported by <x:set>, it must correspond to a
well-formed XML document, not a partial document.)

| _xml_ | _true_
| _String, Reader,
javax.xml.transform.Source, org.w3c.dom.Document, or object exported by
<x:parse>, <x:set>_. |
_Deprecated_ footnote:[Names beginning with the string "xml" are reserved by the XML specification.]. Use attribute _doc_ instead.

| _xslt_ | _true_
| _String, Reader or
javax.xml.transform.Source_ |Transformation
stylesheet as a _String_, _Reader_, or _Source_ object.

|docSystemId |true
|String |The
system identifier (URI) for parsing the XML document.

|xmlSystemId |true
|String |
_Deprecated_ _1_. Use attribute _docSystemId_ instead.

|xsltSystemId
|true |String
|The system identifier (URI) for parsing the
XSLT stylesheet.

| _var_ | _false_
| _String_ |Name
of the exported scoped variable for the transformed XML document. The
type of the scoped variable is _org.w3c.dom.Document_.

| _scope_ |
_false_ | _String_
|Scope for var.

| _result_ |
_true_ a|
_javax.xml.transform.Result_

|Object that captures or processes the
transformation result.
|===

.*Null & Error Handling*

* If the source XML document is null or empty,
a _JspException_ is thrown.

* If the source XSLT document is null or empty,
a _JspException_ is thrown.

.*Description*

The `<x:transform>` tag applies a
transformation to an XML document (attribute _doc_ or the action's body
content), given a specific XSLT stylesheet (attribute _xslt_). It does
not perform any validation against DTD's or Schemas.

Nothing prevents an implementation from
caching _Transformer_ objects across invocations of `<x:transform>`,
though implementations should be careful they take into account both the
_xslt_ and _xsltSystemId_ attributes when deciding whether to use a
cached _Transformer_ or produce a new one. An implementation may assume
that any external entities that were referenced during parsing will not
change values during the life of the application.

The result of the transformation is written
to the page by default. It is also possible to capture the result of the
transformation in two other ways:

* _javax.xml.transform.Result_ object
specified by the _result_ attribute.

* _org.w3c.dom.Document_ object saved in the
scoped variable specified by the _var_ and _scope_ attributes.

<<<

=== <x:param>

Set transformation parameters. Nested action
of `<x:transform>`.

.*Syntax*

_Syntax 1: Parameter value specified in
attribute "value"_
....
<x:param name="name" value="value"/>
....

_Syntax 2: Parameter value specified in the
body content_
....
<x:param name="name">
    parameter value
</x:param>
....

.*Body Content*

Jakarta Server Pages content. The Jakarta Server Pages container processes the body
content, then the action trims it and processes it further.

.*Attributes*

[caption=""]
[width="100%",cols="25%,25%,25%,25%",options="header",]
|===
|Name |Dynamic
|Type |Description
| _name_ | _true_
| _String_ |Name
of the transformation parameter.

| _value_ | _true_
| _Object_ |Value
of the parameter.
|===

.*Description*

The _<x:param>_ action must be nested within
_<x:transform>_ to set transformation parameters. The value of the
parameter can be specified either via the _value_ attribute, or via the
action's body content.

<<<

== Tag Library Validators

Jakarta Server Pages provides tag library validators
(TLVs) as a mechanism for a tag library to enforce constraints on the
Jakarta Server Pages document (the "XML view") associated with any Jakarta Server Pages page into which
the tag library is imported. While the expectation is that TLVs used by
a tag library will typically enforce multi-tag constraints related to
usage of the library's tags themselves, a TLV is free to perform
arbitrary validation of Jakarta Server Pages documents. A TLV returns to the container
information about which elements, if any, are in violation of its
specific constraints, along with textual descriptions of the syntactic
violation.

The Jakarta Standard Tag Library provides TLVs that perform "reusable"
validation; i.e. generic validation that custom tag-library authors
might wish to incorporate in their own tag libraries. These tag
libraries do not necessarily need to be substantial collections of tags;
a taglib may exist simply to provide site-specific validation logic.
Just like tag libraries whose primary focus is to provide new tags, such
"validation-centric" tag libraries may be configured and used by
"back-end" developers in order to affect the "front-end" Jakarta Server Pages page
author's environment.

This chapter covers the Jakarta Standard Tag Library tag library
validators.

=== Overview

The Jakarta Standard Tag Library exposes via TLVs two simple types of
validations. These TLV classes may be used in custom tag-library
descriptors (TLDs) to restrict the page author's activities. The two
types of validation provided in this fashion are:

* _jakarta.servlet.jsp.jstl.tlv.ScriptFree_ +
Assurance of script-free pages

* _jakarta.servlet.jsp.jstl.tlv.PermittedTaglibs_ +
Enumeration of permitted tag libraries (including the Jakarta Standard Tag Library) on a page

For example, to prevent a Jakarta Server Pages page from using
Jakarta Server Pages scriptlets and Jakarta Server Pages declarations, but still allow expressions, a
developer could create the following TLD:

....
<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="https://jakarta.ee/xml/ns/jakartaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-jsptaglibrary_3_0.xsd"
    version="3.0">
    <description>
        Validates Jakarta Server Pages to prohibit use of scripting elements.
    </description>
    <tlib-version>1.0</tlib-version>
    <jsp-version>2.0</jsp.version>
    <short-name>scriptfree</short-name>
    <uri>http://acme.com/scriptfree</uri>

    <validator>
        <validator-class>
            jakarta.servlet.jsp.jstl.tlv.ScriptFreeTLV
        </validator-class>
        <init-param>
            <param-name>allowDeclarations</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>allowScriptlets</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>allowExpressions</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>allowRTExpressions</param-name>
            <param-value>true</param-value>
        </init-param>
    </validator>
</taglib>
....

Note that in Jakarta Server Pages, scripting elements can
also be disabled through the use of the _scripting-invalid_
configuration element (see the Jakarta Server Pages specification for details).

Similarly, to restrict a Jakarta Server Pages page to a set of
permitted tag-libraries (in the example below, the Jakarta Standard Tag Library "Expression Language" tag
libraries), a developer could create the following TLD:

....
<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="https://jakarta.ee/xml/ns/jakartaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-jsptaglibrary_3_0.xsd"
    version="3.0">
    <description>
        Restricts Jakarta Server Pages to the Jakarta Standard Tag Library tag libraries
    </description>
    <tlib-version>1.0</tlib-version>
    <jsp-version>2.0</jsp.version>
    <short-name>jstl taglibs only</scriptfree>
    <uri>http://acme.com/jstlTaglibsOnly</uri>

    <validator>
        <validator-class>
            jakarta.servlet.jsp.jstl.tlv.PermittedTaglibsTLV
        </validator-class>
        <init-param>
            <param-name>permittedTaglibs</param-name>
            <param-value>
                jakarta.tags.core
                jakarta.tags.xml
                jakarta.tags.fmt
                jakarta.tags.sql
            </param-value>
        </init-param>
    </validator>
</taglib>
....

== Functions: function tag library

Just like custom actions allow developers to
extend the Jakarta Server Pages syntax with their own customized behavior, the expression language defined in Jakarta Server Pages introduces the notion of _functions_ to allow developers to extend the capabilities of the Expression Language.

The Jakarta Standard Tag Library is about the standardization, via these
extension mechanisms, of behavior that is commonly needed by page
authors. In addition to defining a standard set of actions, the Jakarta Standard Tag Library
therefore also defines a standardized set of Expression Language functions. These
functions are described in this chapter.

=== Overview

The Jakarta Standard Tag Library functions are all grouped within the
_function_ tag library. They cover various domains of functionality
described below.

==== The _length_ Function

A feature sorely missed in JSTL 1.0 was the
ability to easily get the size of a collection. While the
_java.util.Collection_ interface defines a _size()_ method, it
unfortunately does not conform to the JavaBeans architecture design
pattern for properties and cannot be accessed via the expression
language.

The _length_ function has been designed to be
very similar to the use of "length" in EcmaScript. It can be applied to
any object supported by the Jakarta Standard Tag Library iteration action
<c:forEach>footnote:[Note that the support in <c:forEach> for strings representing lists of coma separated values has been deprecated. The proper way to process strings of tokens is via <c:forTokens> or via functions _split_ and _join_.] and returns the length of the
collection. When applied to a String, it returns the number of
characters in the string.

A sample use of _length_ is shown in the
example below where scoped variable _athletes_ is a collection of
_Athletes_ objects.

....
There are ${fn:length(athletes)} athletes representing ${country}
....

==== String Manipulation Functions

String manipulation functions allow page
authors to:

* Change the capitalization of a string (
_toLowerCase_, _toUpperCase_)

* Get a subset of a string (_substring, substringAfter, substringBefore_)

* Trim a string (_trim_)

* Replace characters in a string (_replace_)

* Check if a string contains another string (_indexOf, startsWith, endsWith, contains, containsIgnoreCase_)

* split a string (_split_) into an array, and
join an array into a string (_join_)

* Escape XML characters in the string (_escapeXml_)

The example below shows simple uses of these
functions.

....
<%-- truncate name to 30 chars and display it in uppercase --%>
${fn:toUpperCase(fn:substring(name, 0, 30))}

<%-- Display the text value prior to the first '*' character --%>
${fn:substringBefore(text, '*')}

<%-- Scoped variable "custId" may contain whitespaces at the beginning
or end. Trim it first, otherwise we end up with +'s in the URL --%> 
<c:url var="myUrl" value="${base}/cust"> 
    <c:param name="custId" value="${fn:trim(custId)}"/> 
</c:url> 

<%-- Display the text in between brackets --%>
${fn:substring(text, fn:indexOf(text, '(')+1,
                     fn:indexOf(text, ')'))}

<%-- Display the name if it contains the search string --%>
<c:if test="${fn:containsIgnoreCase(name, searchString)}">
    Found name: ${name}
</c:if>

<%-- Display the last 10 characters of the text value --%>
${fn:substring(text, fn:length(text)-10)}

<%-- Display text value with bullets instead of '-' --%>
${fn:replace(text, '-', '&#149;')}
....

While one can always use `<c:out>` to make sure
that XML characters are properly escaped, the function escapeXml
provides a syntax that is more concise as can be seen in the following
example:

....
<%-- Escape XML characters when displaying
the value of a request parameter (avoid cross-site scripting) --%>

<input name="userName" value="${fn:escapeXml(param:userName)}"> 

<%-- Escape XML characters when passing an attribute value to an action --%>

<%-- Using <c:out> with <c:set>--%>
<c:set var="nameEscaped">
    <c:out value="${name}"/>
</c:set>
<my:tag name="${nameEscaped}"/>

<%-- Using <c:out> with <jsp:attribute>--%>
<my:tag>
    <jsp:attribute name="name">
        <c:out value="${name}"/>
    </jsp:attribute>
</my:tag>

<%-- Using fn:escapeXml --%>
<my:tag title="${fn:escapeXml(name)}"/>
....

<<<<

=== fn:contains

Tests if a string contains the specified
substring.

.*Syntax*
....
fn:contains(string, substring) → boolean
....

.*Arguments & Result*

[caption=""]
[width="100%",cols="34%,33%,33%",options="header",]
|===
|Argument |Type
|Description
| _string_ |
_String_ |The input string on which the
function is applied.

| _substring_ |
_String_ |The substring tested for.

| _Result_ |
_boolean_ | _true_ if the character sequence
represented by the _substring_ argument exists in the character sequence
represented by the _string_ argument, _false_ otherwise.
|===

.*Null & Error Handling*

* If _string_ is null, it is processed as an
empty string.

* If _substring_ is null, it is processed as an
empty string.

.*Description*

Returns _true_ if the character sequence
represented by the _substring_ argument exists in the character sequence
represented by the _string_ argument, _false_ otherwise.

If _substring_ is empty, this matches the
beginning of the string and the value returned is true.



Essentially, _fn:contains_ returns the value
of:

{nbsp}{nbsp}{nbsp}{nbsp} _fn:indexOf(string, substring) != -1_.

<<<

=== fn:containsIgnoreCase

Tests if a string contains the specified
substring in a case insensitive way.

.*Syntax*
....
fn:containsIgnoreCase(string, substring) → boolean
....

.*Arguments & Result*

[caption=""]
[width="100%",cols="34%,33%,33%",options="header",]
|===
|Argument |Type
|Description
| _string_ |
_String_ |The input string on which the
function is applied.

| _substring_ |
_String_ |The substring tested for.

| _Result_ |
_boolean_ | _true_ if the character sequence
represented by the _substring_ argument exists in the character sequence
represented by the _string_ argument ignoring case differences, _false_
otherwise.
|===

.*Null & Error Handling*

* If _string_ is null, it is processed as an
empty string.

* If _substring_ is null, it is processed as an
empty string.

.*Description*

The behavior is the same as _fn:contains_,
except that the comparison is done in a case insensitive way, as in:

_fn:contains(fn:toUpperCase(string),
fn:toUpperCase(substring))._

<<<

=== fn:endsWith

Tests if a string ends with the specified
suffix.

.*Syntax*
....
fn:endsWith(string, suffix) → boolean
....

.*Arguments & Result*

[caption=""]
[width="100%",cols="34%,33%,33%",options="header",]
|===
|Argument |Type
|Description
| _string_ |
_String_ |The input string on which the
function is applied.

| _suffix_ |
_String_ |The suffix to be matched.

| _Result_ |
_boolean_ | _true_ if the character sequence
represented by the _suffix_ argument is a suffix of the character
sequence represented by the _string_ argument, _false_ otherwise.
|===

.*Null & Error Handling*

* If _string_ is null, it is processed as an
empty string.

* If _substring_ is null, it is processed as an
empty string.

.*Description*

Behavior is similar to _fn:startsWith_,
except that the substring must be at the end of the input string.

If _suffix_ is empty, this matches the end of
the string and the value returned is true.

<<<

=== fn:escapeXml

Escapes characters that could be interpreted
as XML markup.

.*Syntax*
....
fn:escapeXml(string) → String
....

.*Arguments & Result*

[caption=""]
[width="100%",cols="34%,33%,33%",options="header",]
|===
|Argument |Type
|Description
| _string_ |
_String_ |The input string on which the
conversion is applied.

| _Result_ |
_String_ |Converted string.
|===

.*Null & Error Handling*

* If _string_ is null, it is processed as an
empty string.

.*Description*

Escapes characters that could be interpreted
as XML markup. The conversions are the same as the ones applied by
`<c:out>` when attribute _escapeXml_ is set to true. See
<<c:out>>.

If _string_ is an empty string, an empty
string is returned.

<<<

=== fn:indexOf

Returns the index within a string of the
first occurrence of a specified substring.

.*Syntax*
....
fn:indexOf(string, substring) → int
....

.*Arguments & Result*

[caption=""]
[width="100%",cols="34%,33%,33%",options="header",]
|===
|Argument |Type
|Description
| _string_ |
_String_ |The input string on which the
function is applied.

| _substring_ |
_String_ |The substring to search for in the
input string.

| _Result_ | _int_
|If the substring argument is a substring of
the input string, returns the index of the first character of the first
such substring; if it does not occur as a substring, -1 is returned.
|===

.*Null & Error Handling*

* If _string_ is null, it is processed as an
empty string.

* If _substring_ is null, it is processed as an
empty string.

.*Description*

Returns the index (0-based) within a string
of the first occurrence of a specified substring according to the
semantics of method _indexOf(substring)_ of the Java class
_java.lang.String_, with the exception of the "Null and Error Handling"
processing described above.

If _substring_ is empty, this matches the
beginning of the string and the value returned is 0.

<<<

=== fn:join

Joins all elements of an array into a string.

.*Syntax*
....
fn:join(array, separator) → String
....

.*Arguments & Result*

[caption=""]
[width="100%",cols="34%,33%,33%",options="header",]
|===
|Argument |Type
|Description
| _array_
|String[] |Array
of strings to be joined.

| _separator_
|String |String to
separate each element of the array in the resulting string.

| _Result_ |
_String_ |All array elements joined into one
string.
|===

.*Null & Error Handling*

* If _array_ is null, an empty string is
returned.

* If separator is null, it is processed as an
empty string.

.*Description*

Joins all elements of the string array into a
string.

If separator is an empty string, then the
elements are joined together without any separator.

<<<

=== fn:length

Returns the number of items in a collection,
or the number of characters in a string.

.*Syntax*
....
fn:length(input) → integer
....

.*Arguments & Result*

[caption=""]
[width="100%",cols="34%,33%,33%",options="header",]
|===
|Argument |Type
|Description
| _input_ |Any of
the types supported for the _items_ attribute in the `<c:forEach>` action,
or _String_. |The input collection or string
on which the length is computed.

| _Result_ | _int_
|Length of the collection or the string.
|===

.*Null & Error Handling*

* If _input_ is null, it is treated as an empty
collection and the value returned is 0.

* If input is an empty string, the value
returned is 0.

<<<

=== fn:replace

Returns a string resulting from replacing in
an input string all occurrences of a "before" substring into an "after"
substring.

.*Syntax*
....
fn:replace(inputString, beforeSubstring, afterSubstring) → String
....

.*Arguments & Result*

[caption=""]
[width="100%",cols="34%,33%,33%",options="header",]
|===
|Argument |Type
|Description
| _inputString_ |
_String_ |The input string on which the
replace function is applied.

| _beforeSubstring_
| _String_ |The
"before" substring to be replaced.

| _afterSubstring_
| _String_ |The
"after" substring that replaces the "before" substring.

| _Result_ |
_String_ |The string that results from
replacing _beforeSubstring_ with _afterSubstring_.
|===

.*Null & Error Handling*

* If _inputString_ is null, it is processed as
an empty string.

* If _beforeSubstring_ is null, it is processed
as an empty string.

* If _afterSubstring_ is null, it is processed
as an empty string.

.*Description*

All occurrences of _beforeSubstring_ are
replaced by _afterSubstring_. The text replaced is not reprocessed for
further replacements.

If _inputstring_ is an empty string, an empty
string is returned.

If _beforeSubstring_ is an empty string, the
input string is returned.

If _afterSubstring_ is an empty string, all
occurrences of _beforeSubstring_ are removed from _inputString_.

<<<

=== fn:split

Splits a string into an array of substrings.

.*Syntax*
....
fn:split(string, delimiters) → String[]
....

.*Arguments & Result*

[caption=""]
[width="100%",cols="34%,33%,33%",options="header",]
|===
|Argument |Type
|Description
| _string_ |String
|The input string that gets split into an
array of substrings.

| _delimiters_
|String |Delimiter
characters used to split the string.

| _Result_ |
_String[]_ |Array of strings.
|===

.*Null & Error Handling*

* If _string_ is null, it is processed as an
empty string.

* If _delimiters_ is null, it is processed as
an empty string.

.*Description*

Breaks a string into tokens according to the
semantics of the Java class _java.util.StringTokenizer_, with the
exception of the "Null and Error Handling" described above.

If the input string is empty, the array
returned contains one element consisting of an empty string (no
splitting occurred, original string is returned).

If _delimiters_ is an empty string, the array
returned contains one element consisting of the input string (no
splitting occurred, original string is returned).

Delimiter characters themselves are not
treated as tokens, and are not included in any token.

<<<

=== fn:startsWith

Tests if a string starts with the specified
prefix.

.*Syntax*
....
fn:startsWith(string, prefix) → boolean
....

.*Arguments & Result*

[caption=""]
[width="100%",cols="34%,33%,33%",options="header",]
|===
|Argument |Type
|Description
| _string_ |
_String_ |The input string on which the
function is applied.

| _prefix_ |
_String_ |The prefix to be matched.

| _Result_ |
_boolean_ | _true_ if the character sequence
represented by the _prefix_ argument is a prefix of the character
sequence represented by the _string_ argument, _false_ otherwise.
|===

.*Null & Error Handling*

* If _string_ is null, it is processed as an
empty string.

* If _prefix_ is null, it is processed as an
empty string.

.*Description*

Tests if an input string starts with the
specified prefix according to the semantics of method _startsWith(String
prefix)_ of the Java class _java.lang.String_, with the exception of
the "Null and Error Handling" processing described above.

If _prefix_ is empty, this matches the
beginning of the string and the value returned is true.

<<<

=== fn:substring

Returns a subset of a string.

.*Syntax*
....
fn:substring(string, beginIndex, endIndex) → String
....

.*Arguments & Result*

[caption=""]
[width="100%",cols="34%,33%,33%",options="header",]
|===
|Argument |Type
|Description
| _string_ |
_String_ |The input string on which the
substring function is applied.

| _beginIndex_ |
_int_ |The beginning index (0-based),
inclusive.

| _endIndex_ |
_int_ |The ending index (0-based), exclusive
.

| _Result_ |
_String_ |The substring of the input string.
|===

.*Null & Error Handling*

* If _string_ is null, it is processed as an
empty string.

* If _beginIndex_ is greater than the last
index of the input string, an empty string is returned.

* If _beginIndex_ is less than 0, its value is
adjusted to be 0.

* If _endIndex_ is less than 0 or greater than
the length of the input string, its value is adjusted to be the length
of the input string (the substring therefore starts at _beginIndex_ and
extends to the end of the input string).

* If _endIndex_ is less than _beginIndex_, an
empty string is returned.

.*Description*

Returns a substring of the input string
according to the semantics of method _substring()_ of the Java class
_java.lang.String_, with the exception of the "Null and Error Handling"
processing described above.

Using a 0-based indexing scheme, the
substring begins at the specified _beginIndex_ and extends to the
character at index _endIndex_ -1. The length of the substring is
therefore _endIndex-beginIndex_.

It is suggested to use the value -1 for
_endIndex_ to extend the substring to the end of the input string.

<<<

=== fn:substringAfter

Returns a subset of a string following a
specific substring.

.*Syntax*
....
fn:substringAfter(string, substring) → String
....

.*Arguments & Result*

[caption=""]
[width="100%",cols="34%,33%,33%",options="header",]
|===
|Argument |Type
|Description
| _string_ |
_String_ |The input string on which the
substring function is applied.

| _substring_ |
_String_ |The substring that delimits the
beginning of the subset of the input string to be returned.

| _Result_ |
_String_ |The substring of the input string.
|===

.*Null & Error Handling*

* If _string_ is null, it is processed as an
empty string.

* If _substring_ is null, it is processed as an
empty string.

.*Description*

The substring returned starts at the first
character after the substring matched in the input string, and extends
up to the end of the input string.

If _string_ is an empty string, an empty
string is returned.

If _substring_ is an empty string, it matches
the beginning of the input string and the input string is returned. This
is consistent with the behavior of function _indexOf_, where an empty
substring returns index 0.

If _substring_ does not occur in the input
string, an empty string is returned.

<<<

=== fn:substringBefore

Returns a subset of a string before a
specific substring.

.*Syntax*
....
fn:substringBefore(string, substring) → String
....

.*Arguments & Result*

[caption=""]
[width="100%",cols="34%,33%,33%",options="header",]
|===
|Argument |Type
|Description
| _string_ |
_String_ |The input string on which the
substring function is applied.

| _substring_ |
_String_ |The substring that delimits the end
of subset of the input string to be returned.

| _Result_ |
_String_ |The substring of the input string.
|===

.*Null & Error Handling*

* If _string_ is null, it is processed as an
empty string.

* If _substring_ is null, it is processed as an
empty string.

.*Description*

The substring returned starts at the first
character in the input string and extends up to the character just
before the substring matched in the input string.

If _string_ is an empty string, an empty
string is returned.

If _substring_ is an empty string, it matches
the beginning of the input string and an empty string is returned. This
is consistent with the behavior of function _indexOf_, where an empty
substring returns index 0.

If _substring_ does not occur in the input
string, an empty string is returned.

<<<

=== fn:toLowerCase

Converts all of the characters of a string to
lower case.

.*Syntax*
....
fn:toLowerCase(string) → String
....

.*Arguments & Result*

[caption=""]
[width="100%",cols="34%,33%,33%",options="header",]
|===
|Argument |Type
|Description
| _string_ |
_String_ |The input string on which the
transformation to lower case is applied.

| _Result_ |
_String_ |The input string transformed to
lower case.
|===

.*Null & Error Handling*

* If _string_ is null, it is treated as an
empty string and an empty string is returned.

.*Description*

Converts all of the characters of the input
string to lower case according to the semantics of method
_toLowerCase()_ of the Java class _java.lang.String_.

<<<

=== fn:toUpperCase

Converts all of the characters of a string to
upper case.

.*Syntax*
....
fn:toUpperCase(string) → String
....

.*Arguments & Result*

[caption=""]
[width="100%",cols="34%,33%,33%",options="header",]
|===
|Argument |Type
|Description
| _string_ |
_String_ |The input string on which the the
transformation to upper case is applied.

| _Result_ |
_String_ |The input string transformed to
upper case.
|===

.*Null & Error Handling*

* If _string_ is null, it is treated as an
empty string and an empty string is returned.

.*Description*

Converts all of the characters of the input
string to upper case according to the semantics of method
_toUpperCase()_ of the Java class _java.lang.String_.

<<<

=== fn:trim

Removes white space from both ends of a
string.

.*Syntax*
....
fn:trim(string) → String
....

.*Arguments & Result*

[caption=""]
[width="100%",cols="34%,33%,33%",options="header",]
|===
|Argument |Type
|Description
| _string_ |
_String_ |The input string on which the the
trim is applied.

| _Result_ |
_String_ |The trimmed string.
|===

.*Null & Error Handling*

* If _string_ is null, it is treated as an
empty string and an empty string is returned.

.*Description*

Removes white space from both ends of a
string according to the semantics of method _trim()_ of the Java class
_java.lang.String_.

[appendix]
== Compatibility & Migration

This appendix provides
information on compatibility between different versions of the Jakarta Standard Tag Library, as well
as on how to migrate your web application to take advantage of the new
features of the latest Jakarta Standard Tag Library release.

=== Java EE Backwards Compatibility

The API has moved from the Java EE (JCP) `javax.servlet.jsp.jstl` package to the Jakarta EE (Eclipse Foundation) `jakarta.servlet.jsp.jstl` package. Applications
using the Java EE package will need to change this to the Jakarta EE package.

<<<

[appendix]
== Changes

This appendix lists the
changes in the Jakarta Standard Tag Library specification. This appendix is non-normative.

=== Changed between Jakarta Standard Tag Library 2.0 and Jakarta Standard Tag Library 3.0

** https://github.com/eclipse-ee4j/jstl-api/issues/149 : Remove dependency on XML Binding from the API pom

** https://github.com/eclipse-ee4j/jstl-api/issues/156 : Update Jakarta Tags to Java 11

** https://github.com/eclipse-ee4j/jstl-api/issues/157 : Add JPMS Module Info Class

** https://github.com/eclipse-ee4j/jstl-api/issues/144 : Rename Tag URIs to 'jakarta.tags.*'

=== Changed between Jakarta Standard Tag Library 2.0 and JSR-52

** The API has moved from the `javax.servlet.jsp.jstl` package to the `jakarta.servlet.jsp.jstl` package.
** The contents of the Javadoc were removed and are now included by reference.

<<< 

'''''
