Учебное пособие (1075724), страница 48
Текст из файла (страница 48)
Если количествоошибок больше нуля, то выводится сообщение об ошибках с помощью функцииxrx_example:ShowErrorReturnForm().)};(: ++++++++++++++++++++++++++++++++++++++++++++++ :)(: Преобразование XSLT для отчета :)(: ++++++++++++++++++++++++++++++++++++++++++++++ :)declare function local:transform_report($param as node(),$report_format as xs:string) as node()*{Функция выполняет XSLT-преобразование данных, которые были полученыв результате выполнения динамически сформированного запроса в HTML.(: Параметры преобразования :)let$XSLTFile := concat(xrx_example:BaseCurrentURL(), "report.xsl"),Для преобразования используется файл "report.xsl".$params :=<parameters><param name="report_format" value="{$report_format}"/></parameters>В качестве параметра в преобразование передается тип форматированияотчета (списком или таблицей), этот параметр задается в форме ввода параметров.let $TransformRes := transform:transform($param,xs:anyURI($XSLTFile), $params)455return $TransformResФункциявозвращаетHTML-фрагмент,которыйсоответствуетрезультирующим данным, представленным в виде таблицы или списка.};(: ++++++++++++++++++++++++++++++++++++++++++++++ :)(: Формирование запроса для отчета.Запрос формируется в виде строки, содержащей XQuery-запрос.В дальнейшем этот запрос будет динамически интерпретирован ивыполнен с помощью функции util:eval(аналогично динамическому SQL) :)(: ++++++++++++++++++++++++++++++++++++++++++++++ :)declare function local:MakeReportQuery($Data as node()) as xs:string{(Размершрифтаздесьнемногоуменьшен,чтобысохранилосьформатирование.)В этой функции динамически формируется XQuery-запрос на выборкуданных на основе параметров отчета, введенных в форме.
Задача функции –сформировать строку, содержащую XQuery-запрос.Этот запрос снабжен большим количеством комментариев, поэтому здесь мытолько поясним подход к формированию таких запросов.Вначале выбираются необходимые для отчета данные с помощью вложенныхконструкций for и let.Затем формируется «пустой» оператор where (1=1).Далее проверяется каждый параметр отчета. Если параметр заполнен, тосоответствующее этому параметру условие добавляется в секцию «where».Например, если задан фрагмент наименования компьютера, то в отчетпопадают только такие компьютеры, в название которых входит этот фрагмент.let$t1 := concat("(: report_data - корневой элемент данных :)", " ","<report_data>", " ", "{ ", " ","let ", " ","(: Документ, содержащий информацию о процессорах :)", " ","$Processors := doc('", xrx_example:ProcessorsFileName(), "')//processors, ", " ","(: Коллекция, содержащая даные о компьютерах :)", " ",456"$ComputersList := collection('", xrx_example:PathURI_data_list_in_db("computer"), "')", " ",""for ", " ",(: Перебор всех всех файлов в коллекции, из каждого файла читается корневой элементcomputer :)", " ",""$Computer in $ComputersList//computer ", " ",let ", " ","(: Название компьютера выделяется в отдельную переменную для удобства сортировки :)","$computer_name := $Computer/computer_name, ", " ","(: Для каждого компьютера по id процессора читается название процессора :)", " ","$processor_name := $Processors//processor[@id=$Computer/processor_id]/processor_name "," "," ","(: where - условия выборки, (1=1) - заглушка для where, если далее не задано никакихусловий :)", " ","where (1=1) ", " "),$t2 := concat($t1,if($Data/computer_name = "") then ("")else(concat("(: Если пользователь указал часть названия компьютера, то этот параметр должен входить какподстрока в названия компьютеров :)", " ","and (fn:contains($Computer/computer_name, '", $Data/computer_name, "')) ", " "))),$t3 := concat($t2,if($Data/processor_id = "") then ("")else(concat("(: Параметр отчета 'процессор' возвращается в виде набора id-элементов, соединенныхпробелами :)", " ","(: Поэтому нужно проверить, не входит ли id текущего компьютера в эту строку :)", " ","and (fn:contains('", $Data/processor_id, "', $Computer/processor_id)) ", " "))),$t4 := concat($t3,if($Data/op1 castable as xs:integer)then(concat("(: Ограничение снизу на объем ОП :)", " ","and (xs:integer($Computer/op) >= xs:integer('", $Data/op1, "')) ", " "))else ("")),$t5 := concat($t4,if($Data/op2 castable as xs:integer)457then(concat("(: Ограничение сверху на объем ОП :)", " ","and (xs:integer($Computer/op) <= xs:integer('", $Data/op2, "')) ", " "))else ("")),$t6 := concat($t5,if($Data/server = "nofilter") then ("")else(concat("(: Проверка признака сервера :)", " ","and ($Computer/server = '", $Data/server, "') ", " "))),(: Проверка того, что в заданном диапазоне было хотя бы одно обновление :)(: Проверка что существует хотя бы один элемент upgrade, дата которого соответственно больше илименьше заданной границы :)(: Здесь могла быть более сложная проверка на пересечение диапазона в запросе и диапазона обновлений:)$t7 := concat($t6,if($Data/upgrade_date1 castable as xs:date)then(concat("(: Проверка того, что хотя бы одно обновление было позже параметра :)", " ","and (fn:exists($Computer/upgrades/upgrade[xs:date(upgrade_date) >= xs:date('",$Data/upgrade_date1, "')])) ", " "))else ("")),$t8 := concat($t7,if($Data/upgrade_date2 castable as xs:date)then(concat("(: Проверка того, что хотя бы одно обновление было ранее параметра :)", " ","and (fn:exists($Computer/upgrades/upgrade[xs:date(upgrade_date) <= xs:date('",$Data/upgrade_date2, "')])) ", " "))else ("")),$OrderBy := concat($t8,"(: Сортировка :)", " ","order by ", $Data/order_field, "", $Data/order_type, "", " "),$Result := concat($OrderBy,458"(: Возвращаемые данные :)", " ","return ", " ","<computer> ", " ", "{ ", " ","$Computer/computer_name, ", " ","$processor_name, ", " ","$Computer/op, ", " ","$Computer/hdd, ", " ","$Computer/server, ", " ",""$Computer/upgrades ", " ",}", " ", "</computer> ", " ","}", " ", "</report_data> ")return $Result};(: ++++++++++++++++++++++++++++++++++++++++++++++ :)(: Формирование отчета :)(: ++++++++++++++++++++++++++++++++++++++++++++++ :)declare function local:Report($Data as node()) as node()*{let$ReportFormat := xs:string($Data/report_format),Как форматировать отчет – списком или таблицей.$CurrentCssURI := xrx_example:PathURI_current_css(),Путь к таблице стилей CSS.$Query := local:MakeReportQuery($Data),Формирование текста XQuery-запроса на выборку данных.$ReportData := util:eval($Query),Выполнение запроса и получение данных.$XSLTResult := local:transform_report($ReportData, $ReportFormat)Преобразование данных в HTML с помощью XSLT-преобразования.returnФормирование результирующего документа в формате HTML.<html xmlns="http://www.w3.org/1999/xhtml"xmlns:xforms="http://www.w3.org/2002/xforms"xmlns:ev="http://www.w3.org/2001/xml-events"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF8"/>459<style type="text/css"><!-- Добавление стилей CSS с помощью XInclude --><xi:include xmlns:xi="http://www.w3.org/2001/XInclude"href="{$CurrentCssURI}"/></style></head><body><h1>Результат отчета</h1><div>{$XSLTResult}</div>Переменная$XSLTResultсодержитданныеотчета,которыебылипреобразованы в HTML с помощью XSLT-преобразования.<hr/><h2>Текст запроса</h2><big><big><pre>{$Query}</pre></big></big>Переменная $Query содержит текст запроса и выводится для справки.</body></html>};(: ++++++++++++++++++++++++++++++++++++++++++++++ :)(: Сохранение условий для формирования отчета :)(: ++++++++++++++++++++++++++++++++++++++++++++++ :)declare function local:PreReport() as node()*Параметрыотчета,переданныеизXForms-формы,сохраняютсявсессионную переменную.{(: Если сессия не создана, то она создается :)session:create(),session:set-attribute($report_params_data, ""),let$PostData := request:get-data(),$Data := fn:root($PostData)//report_paramsreturnsession:set-attribute($report_params_data, $Data)};460(: ++++++++++++++++++++++++++++++++++++++++++++++ :)(: Модели данных формы :)(: ++++++++++++++++++++++++++++++++++++++++++++++ :)declare function local:CreateXFormsModels($ProcessorReadURI asxs:string, $PreReportURI as xs:string) as node()*{Функция генерирует модель данных для формы ввода параметров отчета иограничения на вводимые параметры с помощью xforms:bind.((: Основная модель данных :)<xforms:model id="computer_model"><!-- Основные данные (о компьютере) --><xforms:instance id="computer_instance" xmlns=""><report_params><computer_name/><processor_id/><op1/><op2/><server>nofilter</server><upgrade_date1/><upgrade_date2/><order_field>$computer_name</order_field><order_type>ascending</order_type><report_format>table</report_format></report_params></xforms:instance><!-- Граничные значения для ОП - целого типа --><xforms:bind nodeset="//op1" type="xforms:int" /><xforms:bind nodeset="//op2" type="xforms:int" /><!-- Граничные значения для даты модернизации - поле типа дата --><xforms:bind nodeset="//upgrade_date1" type="xforms:date" />461<xforms:bind nodeset="//upgrade_date2" type="xforms:date" /><!-- Отправка формы --><xforms:submission replace="none" action="{$PreReportURI}"method="post" id="submit_id" includenamespaceprefixes=""/></xforms:model>),((: Данные для выбора типов процессоров :)<xforms:model id="processor_model"><xforms:instance id="processor_instance" xmlns=""src="{$ProcessorReadURI}"/></xforms:model>)};(: ++++++++++++++++++++++++++++++++++++++++++++++ :)(: Редактирование формы :)(: ++++++++++++++++++++++++++++++++++++++++++++++ :)declare function local:EditForm($ReportURI as xs:string) as node(){Функция генерирует поля ввода для формы ввода параметров отчета.<div><table border="1" align="center" ><tr><th colspan="2" align="right">Подстрока, которую должносодержать наименование компьютера:</th><td><xforms:input model="computer_model" ref="computer_name"/></td></tr><tr><th colspan="2" align="right">Типы процессоров:</th><td>462<xforms:select model="computer_model" ref="processor_id"><xforms:itemset model="processor_model"nodeset="//processor"><xforms:value ref="@id"/><xforms:label ref="processor_name"/></xforms:itemset></xforms:select></td></tr><tr><th rowspan="2" align="right">Ограничение для объема ОП</th><th align="right">Минимальное:</th><td><xforms:input model="computer_model" ref="op1"><xforms:alert>Значение должно быть целымчислом</xforms:alert></xforms:input></td></tr><tr><th align="right">Максимальное:</th><td><xforms:input model="computer_model" ref="op2"><xforms:alert>Значение должно быть целымчислом</xforms:alert></xforms:input></td></tr><tr><th colspan="2" align="right">Используется как сервер:</th><td><xforms:select1 model="computer_model" ref="server"><xforms:choices>463<xforms:item><xforms:label>Нет фильтра</xforms:label><xforms:value>nofilter</xforms:value></xforms:item><xforms:item><xforms:label>Да</xforms:label><xforms:value>true</xforms:value></xforms:item><xforms:item><xforms:label>Нет</xforms:label><xforms:value>false</xforms:value></xforms:item></xforms:choices></xforms:select1></td></tr><tr><th rowspan="2" align="right">Были модернизации вдиапазоне</th><th align="right">От:</th><td><xforms:input model="computer_model" ref="upgrade_date1"><xforms:alert>Значение должно быть датой</xforms:alert></xforms:input></td></tr><tr><th align="right">До:</th><td><xforms:input model="computer_model" ref="upgrade_date2"><xforms:alert>Значение должно быть датой</xforms:alert></xforms:input></td></tr>464<tr><th colspan="3" align="center">Сортировка по полю:<xforms:select1 model="computer_model" ref="order_field"><xforms:choices><xforms:item><xforms:label>Название компьютера</xforms:label><xforms:value>$computer_name</xforms:value></xforms:item><xforms:item><xforms:label>Название процессора</xforms:label><xforms:value>$processor_name</xforms:value></xforms:item></xforms:choices></xforms:select1><xforms:select1 model="computer_model" ref="order_type"><xforms:choices><xforms:item><xforms:label>по возрастанию</xforms:label><xforms:value>ascending</xforms:value></xforms:item><xforms:item><xforms:label>по убыванию</xforms:label><xforms:value>descending</xforms:value></xforms:item></xforms:choices></xforms:select1></th></tr><tr><th colspan="2" align="right">Форматировать отчет:</th><td>465<xforms:select1 model="computer_model" ref="report_format"><xforms:choices><xforms:item><xforms:label>таблицей</xforms:label><xforms:value>table</xforms:value></xforms:item><xforms:item><xforms:label>списком</xforms:label><xforms:value>list</xforms:value></xforms:item></xforms:choices></xforms:select1></td></tr><tr><td colspan="3" align="center"><xforms:trigger><xforms:label>Сформировать отчет</xforms:label><xforms:action ev:event="DOMActivate" if="isvalid(instance('computer_instance'))"><!-- Данные передаются на сервер и сохраняются в сессионнойпеременной --><xforms:send submission="submit_id" /><!-- Данные читаются из сессионной переменной, проверяются ипередаются для формирования отчета --><xforms:load show="replace" resource="{$ReportURI}"/></xforms:action></xforms:trigger></td></tr></table></div>};466(: ++++++++++++++++++++++++++++++++++++++++++++++ :)(: Форма параметров отчета :)(: ++++++++++++++++++++++++++++++++++++++++++++++ :)declare function local:ReportForm() as node(){Функция генерирует XHTML-документ, содержащий XForms-форму вводапараметров отчета.let$ProcessorReadURI :=xrx_example:PathURI_data_list($module_processor_id,$module_processor_ver),(: К названию текущего скрипта добавляется параметр ?prereport=1 :)$CurrentScriptName := xrx_example:FileNameFromCurrentURL(),$PreReportURI := concat($CurrentScriptName, "?prereport=1"),$ReportURI := concat($CurrentScriptName, "?report=1"),$CurrentCssURI := xrx_example:PathURI_current_css(),$XFormsCssURI := xrx_example:PathURI_xforms_css(),$form :=<html xmlns="http://www.w3.org/1999/xhtml"xmlns:xforms="http://www.w3.org/2002/xforms"xmlns:ev="http://www.w3.org/2001/xml-events"><head><meta http-equiv="Content-Type" content="text/html;charset=UTF8"/><style type="text/css"><!-- Добавление стилей CSS с помощью XInclude --><xi:include xmlns:xi="http://www.w3.org/2001/XInclude"href="{$CurrentCssURI}"/><xi:include xmlns:xi="http://www.w3.org/2001/XInclude"href="{$XFormsCssURI}"/></style><!-- Модель создается в секции head -->{ local:CreateXFormsModels($ProcessorReadURI, $PreReportURI) }</head>467<body><h1>Параметры отчета</h1><!-- Поля редактирования формы -->{ local:EditForm($ReportURI) }</body></html>(: сгенерированный XForms-документ обрабатывается с помощью XSLTпреобразования для получения HTML-документа :)return xrx_example:transform_xsltforms($form)};7.3.5.6.2 XSLT-преобразование report.xslФайл «report.xsl» используется для преобразования данных отчета из XML вHTML.На вход преобразование получает данные отчета (корневой элемент«report_data»), на выходе генерируется фрагмент HTML-документа.<?xml version="1.0" encoding="utf-8"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"version="1.0"><xsl:param name="report_format" select="string('table')"/>Параметр «report_format», который передается в преобразование, определяеттип форматировния отчета – в виде таблицы или в виде списка.<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--><!-- Шаблон обработки корневого элемента XML - документа --><xsl:template match="/"><div><xsl:apply-templates/></div></xsl:template>Шаблон для корневого элемента оборачивает результат преобразования вэлемент «div».<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-->468<!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--><xsl:template match="report_data">Шаблонпреобразованиядляосновногоэлементаданныхотчета«report_data».<xsl:choose><xsl:when test="$report_format='table'">Если задано форматирование в виде таблицы ($report_format='table'), тоформируется шапка таблицы, затем данные выводятся в виде строк таблицы.<table border="1"><tr><th>Наименование</th><th>Тип процессора</th><th>Объем ОП (в Мб)</th><th>Объем жесткого диска (в Гб)</th><th>Используется как сервер</th><th>Обновления</th></tr><xsl:for-each select="computer"><tr><td><xsl:value-of select="computer_name"/></td><td><xsl:value-of select="processor_name"/></td><td><xsl:value-of select="op"/></td><td><xsl:value-of select="hdd"/></td><td><xsl:choose><xsl:when test="server[.='true']">Да</xsl:when><xsl:otherwise>Нет</xsl:otherwise></xsl:choose></td><td><xsl:apply-templates select="upgrades"/></td></tr></xsl:for-each></table>469</xsl:when><xsl:otherwise>Иначе, если задано форматирование в виде списка, то данные выводятся ввиде элементов нумерованного списка.<ol><xsl:for-each select="computer"><li><p>Наименование: <b><xsl:value-ofselect="computer_name"/></b></p><p>Тип процессора: <b><xsl:value-ofselect="processor_name"/></b></p><p>Объем ОП (в Мб): <b><xsl:value-ofselect="op"/></b></p><p>Объем жесткого диска (в Гб): <b><xsl:value-ofselect="hdd"/></b></p><p>Используется как сервер: <b><xsl:choose><xsl:when test="server[.='true']">Да</xsl:when><xsl:otherwise>Нет</xsl:otherwise></xsl:choose></b></p><p><xsl:apply-templates select="upgrades"/></p></li></xsl:for-each></ol></xsl:otherwise></xsl:choose></xsl:template><!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--><!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--><xsl:template match="upgrades">470Модернизации компьютера (элементы «upgrade») также выводятся в видесписка или в виде таблицы.<xsl:choose><xsl:when test="$report_format='table'"><xsl:choose><xsl:when test="count(upgrade[upgrade_date andupgrade_description]) > 0"><table border="1"><tr><th>Дата</th><th>Описание</th></tr><xsl:for-each select="upgrade[upgrade_date andupgrade_description]"><tr><td><xsl:value-of select="upgrade_date"/></td><td><xsl:value-of select="upgrade_description"/></td></tr></xsl:for-each></table></xsl:when><xsl:otherwise><p>Нет обновлений</p></xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise><xsl:if test="count(upgrade[upgrade_date andupgrade_description]) > 0"><p>Список обновлений:</p>471<ol><xsl:for-each select="upgrade[upgrade_date andupgrade_description]"><li><b><xsl:value-of select="upgrade_date"/>(<xsl:value-of select="upgrade_description"/>)</b></li></xsl:for-each></ol></xsl:if></xsl:otherwise></xsl:choose></xsl:template><!-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--></xsl:stylesheet>7.3.5.6.3 Взаимодействие между сценариями модуля4722.














