• Aucun résultat trouvé

Computing New Information

4.3 Transformation in HTML

4.3.3 Computing New Information

XSLT can also be used for more complex selections and transformations. We will now show how to create a web page presenting the content of the cellar and integrating information from the wine catalog. The end result is shown in figure 4.3 (an outline of the underlying HTML is in listing 4.5). There are external links in order to get more information about the wines directly from the website of the Soci´et´e des Alcools du Qu´ebec (SAQ). There are two similar links for each wine but it is just to show and compare ways of creating them in XSL.

Listing 4.5: [CellarBook.html]: HTML output (slightly reformatted and trimmed to fit on the page) about the cellar. The XSLT code is shown in listing 4.6. Because of the use of a namespace in the htmltag, the XMLprocessor has generatedxmlns="" attributes for all top level HTML elements.

Figure 4.3: [CellarBook.jpg]: HTMLdisplay of listing 4.5

. . . .

< tr >

< td c o l s p a n = " 3 " > E s t i m a t e d v a l u e < / td >

35 < td a l i g n = " r i g h t " > 3 3 3 . 7 5 $ < / td >

< td a l i g n = " r i g h t " > 14 < / td >

< / tr >

< / t a b l e >

< h3 x m l n s = " " > C o m m e n t s < / h3 >

40 C 0 0 0 4 3 1 2 5 : < b x m l n s = " " > Guy Lapalme , M o n t r ´e a l < / b >

: s h o u l d r e o r d e r s o o n . . . .

< / b o d y >

< / h t m l >

Listing 4.6 illustrates some new features. The root template (line 15) creates the high level structure of the XHTML file: the title of the page, also displayed at the top of the page, refers to the name of the owner. In listing 2.2, element name (line 12) is structured in two elements: first and family. When the value of such an element is returned from a xsl:value-of, it is the text context of all elements: in fact, there are 5 parts in this case:

• the text node comprising a \n2 following the name opening tag and white space until the start of first

• the content of the element first

• the \n and spaces between the closing tag of first and the opening tag offamily

• the content of the element family

• the \n and spaces between the closing tag of familyand the closing tag of name Given the fact, that a sequence of\n and spaces in HTMLis displayed as a single space by the browser, we get an appropriate display in this case. But this shows that dealing with text content can become a bit tricky. The next section will explain how to deal with some of the most frequent cases.

The content of the cellar book is obtained by an explicit call (line 26) to the template defined at (line 34) which creates a table with the address of the owner (line 40) and the cellar (line 44). It then calls the cellar template (line 51). The lines of the addresses are obtained by looping on all elements with afor-eachand outputting a<br/>between the text value of each element of the ownerandlocationelements. Because we want to skip the first element (the owner name has already been given at the top), we only keep those (line 44) with a position number be greater than 1.

The comment(line 55) template outputs the value of the code of the parent node, a colon and the text value of the comment followed by a line break. In getting the content of the comment, the cat:bold elements will be processed by the appropriate template (line 61) to transform them by HTML btags.

2\nis the notation for anend of line character.

The cellar(line 66) template produces a table of information about wines in the cellar sorted by their code. This is why the content of the xsl:apply-templates element (line 75) is an xsl:sort element indicating the sorting key and the sort order. The last line of the table contains an estimated total value of the cellar obtained by a call (line 81) to thetotal named template. To compute the total number of bottles (line 88), we can use the predefined sum function. Finally, if there are any comment in thewine elements of the cellar (line 93), we add a Comments section and output each of them, also in increasing order of wine codes so that they be in the same order as in the table of wines.

We define the wine template (line 102) to create a row in the table of wines. We first define a variable code (line 104) having the value of the code attribute. We display it without the first letter, to make it match with the official SAQ code.3 In order to gather some information about this wine from the wine catalog and we pass the wine node from the wine-catalog as a parameter to the call to the nameAndUrltemplate (line 107). The link between the current element and the corresponding element in the catalog is done using the value of the code variable given in the XPath expression. The remaining elements of the row are the purchase date (right-aligned), a number of stars corresponding to the rating and the quantity (right-aligned).

The named template total (line 121) computes the estimated value of the cellar. Since there are no assignment in XSLT, we cannot change the value of a variable in a template, so we call total recursively in order to update the sum. This is why this template has two parameters: indexis the index of the current node in the list of wines and sumis used as an accumulator. These are initialized at the call (line 81) respectively to 1 and 0. The total template first tests whether index is greater than the number of wine elements (line 125).

If so, it returns the current value of sum properly formatted. If the index is less than the number of wines, then we process theindexth wine, for which we get the quantity (line 129) and the code. We then search the wine catalog to get its price, which is used to compute a new value for the sumparameter for the recursive call to total (line 133).

nameAndUrl (line 142) is another named template that receives awine element as

param-eter. From this wine element, we create a XHTML link (line 146) with an a element with an href attribute whose value is a string giving the address of the SAQ website. This is a bit involved because the link must be created dynamically using the xsl:element and the

xsl:attribute elements with appropriate contents. For that, we use two variables:

$SAQquery set inxsl:param for the whole stylesheet (line 5). This string corresponds to the URL encoded CGI call to query the SAQ database from a webpage.

$SAQcode is the code of the wine (minus its first character).

The values are used to create the value of the attributehref of theaelement in the resulting HTML.

Because creating such dynamic elements and attributes is often required,XSLTdesigners have defined anon-XMLformalism called in which we only indicate the shape of the element

3We had added an initialCin order to be the right format for anID type of aDTDor XML Schema.

to create. Within this element, we can use a variable between braces that will be replaced by its current value (line 155). One should consult the documentation to determine which contexts allow this shortcut notation.

Listing 4.6: [CellarBook.xsl]: XSLT stylesheet to produce information about the cellar (listing 2.2). The resulting HTML (listing 4.5) is displayed in figure 4.3

< ? xml v e r s i o n = " 1.0 " e n c o d i n g = " UTF -8 " ? >

40 < tr > < td > < xsl:for - e a c h s e l e c t = " o w n e r /*[ p o s i t i o n () >1] " >

85 < / td >

130 < x s l : v a r i a b l e n a m e = " c o d e " s e l e c t = " ./ w i n e [$ i n d e x ]/ @ c o d e " / >

We will now use an XSLT stylesheet (shown in listing 4.8) to produce a compact form of an XML file. The output of this transformation will only be a stream of plain characters without any tags. This illustrates that XSLT can be used to transform XML input into something else than XML.

The algorithm follows the same pattern as the one explained in section 4.3.1. We recur-sively follow the structure of tree and output a corresponding stream of characters. In our case, only one rule is applied to all element nodes: we output the name of the element and then output its attributes and children, but with an indentation corresponding to the number

Documents relatifs