• Aucun résultat trouvé

JSTL-XML and XSL

Dans le document Beginning JSP, JSF and Tomcat (Page 151-155)

The XML actions specified in JSTL are meant to address the basic XML needs that a JSP programmer is likely to encounter.

To make XML file contents easier to access, the W3C specified the XML Path Language (XPath). The name XPath was chosen to indicate that it identifies paths within XML documents (see

http://www.w3.org/TR/xpath). The JSTL-XML actions rely on that language to identify XML components.

To avoid confusion between EL expressions and XPath expressions, the actions that require an XPath expression always use the select attribute. In this way, you can be sure that all expressions outside select are EL expressions. Several XML actions are the XPath-counterparts of equivalent core actions, with the attribute select replacing the attribute value (when present). They are: x:choose, x:forEach, x:if, x:out, x:otherwise, x:set, and x:when.

The remaining three actions are x:parse and the pair x:transform and x:param. But before you can learn about them, we have to talk about the Extensible Stylesheet Language (XSL).

XSL is a language for expressing style sheets that describe how to display and transform XML documents. The specification documents are available from http://www.w3.org/Style/XSL/.

While CSS only needs to define how to represent the predefined HTML tags, XSL has to cope with the fact that there are no predefined tags in XML! How do you know whether a <table> element in an XML file represents a table of data as you know it from HTML or an object around which you can sit for dinner?

That’s why XSL is more than a style-sheet language. It actually includes three parts:

XPath: The language to navigate in XML documents I already mentioned.

XSLT: A language to transform XML documents that can completely change their structure.

XSL Formatting Objects (XSL-FO): A language for formatting XML documents.

I will only explain XPath and XSLT, because XSL-FO is concerned with page formatting (page size, margins, headers, footers, citations, footnotes, and so on), which is very different from the screen formatting and hyperlinking you need for web pages.

Just to give you an idea, XSL-FO divides the output into pages, the pages into regions (body, header, footer, and left and right sidebars), the regions into block areas, the block areas into line areas, and the line areas into inline areas. You can define several attributes of these fields and then “flow” your content into them. XSL-FO also provides constructs for lists and tables similar to those you know from HTML.

XPath

XPath expressions identify a set of XML nodes through patterns. Extensible Stylesheet Language Transformations (XSLT) templates (see later in this chapter for XSLT examples) then use those patterns when they apply transformations. Possible XPath nodes can be any of the following: document/root, comment, element, attribute, text, processing instruction, and namespace.

„ Note Processing instructions in an XML document provide information for the application that uses the

document.

For example, take a look at the following XML document:

<?xml version="1.0" encoding="UTF-8"?>

<whatever xmlns:zzz="http://myWeb.com/whatever">

<!-- bla bla --> <?myAppl "xyz"?>

<item name="anything">

<subitem>The quick brown fox</subitem>

</item>

</whatever>

The document (or root) node is <whatever>, <!-- bla bla --> is a comment node,

<subitem>...</subitem> is an element node, name="anything" is an attribute node, the string The quick brown fox is a text node, <?myAppl "xyz"?> is a processing-instruction node, and

xmlns:zzz="http://myWeb.com/whatever" is a namespace node.

As with URLs, XPath uses a slash as a separator. Absolute paths start with a slash, while all other paths are relative. Similar to file directories, a period indicates the current node, while a double period indicates the parent node.

Several nodes with the same name are distinguished by indexing them, as Java does with array elements. For example, let’s say you have the following XML code:

<a> <b>whatever</b> <b>never</b> </a>

<c> <non_b>no</non_b> <b>verywell</b> </c>

<a> <b attr="zz">nice</b> <b attr="xxx">ok</b> </a>

The pattern /a/b selects the four <b> elements, which contain whatever, never, nice, and ok. The <b>

element with verywell isn’t selected, because it’s inside <c> instead of <a>. The pattern /a[1]/b[0]

selects the <b> element with nice. Attribute names are prefixed by an @. For example, /a[1]/b[1]/@attr refers to the attribute that has the value xxx in the example.

A clever thing in XPath: you can use conditions as indices. For example, /a/b[@attr="zz"] selects the same <b> element selected by /a[1]/b[0], while /a[b] selects all <a> elements that have <b> as a child (in the example, both), and /a[b="never"] selects the first <a> element. A final example: /a/b[@attr][0]

selects the first <b> element that is contained in an <a> and has the attribute attr (i.e., it selects once again the element /a[1]/b[0]).

XPath defines several operators and functions related to node sets, positions, or namespaces, and it defines string, numeric, boolean, and conversion operations.

A node set is a group of nodes considered collectively. A node set resulting from the execution of an XPath expression doesn’t necessarily contain several nodes. It can consist of a single node or even none.

Keep in mind that the nodes belonging to a node set can be organized in a tree, but not necessarily. For example, the expression $myDoc//C identifies all C elements in a document that was parsed into the variable myDoc. It is unlikely that they form a tree.

Within XPath, you have access to the implicit JSP objects you’re familiar with. Table 5-3 lists the mappings.

Table 5-3. XPath Mappings of Implicit JSP Objects

JSP XPath

pageContext.findAttribute("attrName") $attrName

request.getParameter("parName") $param:paramName

request.getHeader("headerName") $header:headerName

cookie’s value for name foo $cookie:foo

application.getInitParameter("initParName") $initParam:initParName pageContext.getAttribute("attrName", PageContext.PAGE_SCOPE) $pageScope:attrName pageContext.getAttribute("attrName", PageContext.REQUEST_SCOPE) $requestScope:attrName pageContext.getAttribute("attrName", PageContext.SESSION_SCOPE) $sessionScope:attrName pageContext.getAttribute("attrName", PageContext.APPLICATION_SCOPE) $applicationScope:attrName

Before we look at an XPath example, I would like to give you a more rigorous reference of its syntax and explain some terms that you are likely to encounter “out there.”

To identify a node or a set of nodes, you need to navigate through the tree structure of an XML document from your current position within the tree (the context node) to the target. The path

description consists of a series of steps separated by slashes, whereby each step includes the navigation direction (the axis specifier), an expression identifying the node[s] (the node test), and a condition to be satisfied (the predicate) enclosed between square brackets.

A slash at the beginning indicates that the path begins at the root node, while paths relative to the context node begin without a slash. Two consecutive colons separate the axis specifier and the node test.

For example, this code identifies the second attribute of all B elements immediately below the root element A:

/child::A/child::B/attribute::*[position()=2]

You can express the same path with an abbreviated syntax, as follows:

/A/B/@*[2]

where child, ::, and position()= are simply omitted, and attribute is represented by @.

Table 5-4 shows the possible axis specifiers and their abbreviated syntax.

Table 5-4. Axis Specifiers

Specifier Abbreviated Syntax

ancestor Not available (n/a) ancestor-or-self n/a

attribute @

child Default; do not specify it

descendant //

descendant-or-self n/a

following n/a

following-sibling n/a

namespace n/a

parent (i.e., two dots)

preceding n/a

preceding-sibling n/a

self (i.e., a single dot)

As node tests, you can use node names with or without a namespace prefix, or you can use an asterisk to indicate all names. With abbreviated syntax, an asterisk on its own indicates all element nodes, and @* indicates all attributes.

You can also use node()as a node test to indicate all possible nodes of any type. Similarly, comment() indicates all comment nodes, text() indicates all text nodes, and processing-instruction() indicates all processing instruction nodes.

For example, the following code selects all elements B descendant of A that have the attribute xx set to 'z':

A//B[@xx='z']

while to select all elements C anywhere in the tree that have the attribute yy you can do this:

//C[@yy]

To form expressions, besides the operators you have already seen (i.e., slash, double slash, and square brackets), you have available all standard arithmetic and comparison operators (i.e., +, -, *, div,

mod, =, !=, <, <=, >, and >=). Additionally, you have and and or for boolean operations, and the union operator | (i.e., the vertical bar) to merge two node sets.

References to variables are indicated by sticking a dollar sign before them, as shown in the following example:

<x:parse doc="${sf}" varDom="dom"/>

<x:forEach var="tag" select="$dom//starship">

where I parse an XML document into the variable dom and then use $dom when I refer to it in an XPath expression.

Dans le document Beginning JSP, JSF and Tomcat (Page 151-155)