Главная > J2EE > JSTL: Шаблоны для разработки веб-приложений в java. Часть 2

Тема Зацепин
268

Java-разработчик 🧩
55
3 минуты

JSTL: Шаблоны для разработки веб-приложений в java. Часть 2

В прошлый раз я рассказал о тегах основного назначения, сегодня самое время перейти к средствам позволяющим работать с xml. Прежде всего, мы должны в заголовке jsp страницы подключить следующую библиотеку тегов:

Добавлено : 3 Nov 2008, 17:59
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>

Во всех последующих примерах будет нужен xml-файл, вот его код:

xmlversion="1.0"encoding="utf-8"?>id="12"></span><span>Книга про зайцев</span><span>99.95main="true">Тапкин Василий ВасильевичПупкина Ленка Ленковнаid="13"></span><span>Слоны-людоеды</span><span>29.95main="true">Слоноглазов Глеб ГамбитовичСлоноухова Виктория Мракобесовна

До начала работы с xml его нужно распарсить, делается это либо непосредственно внутри jsp-файла либо подобную работу может выполнить java backend-код. Парсинг выполняется средствами тега x:parse, например, так:

var="bookshelf">xmlversion="1.0"encoding="utf-8"?>id="12"></span><span class="sc0">Книга про зайцев</span><span class="sc1">99.95main="true">Тапкин Василий ВасильевичПупкина Ленка Ленковнаid="13"></span><span class="sc0">Слоны-людоеды</span><span class="sc1">29.95main="true">Слоноглазов Глеб ГамбитовичСлоноухова Виктория Мракобесовна
var="bookshelf2"xml="${helloMachine.bookshelfAsString}"/>

Если в первом случае весь код xml находится внутри тега parse, то второй вариант предполагает, что в составе класса HelloMachineBean должен появиться новый метод (для как бы не настоящего свойства), который читал бы с диска приведенный ранее xml-документ, и возвращал бы его в jstl-код в виде обычной строки.

public String getBookshelfAsString() {
try {
BufferedReader brin = new BufferedReader(
new InputStreamReader(getClass().getResourceAsStream("/testi/templates/book.xml")));
StringBuffer buf =
new StringBuffer();
String line;
while ((line = brin.readLine()) != null)
buf.append(line);
return buf.toString();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}

Теперь попробуем с этим xml-файлом что-нибудь сделать. В самом простом случае нужно вывести на экран какую-то информацию. Обычный c:out не подходит, нам нужен тег, который выбирает с помощью xpath-выражений. И такой тег есть – x:out, в качестве параметров для него указывается атрибут select с выражением вида:

Где-искать/Чего-искать

Где искать – это java-переменная ссылающаяся на xml-дерево. Имя ее может быть как просто bookshelf (см. прошлый пример), так и содержать имя контекста, например: pageScope:bookshelf.

Вот примеры, отбирающие разные части xml-документа (пусть вас не смущает то, что у меня и имя переменной в которой хранится xml-документ и имя первого тега совпадают – это ничего не значит):

var="bookshelf">url="book.xml"charEncoding="utf-8"/> all book content:select="$bookshelf/bookshelf/book[1]"escapeXml="false"/> id:select="$bookshelf/bookshelf/book[1]/@id"/> title:select="$bookshelf/bookshelf/book[1]/title"/> qty authors:select="count($bookshelf/bookshelf/book[1]/authors/author)"/>

Атрибут escapeXML служит для управления тем, что будет происходить при обработке сущностей xml. Так в ранее приведенном примере документа, у меня внутри тега description находится символьный контейнер CDATA, внутри текста которой есть сущность ©. В результате вывода с включенным escapeXML я вижу именно ©, когда же режим экранирования отключен, то вижу значок копирайта (собственно, это аналог атрибута из xsl – disable-output-escaping).

Теперь проблема: если я к xml-документу добавлю пространства имен, например, так:

xmlns="http://books.com/buki">

То ранее приведенный код не будет работать. Выходом будет записать выражение, основанное не на полных именах тегов, а на коротких именах (локальных именах):

all book content:select="$bookshelf/*[name()='bookshelf']/*[name()='book'][1]"escapeXml="false"/> id:select="$bookshelf/*[name()='bookshelf']/*[name()='book'][1]/@id"/> title:select="$bookshelf/*[name()='bookshelf']/*[name()='book'][1]/*[name()='title']"/> qty authors:select="count($bookshelf/*[name()='bookshelf']/*[name()='book'][1]/*[name()='authors']/*[name()='author'])"/>

Подобные выражения, мягко говоря, не удобочитаемы, но лучшего выхода из сложившейся проблемы нет (точнее есть: плюнуть на jstl и написать самому).

При записи сложных xpath-выражений можно ссылаться на объявленные в jstl переменные, например, далее я хочу найти в списке книг только ту, номер которой был передан как входной параметр скрипту:

book title by bid: select="$bookshelf/bookshelf/book[@id = $param:bid]/title"/>

Теперь перейдем к тегу x:set. Он очень похож на x:out, вот только не выводит на экран некоторую xpath-часть входного документа, а присваивает ее jstl-переменной, например, для того чтобы в последующем еще раз выполнить обработку документа с помощью x:out (ни в коем случае полученный промежуточный узел нельзя выводить c:out):

var="bookTitle"select="$bookshelf/bookshelf/book[1]/title"/> book title = select="$bookTitle/."/>

Теперь разберемся с тем, как в xml работать с циклами и условиями. В стандартной части jstl есть тег forEach умеющий работать со списками и массивами. В части jstl посвященной xml есть одноименный и очень похожий по параметрами тег forEach. Вот пример использования двойного цикла (в виде заголовка название книги, далее в виде списка авторы):

select="$bookshelf/bookshelf/book"var="book">

select="$book/title"/>

    select="$book/authors/author"var="author">
  • select="$author"/>

Для работы с условиями есть два тега: if и choose, точь-в-точь как их старшие братья. Далее идет пример, в котором для каждой книги выводится сообщение “два или более автора” если у книги, действительно, более чем один автор:

select="$bookshelf/bookshelf/book"var="book">

select="$book/title"/>

select="count($book/authors/author) >= 2"> Два или более писателя сотворили сей опус

Также как и для c:if, у тега x:if есть необязательные атрибуты (var и scope) позволяющие не только выполнить проверку условия, но и сохранить ее в некоторую переменную для последующего многократного использования (в этом случае указывать тело условия не обязательно). В следующем примере показывается прием, когда в условии мы можем обращаться к переменным полученным как параметр формы.

select="$bookshelf/bookshelf/book[@id = $param:bid]"var="xxx"/>

Теперь разберем то, как работать со сложными условиями, когда у нас две или более ветви вычислений:

select="$bookshelf/bookshelf/book"var="book">

select="$book/title"/>

select="count($book/authors/author) = 0"> У книги нет авторов, вообще. select="count($book/authors/author) = 1"> Только один автор Количество авторов неизвестно, но их точно более чем один

Последний тег в разделе посвященном работе с xml – это x:transform. Его назначение выполнять xsl-трансформацию некоторого xml-документа с помощью xsl-документа в другой xml или html-документ. Для следующего примера я создал небольшой xsl-файлик:

transbook.xsl
xmlversion="1.0"encoding="UTF-8"?>version="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform">method="xml"version="1.0"encoding="UTF-8"indent="yes"/>match="/">select="bookshelf/book">

select="title"disable-output-escaping="yes"/>

    select="authors/author">
  • select="."disable-output-escaping="yes"/>

Для дальнейшего примера вам нужно удостовериться, что в папке lib веб-приложения есть библиотека xerces, а теперь, поехали дальше.

У тега transform есть два обязательных атрибута: xml – содержит входные данные для трансформации, и атрибут xslt, задающий правила по которым трансформация будет выполнена. Вот только … неожиданный момент, что оба входные параметр xslt – это не xml-документы созданный с помощью x:parse, а строки текста с их значениями.

var="bookshelf">url="book.xml"charEncoding="utf-8"/>var="transbook">url="transbook.xsl"charEncoding="utf-8"/>xml="${bookshelf}"xslt="${transbook}"/>

Одна из приятных (правка никогда не использованных мною) возможностей – это создание из тегов transform настоящей цепочки обработки данных. Когда результат первого преобразования xml-я подается на вход еще одному тегу transform, а результат второго преобразования – на вход третьему …

var="transbook_0">url="transbook_0.xsl"charEncoding="utf-8"/>var="transbook_1">url="transbook_1.xsl"charEncoding="utf-8"/>var="transbook_2">url="transbook_2.xsl"charEncoding="utf-8"/>xslt="${transbook_2}">xslt="${transbook_1}">xslt="${transbook_0}"xml="${bookshelf}"/>

Еще одна полезная методика позволяющая управлять выполнением трансформаций – это передача в xsl-файл переменных извне. Я обновил xsl-файл, добавил внутри корневого элемента, элемента param, а затем внутри template обрабатывающего элемент “/” я вывел переменную с именем fio. Откуда же она взялась?

version="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform">method="xml"version="1.0"encoding="UTF-8"indent="yes"/>name="fio"/>match="/">

select="$fio"disable-output-escaping="yes"/>

select="bookshelf/book">

select="title"disable-output-escaping="yes"/>

    select="authors/author">
  • select="."disable-output-escaping="yes"/>

А переменная поступила из jstl-кода (единственный недостаток в том, что нельзя передать внутрь xsl-файла произвольный узел xml – только строки):

xml="${bookshelf}"xslt="${transbook}">name="fio"value="Petyano"/>

Источник — http://black-zorro.com/mediawiki/JSTL:_Шаблоны_для_разработки_веб-приложений_в_java._Часть_2

Теги: j2eejspjstlpatternstaglib

Еще от автора

Применение WeakHashmap для списков слушателей

В статье от 11мая 1999 года Reference Objects были описаны основные идеи применения ссылочных объектов, но не приводилось детального описания. Данная статья позволит вам получить больше сведений, касающихся данной темы. В основном ссылочные объекты применяются для косвенных ссылок на память необходимую объектам. Ссылочные объекты хранятся в очереди (класс ReferenceQueue), в которой отслеживается доступность ссылочных объектов. Исходя из типа ссылочного объекта, сборщик мусора может освобождать память даже тогда, когда обычные ссылки не могут быть освобождены.

Заставки в Mustang

Согласно определению, данному в Wikipedia, заставка - это компьютерный термин, обозначающий рисунок, появляющийся во время загрузки программы или операционной системы. Заставка для пользователя является визуальным отображением инициализации программы. До выхода версии Java SE 6 (кодовое название Mustang) единственной возможностью применения заставки было создание окна, во время запуска метода main, и размещение в нем картинки. Хотя данный способ и работал, но он требовал полной инициализации исполняемой Java среды до появления окна заставки. При инициализации загружались библиотеки AWT и Swing, таким образом, появление заставки задерживалось. В Mustang появился новый аргумент командной строки, значительно облегчающий использование заставок. Этот способ позволяет выводить заставку значительно быстрее до запуска исполняемой Java среды. Окончательное добавление данной функциональности находится на рассмотрении в JCP.

Совмещение изображений

1 Введение 2 Правила визуализации и пример 3 Совмещение изображений в оперативной памяти 4 Постепенное исчезновение изображения 5 Ссылки и дополнительная информация

Еще по теме

Применение WeakHashmap для списков слушателей

В статье от 11мая 1999 года Reference Objects были описаны основные идеи применения ссылочных объектов, но не приводилось детального описания. Данная статья позволит вам получить больше сведений, касающихся данной темы. В основном ссылочные объекты применяются для косвенных ссылок на память необходимую объектам. Ссылочные объекты хранятся в очереди (класс ReferenceQueue), в которой отслеживается доступность ссылочных объектов. Исходя из типа ссылочного объекта, сборщик мусора может освобождать память даже тогда, когда обычные ссылки не могут быть освобождены.

Заставки в Mustang

Согласно определению, данному в Wikipedia, заставка - это компьютерный термин, обозначающий рисунок, появляющийся во время загрузки программы или операционной системы. Заставка для пользователя является визуальным отображением инициализации программы. До выхода версии Java SE 6 (кодовое название Mustang) единственной возможностью применения заставки было создание окна, во время запуска метода main, и размещение в нем картинки. Хотя данный способ и работал, но он требовал полной инициализации исполняемой Java среды до появления окна заставки. При инициализации загружались библиотеки AWT и Swing, таким образом, появление заставки задерживалось. В Mustang появился новый аргумент командной строки, значительно облегчающий использование заставок. Этот способ позволяет выводить заставку значительно быстрее до запуска исполняемой Java среды. Окончательное добавление данной функциональности находится на рассмотрении в JCP.

Использование потоков

1 Введение 2 Работа с выражениями типа Boolean 3 Класс JoptionPane 4 Приложение-счетчик 5 Ссылки

Перехват необрабатываемых исключений

В статье от 16 марта 2004 года Best Practices in Exception Handling были описаны приемы обработки исключений. В данной статье вы изучите новый способ обработки исключений при помощи класса UncaughtExceptionHandler добавленного в J2SE 5.0.

Использование класса LinkedHashMap

1 Введение 2 Сортировка хэш-таблицы 3 Копирование таблицы 4 Сохранение порядка доступа к элементам 5 Ссылки

Сказ про кодировки и java

С кодировками в java плохо. Т.е., наоборот, все идеально хорошо: внутреннее представление строк – Utf16-BE (и поддержка Unicode была с самых первых дней). Все возможные функции умеют преобразовывать строку из маленького регистра в большой, проверять является ли данный символ буквой или цифрой, выполнять поиск в строке (в том числе с регулярными выражениями) и прочее и прочее. Для этих операций не нужно использовать какие-то посторонние библиотеки вроде привычных для php mbstring или iconv. Как говорится, поддержка многоязычных тестов “есть в коробке”. Так откуда берутся проблемы? Проблемы возникают, как только строки текста пытаются “выбраться” из jvm (операции вывода текста различным потребителям) или наоборот пытаются в эту самую jvm “залезть” (операция чтения данных от некоторого поставщика).