Главная » XSLT » Заполнение формы

0

Задача

Требуется объединить XML-данные с формой перед отправкой ее клиенту.

Решение

Если HTML-документ соответствует спецификации XHTML или хотя бы на­писан с учетом требований XML, то с помощью XSLT-преобразования его можно объединить с данными, хранящимися в формате XML. В этом рецепте мы объеди­ним данные из XML-документа с шаблонной HTML-формой. Представьте, на­пример, что дизайнер подготовил форму, которую пользователь должен запол­нить перед совершением покупки в Интернет-магазине. В эту форму нужно добавить налог с продаж, величина которого зависит от штата, указанного пользо­вателем при вводе адреса для выставления счета. Поскольку и штат, в пользу ко­торого компания взимает налог, и ставка налога могут изменяться, «зашивать» их в форму было бы неправильно. Вместо этого сервер мог бы подставить нужные данные в форму динамически, применив XSLT-преобразование.

Данные о ставках налога можно хранить (или извлекать из базы данных) в таком виде:

<salesTax> <state>

<name>AL</name> <tax>4</tax> </state> <state>

<name>AK</name> <tax>0</tax> </state> <state>

<name>AZ</name> <tax>5.6</tax> </state>

<state>

<name>WY</name> <tax>4</tax> </state> </salesTax>

А заготовка формы может выглядеть так:

<html> <head>

<title>Check Out</title>

<script type="text/javascript" language="JavaScript"> <!–

/* Инициaлизиpовaть налог для штата по умолчанию */ setTax(document.customerlnfo.billState)

/* nepec4^a^ налог пpи измeнeнии штата */

function setTax(field) {

var value = new String(field.value)

var commaPos = value.indexOf(",")

var taxObj = document.customerInfo.tax

var tax = value.substr(commaPos + 1)

var subtotalObj = document.customerlnfo.subtotal

taxObj.value = tax

document.customerlnfo.total.value =

parseFloat(subtotalObj.value) +

(parseFloat(subtotalObj.value) * parseFloat(tax) / 100.00)

}

– >

</script> </head>

<body bgcolor="#FFFFFF" text="#000000"> <h1>Pacчeт</h1>

<form name="customerInfo" method="post" action="">

<table width="70%" border="0" cellspacing="3" cellpadding="3"> <tr>

<td width="7%">&#xa0;</td> <td width="32%">

<div align="center"><b>Aдpec доcтaвки</b></div> </td>

<td width="2 0%">&#xa0;</td> <td width="7%">&#xa0;</td> <td width="34%">

<div align="center"><b>Aдpec для выcтaвлeния cчeтa</b></div>

</td> </tr> <tr>

<td width="7%">Фамилия</td> <td width="32%">

<input type="text" name="shipName" maxlength="40" size="50" border="0" align="absmiddle"/> </td>

<td width="2 0%">&#xa0;</td> <td width="7%">Фамилия</td> <td width="3 4%">

<input type="text" name="billName" maxlength="40" size="50" border="0" align="absmiddle"/> </td> </tr> <tr>

<td width="7%">Aдрес</td> <td width="32%">

<input type="text" name="shipAddr" maxlength="40" size="50" border="0"

align="absmiddle"/> </td>

<td width="2 0%">&#xa0;</td> <td width="7%">Aдрес</td> <td width="34%">

<input type="text" name="billAddr" maxlength="40" size="50" border="0" align="absmiddle"/> </td> </tr> <tr>

<td width="7%">Город</td> <td width="32%">

<input type="text" name="shipCity" maxlength="40" size="50" border="0" align="absmiddle"/> </td>

<td width="2 0%">&#xa0;</td> <td width="7%">Город</td> <td width="34%">

<input type="text" name="billCity" maxlength="40" size="50" border="0" align="absmiddle"/> </td> </tr> <tr>

<td width="7%">Штат</td> <td width="32%">

<select name="shipState" size="1" align="absmiddle"> </select> </td>

<td width="2 0%">&#xa0;</td> <td width="7%">Штат</td> <td width="34%">

<select name="billState" size="1" align="absmiddle"

onChange="setTax(this)">

</select> </td> </tr> <tr>

<td width="7%">Почтовый индекс</td> <td width="32%">

<input type="text" name="shipZip" maxlength="10" size="15" border="0" align="absmiddle"/> </td>

<td width="2 0%">&#xa0;</td>

<td width="7%">Почтовый индекс</td>

<td width="34%">

<input type="text" name="billZip" maxlength="10" size="15" border="0" align="absmiddle"/> </td> </tr> <tr>

<td width="7%">&#xa0;</td> <td width="32%">&#xa0;</td> <td width="2 0%">&#xa0;</td> <td width="7%">&#xa0;</td> <td width="34%">&#xa0;</td> </tr> <tr>

<td width="7%">&#xa0;</td> <td width="32%">&#xa0;</td> <td width="2 0%">&#xa0;</td> <td width="7%">Cумма</td> <td width="34%">

<input type="text" name="subtotal" readonly="1" value="10 0.0 0"/> </td> </tr> <tr>

<td width="7%">&#xa0;</td> <td width="32%">&#xa0;</td> <td width="2 0%">&#xa0;</td>

<td width="7%">Hалог</td> <td width="34%">

<input type="text" name="tax" readonly="1"/> </td> </tr> <tr>

<td width="7%">&#xa0;</td> <td width="32%">&#xa0;</td> <td width="2 0%">&#xa0;</td> <td width="7%">Итого</td> <td width="34%">

<input type="text" name="total" readonly="1"/> </td> </tr> </table> </form> </body> </html>

Объединение сводится к преобразованию, в котором действие по умолча­нию – это копирование HTML-содержимого в выходной файл (см. рецепт 6.5). Встретив же элементы select для штатов в адресе доставки и выставления сче­та, преобразование вставляет данные из XML-документа в виде элементов option. Чтобы не усложнять пример, я включил и название штата, и ставку на­лога в атрибут value элемента option, но можно было бы написать функцию сопоставления на JavaScript.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:import href="../util/copy.xslt"/>

<xsl:output method="html"/>

<xsl:template match="html"> <xsl:copy>

<xsl:apply-templates/> </xsl:copy> </xsl:template>

<xsl:template match="select[@name=’shipState’ or @name=’billState’]"> <xsl:copy>

<xsl:copy-of select="@*"/>

<xsl:for-each select="document(‘salesTax.xml’)/salesTax/state"> <option value="{name}’,’,{tax}"> <xsl:value-of select="name"/>

</option> </xsl:for-each> </xsl:copy> </xsl:template>

</xsl:stylesheet>

Обсуждение

Понятно, что для решения задачи, рассмотренной в этом примере, существу­ют и другие, быть может, более подходящие технологии (на ум сразу приходят ASP и JSP). Однако есть два аспекта, которые, возможно, заставят вас предпо­честь решение на основе XSLT.

Во-первых, отметим, что заготовка формы – это стандартный HTML-код, в нем нет никаких серверных элементов. Небольшой фрагмент клиентского сце­нария имеется, но его можно вставить и в процессе XSLT-преобразования. Автору заготовки ничего не нужно знать о технологии, с помощью которой форма будет заполняться на стороне сервера. Вообще, у автора этой Web-страницы может не быть никакого опыта программирования. С другой стороны, автору преобразова­ния нет нужды что-то знать об HTML или графическом дизайне1. Они лишь дол­жны договориться между собой о содержимом и схеме именования. Таким обра­зом, XSLT-преобразование динамического контента обеспечивает настоящее разделение обязанностей, чего так недостает другим методикам.

Во-вторых, с помощью преобразований можно не просто вставлять содержи­мое; его можно частично удалить или реорганизовать, не замусоривая HTML-код не свойственными ему конструкциями.

См. также

Ограничения по времени и месту не позволили мне рассмотреть в этой книге XForms, но интересующемуся читателю я настоятельно рекомендую познако­миться с этой новой технологией (http://www.w3.org/MarkUp/Forms/). В доку­ментах консорциума W3C XForms описывается следующим образом:

Используемые в настоящий момент Web-формы не обеспечивают отделения содержимого формы от его представления. Напротив, в XForms-форме предусмот­рены разделы, описывающие, для чего форма предназначена и как она выглядит. Это позволяет гибко присоединять к XML-определению формы различные спосо­бы представления, в том числе и классические XHTML-формы.

Перечислим основные задачи, которые призвана решать технология XForms:

?               поддержка браузеров в карманных, телевизионных и настольных устрой­ствах, а также принтеров и сканеров;

?               развитый пользовательский интерфейс, отвечающий потребностям бизне­са, бытового потребителя и приложений для управления устройствами;

?               разделение данных, логики и представления;

?               улучшенная поддержка интернационализации;

?               поддержка структурирования данных в форме;

?               развитая логика работы форм;

?               поддержка размещения нескольких форм на странице и многостранич­ных форм;

?               поддержка операций приостановки и возобновления;

?               естественная интеграция с другими наборами XML-тегов.

Мангано Сэл  XSLT. Сборник рецептов. – М.: ДМК Пресс, СПБ.: БХВ-Петербург, 2008. – 864 с.: ил.

По теме:

  • Комментарии