|
||||
|
Глава 10Работа с API процессоров XSLT Как вы видели на протяжении всей книги, при работе с XSLT вам не требовалось никакого программирования. Но все процессоры XSLT, с которыми мы работали до сих пор, — Xalan, Saxon, XT, Oracle и MSXML — разработаны так, что при желании к ним можно обращаться и из кода программы. Здесь мы рассмотрим, как работать с этими процессорами в прикладной программе. Можете спокойно пропустить эту главу, если вы не программист или не собираетесь им становиться. Но если вы не будете использовать возможности программного интерфейса, вы потеряете довольно много, в том числе поддержку XSLT на web-серверах. В этой главе будет также показано, как преобразовывать XML в реляционную базу данных. Для взаимодействия с различными прикладными программными интерфейсами (API, Application Programming Interface) процессоров XSLT я буду применять Java и JavaScript. С различными процессорами XSLT можно работать и при помощи таких языков, как С++ или Visual Basic, но до сих пор подавляющее большинство программистов выбирало Java, а язык JavaScript удобен для обработки преобразований в Internet Explorer. Кроме того, используемые вами процессоры XSLT специально разработаны для взаимодействия с Java, хотя с процессором MSXML3 можно работать из программы как с СОМ-объектом. Как я говорил, с процессором MSXML в Internet Explorer можно работать при помощи JavaScript, такой пример был показан еще в главе 1. И, как я обещал в главе 1, здесь я рассмотрю его более подробно.
XSLT и JavaScript в Internet ExplorerЛюбите вы Microsoft или нет, нельзя отрицать тот факт, что эта фирма включает в Internet Explorer все больше средств поддержки XSLT (дополнительную информацию можно найти по адресу http://msdn.microsoft.com/xml/general/xmlparser.asp), и поэтому работа с браузером заслуживает нашего внимания. В главе 1 я представил пример создания преобразований XSLT в Internet Explorer при помощи JavaScript, и здесь мы рассмотрим этот пример подробнее. Как вы помните (см. главу 2), IE версии 5.5 и младше может осуществлять настоящие преобразования XSLT, если они реализованы на JavaScript (новый, только что вышедший IE 6.0 может разбирать непосредственно синтаксис XSLT просто путем просмотра XML-документов). В этом случае я, пользуясь MSXML и JavaScript, преобразую planets.xmlпри помощи planets.xsl. Для хранения этих документов я создаю два новых объекта, XMLDocumentи XSLDocument, опираясь на классы ActiveXObjectи DOMDocumentпроцессора MSXML в функции xslt. (Эта функция запускается сразу при загрузке страницы, поскольку я установил атрибут onloadэлемента <BODY>в « xslt()»). Я также создам объект, соответствующий элементу <DIV>, который отображает результаты преобразования: <HTML> <HEAD> <TITLE>XSLT Using JavaScript</TITLE> <SCRIPT LANGUAGE="JavaScript"> function xslt() { var XMLDocument = new ActiveXObject('MSXML2.DOMDocument.3.0'); var XSLDocument = new ActiveXObject('MSXML2.DOMDocument.3.0'); var HTMLtarget = document.all['targetDIV']; . . . И planets.xml, и planets.xslявляются документами XML; и процессор MSXML может работать и как проверяющий на допустимость разборщик XML, если установить свойство validateOnParseв true. Для загрузки planets.xmlи planets.xslв объекты XMLDocumentи XSLDocumentслужит метод load. Я также проверяю наличие ошибок, просматривая код ошибок разбора следующим образом: <HTML> <HEAD> <TITLE>XSLT Using JavaScript</TITLE> <SCRIPT LANGUAGE="JavaScript"> function xslt() { var XMLDocument = new ActiveXObject('MSXML2.DOMDocument.3.0'); var XSLDocument = new ActiveXObject('MSXML2.DOMDocument.3.0'); var HTMLtarget = document.all['targetDIV']; XMLDocument.validateOnParse = true; XMLDocument.load('planets.xml'); if (XMLDocument.parseError.errorCode != 0) { HTMLtarget.innerHTML = "Error!"; return false; } XSLDocument.validateOnParse = true; XSLDocument.load('planets.xsl'); if (XSLDocument.parseError.errorCode != 0) { HTMLtarget.innerHTML = "Error!"; return false; } . . . Теперь, после того как оба файла, planets.xmlи planets.xsl, были загружены, преобразование можно осуществить методом transformNode. Посмотрите, как я преобразую XMLDocumentпри помощи XSLDocumentи показываю результат в элементе-приемнике <DIV>: <HTML> <HEAD> <TITLE>XSLT Using JavaScript</TITLE> <SCRIPT LANGUAGE="JavaScript"> function xslt() { var XMLDocument = new ActiveXObject('MSXML2.DOMDocument.3.0'); var XSLDocument = new ActiveXObject('MSXML2.DOMDocument.3.0'); var HTMLtarget = document.all['targetDIV']; . . . HTMLtarget.innerHTML = XMLDocument.transformNode(XSLDocument); return true; } </SCRIPT> </HEAD> <BODY onload="xslt()"> <DIV ID="targetDIV"> </DIV> </BODY> </HTML> Эти результаты показаны на рис. 10.1. ![]() Рис. 10.1. Использование JavaScript для преобразования документа Обработка ошибок разбораПри использовании JavaScript для загрузки документов XML и XSL и работы с ними важно знать, как сообщать об ошибках разбора. В предыдущем примере я сообщал об ошибках, выводя сообщение «Error!» в элементе-приемнике <DIV>документа HTML, но это не очень информативно. Как получить дополнительную информацию? В следующем примере я намерено создаю ошибку разбора, изменив первый тег <PLANET>в planets.xmlна тег <PLANETS>: <?xml version="1.0"?> <?xml-stylesheet type="text/xml" href="planets.xsl"?> <PLANETS> <PLANETS> <NAME>Mercury</NAME> <MASS UNITS="(Earth = 1)">.0553</MASS> <DAY UNITS="days">58.65</DAY> <RADIUS UNITS="miles">1516</RADIUS> <DENSITY UNITS="(Earth = 1)">.983</DENSITY> <DISTANCE UNITS="million miles">43.4</DISTANCE><!--B перигелии--> </PLANET> . . . Я установил свойство validateOnParseобъекта XMLDocumentв true(значение по умолчанию — false, что означает отсутствие проверки), поэтому процессор MSXML отловит эту ошибку разбора. Объект XMLDocumentсодержит объект parseError, и если его свойство errorCodeне равно нулю, это означает наличие ошибки. Сейчас я хочу не просто вывести сообщение «Error!», а расшифровать ошибку при помощи новой функции getError, которая возвращает строку с информацией о месте и причине ошибки. С целый получения этой дополнительной информации я использую свойства <url, line, linepos и reason объекта parseError для того, чтобы определить вызвавший проблему файл, строку, позицию ошибки и ее описание (листинг 10.1). Листинг 10.1. Создание преобразования XSLT и отображение ошибок разбора<HTML> <HEAD> <TITLE>XSLT Using JavaScript</TITLE> <SCRIPT LANGUAGE="JavaScript"> function xslt() { var XMLDocument = new ActiveXObject('MSXML2.DOMDocument.3.0'); var XSLDocument = new ActiveXObject('MSXML2.DOMDocument.3.0'); var HTMLtarget = document.all['targetDIV']; XMLDocument.validateOnParse = true; XMLDocument.load('planets.xml'); if (XMLDocument.parseError.errorCode != 0) { HTMLtarget.innerHTML = getError(XMLDocument); return false; } XSLDocument.validateOnParse = true; XSLDocument.load('planets.xsl'); if (XSLDocument.parseError.errorCode != 0) { HTMLtarget.innerHTML = getError(XSLDocument); return false; } HTMLtarget.innerHTML = XMLDocument.transformNode(XSLDocument); return true; } function getError(errorObject) { var Error = new String; Error = "Error. " + errorObject.parseError.url + "<BR>" + "Line: " + errorObject.parseError.line + "<BR>" + "Character: " + errorObject.parseError.linepos + "<BR>" + "Description: " + errorObject.parseError.reason; return Error; } </SCRIPT> </HEAD> <BODY onload="xslt()"> <DIV ID="targetDIV"> </DIV> </BODY> </HTML> Результат можно увидеть на рис. 10.2, где показаны вызвавший ошибку файл, место ошибки и описание ошибки процессором MSXML. Если вы собираетесь реализовывать преобразования XSLT в Internet Explorer, когда пользователи просматривают ваши документы случайным образом, обработка подобных ошибок разбора исключительно важна. ![]() Рис. 10.2. Обработка ошибки разбора Пока что я преобразовывал при помощи процессора MSXML только документ целиком, но здесь у вас существует значительно больше возможностей. Например, в следующем разделе я воспользуюсь XSLT в Internet Explorer для сортировки данных планет в HTML-таблицы по нажатию кнопок. Для этого я буду обращаться к отдельным узлам внутри таблицы стилей. Internet Explorer и динамические стилиДля того чтобы продемонстрировать все возможности управления преобразованиями XSLT при использовании процессора MSXML, в этом примере я разрешу пользователю динамически сортировать таблицу Planets. Общая идея показана на рис. 10.3. Пользователю достаточно щелкнуть на кнопку, чтобы отсортировать таблицу по названию, массе, радиусу или дню. ![]() Рис. 10.3. Поддержка динамических преобразований XSLT Для сортировки таблицы я, как легко догадаться, применяю таблицу стилей с элементом <xsl:sort>(листинг 10.2). По умолчанию я сортирую планеты по названию. Листинг 10.2. Применение динамических XSLT-преобразований <?xml version="1.0" encoding="iso-8859-1"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.1"> <xsl:template match="/"> <HTML> <HEAD> <TITLE> The Sorted Planets Table </TITLE> </HEAD> <BODY> <H1> The Sorted Planets Table </H1> <TABLE BORDER="2"> <TR> <TD>Name</TD> <TD>Mass</TD> <TD>Radius</TD> <TD>Day</TD> </TR> <xsl:apply-templates select="/PLANETS/PLANET"> <xsl:sort select="NAME" order="ascending"/> </xsl:apply-templates> </TABLE> </BODY> </HTML> </xsl:template> <xsl:template match="PLANET"> <TR> <TD><xsl:value-of select="NAME"/></TD> <TD><xsl:value-of select="MASS"/></TD> <TD><xsl:value-of select="RADIUS"/></TD> <TD><xsl:value-of select="DAY"/></TD> </TR> </xsl:template> </xsl:stylesheet> Эта таблица стилей сортирует планеты в алфавитном порядке по их названиям; но есть и другие возможности: можно позволить пользователю осуществлять сортировку и по другому критерию. Для этого выберите в данной таблице стилей атрибут selectэлемента <xsl:sort>и при помощи JavaScript измените его динамически с «NAME» на «MASS», «RADIUS» или на другой критерий по желанию пользователя, и затем снова выполните преобразование XSLT. При повторном осуществлении преобразования появится новая таблица с новым порядком сортировки. В качестве первого шага в создании нужной нам HTML-страницы я загружу planets.xmlи требуемую таблицу стилей и выполню сортировку по умолчанию, то есть по названию планет: <HTML> <HEAD> <TITLE> Applying Dynamic Styles </TITLE> <SCRIPT LANGUAGE="JavaScript"> var XMLDocument; var XSLDocument; var HTMLtarget; function initialize() { XMLDocument = new ActiveXObject('MSXML2.DOMDocument.3.0'); XSLDocument = new ActiveXObject('MSXML2.DOMDocument.3.0'); HTMLtarget = document.all['targetDIV']; XMLDocument.validateOnParse = true; XMLDocument.load('planets.xml'); if (XMLDocument.parseError.errorCode != 0) { HTMLtarget.innerHTML = "Error!"; return false; } XSLDocument.validateOnParse = true; XSLDocument.load('planets.xsl'); if (XSLDocument.parseError.errorCode != 0) { HTMLtarget.innerHTML = "Error!"; return false; } HTMLtarget.innerHTML = XMLDocument.transformNode(XSLDocument); } . . . Эту часть вы уже видели раньше. Но пользователь теперь может отсортировать таблицу щелчком мыши по массе, радиусу и т.д. Для новой сортировки таблицы я написал функцию sort— ей при щелчке на кнопке передается имя узла (например, «MASS»), по которому нужно провести сортировку. Вот как создаются различные кнопки, показанные на рис. 10.3: <INPUT ТУРЕ="BUTTON" ONCLICK="sort('NAME')" VALUE="Sort by name"></INPUT> <INPUT TYPE="BUTTON" ONCLICK="sort('MASS')" VALUE="Sort by mass"></INPUT> <INPUT TYPE="BUTTON" ONCLICK="sort('RADIUS')" VALUE="Sort by radius"></INPUT> <INPUT TYPE="BUTTON" ONCLICK="sort('DAY')" VALUE="Sort by day"></INPUT> Затем в функции sortя хочу выполнить новую сортировку по имени переданного узла. Для этого я изменяю атрибут selectэлемента <xsl:sort>на имя нового узла, по которому нужно сортировать. Вот как теперь выглядит атрибут select. <xsl:apply-templates select="/PLANETS/PLANET"> <xsl:sort select="NAME" order="ascending"/> </xsl:apply-templates> Я могу обратиться к этому узлу из таблицы стилей, теперь хранимой в объекте XSLDocument, передав в метод selectSingleNodeупомянутого объекта выражение XPath. Метод selectSingleNodeвозвращает объект node, и можно изменить текстовое значение узла при помощи свойства nodeValueобъекта node. В таком случае я только устанавливаю атрибут select в имя нового узла, по которому будет вестись сортировка: <HTML> <HEAD> <TITLE> Applying Dynamic Styles </TITLE> <SCRIPT LANGUAGE="JavaScript"> function initialize() { . . . }
(XSLDocument.selectSingleNode("//xsl:sort/@select")).nodeValue = sortNode; . . . } </SCRIPT> . . Теперь все, что осталось сделать, — снова выполнить преобразование и вывести результаты: <HTML> <HEAD> <TITLE> Applying Dynamic Styles </TITLE> <SCRIPT LANGUAGE="JavaScript"> function initialize() { . . . } function sort(sortNode) { (XSLDocument.selectSingleNode("//xsl:sort/@select")).nodeValue = sortNode; HTMLtarget.innerHTML = XMLDocument.transformNode(XSLDocument); } </SCRIPT> </HEAD> . . . Операция завершена. Результаты показаны на рис. 10.3. При щелчке на кнопке таблица сортируется заново по выбранному значению узла (имейте в виду, что сортировка ведется по алфавиту; сортировка по числовым значениям обсуждается в главе 5, где описывается элемент <xsl:sort>) и отображается еще раз с новым порядком сортировки. Вот вся HTML-страница (листинг 10.3). Листинг 10.3. Применение динамических XSLT-преобразований <HTML> <HEAD> <TITLE> Applying Dynamic Styles </TITLE> <SCRIPT LANGUAGE="JavaScript"> var XMLDocument; var XSLDocument; var HTMLtarget; function initialize() { XMLDocument = new ActiveXObject('MSXML2.DOMDocument.3.0'); XSLDocument = new ActiveXObject('MSXML2.DOMDocument.3.0'); HTMLtarget = document.all['targetDIV']; XMLDocument.validateOnParse = true; XMLDocument.load('planets.xml'); if (XMLDocument.parseError.errorCode != 0) { HTMLtarget.innerHTML = "Error!"; return false; } XSLDocument.validateOnParse = true; XSLDocument load('planets.xsl'); if (XSLDocument.parseError.errorCode != 0) { HTMLtarget.innerHTML = "Error!"; return false; } HTMLtarget.innerHTML = XMLDocument.transformNode(XSLDocument); } function sort(sortNode) { (XSLDocument.selectSingleNode("//xsl:sort/@select")).nodeValue = sortNode; HTMLtarget.innerHTML = XMLDocument.transformNode(XSLDocument); } </SCRIPT> </HEAD> <BODY ONLOAD="initialize()"> <CENTER> <DIV ID="targetDIV"></DIV> <BR> <BR> <INPUT TYPE="BUTTON" ONCLICK="sort('NAME')" VALUE="Sort by name"></INPUT> <INPUT TYPE="BUTTON" ONCLICK="sort('MASS')" VALUE="Sort by mass"></INPUT> <INPUT TYPE="BUTTON" ONCLICK="sort('RADIUS')" VALUE="Sort by radius"></INPUT> <INPUT TYPE="BUTTON" ONCLICK="sort('DAY')" VALUE="Sort by day"></INPUT> </CENTER> </BODY> </HTML> На самом деле загрузить документы XML и XSL в Internet Explorer можно несколькими способами. Для создания объектов XMLDocumentи XSLDocumentя использовал класс ActiveXObject, но эти объекты можно создавать и непосредственно обращаясь к содержащим документы XML объектам ActiveX по идентификатору класса, хранимому в реестре Windows. В следующем примере я таким образом загружу planets.xmlи planets.xslв XMLDocumentи XSLDocument: XMLDocument = document.all['XMLdoc']; XSLDocument = document.all['XSLdoc']; XMLDocument.load('planets.xml'); XSLDocument.load(' planets.xsl'); . . . <OBJECT ID="XMLdoc" WIDTH="0" HEIGHT="0" CLASSID="clsid:f5078f32-c551-11d3-89b9-0000f81fe221"> </OBJECT> <OBJECT ID="XSLdoc" WIDTH="0" HEIGHT="0" CLASSID="clsid:f5078f32-c551-11d3-89b9-0000f81fe221"> </OBJECT> Эта техника не так надежна, как использование класса ActiveXObject, поскольку идентификаторы классов могут различаться в разных версиях Internet Explorer. (Приведены идентификаторы классов для Internet Explorer 5.5). Но есть еще один способ загрузить документы XML и XSL в Internet Explorer — при помощи участков (island) XML. Internet Explorer и участки данных XMLВ Internet Explorer есть специальный тег <XML>, при помощи которого можно создавать участки (island) XML. Участок XML может содержать либо сам код XML, либо ссылку на XML-документ. Участки XML упрощают загрузку документов XML и XSL, поэтому их стоит здесь рассмотреть. В следующем примере я создаю два участка XML, sourceDocumentи stylesheet, и загружаю planets.xmlи planets.xsl, просто обратившись к ним через атрибут src: <HTML> <HEAD> <TITLE> The Planets Table </TITLE> <XML id="sourceDocument" src="planets.xml"></XML> <XML id="stylesheet" src="planets.xsl"></XML> . . . Теперь для осуществления XSLT-преобразования мне нужно только применить, как и раньше, метод transformNodeи присвоить результаты элементу <DIV>, чтобы вывести их (листинг 10.4). Листинг 10.4. Загрузка документов XML и XSL при помощи участков XML <HTML> <HEAD> <TITLE> The Planets Table </TITLE> <XML id="sourceDocument" src="planets.xml"></XML> <XML id="stylesheet" src="planets.xsl"></XML> <SCRIPT FOR="window" EVENT="onload"> targetDIV.innerHTML = sourceDocument.transformNode(stylesheet.XMLDocument); </SCRIPT> </HEAD> <BODY> <CENTER> <DIV id="targetDIV"></DIV> </CENTER> </BODY> </HTML> Вот и все. Заметьте, что по умолчанию Internet Explorer 5.5 и младше использует устаревший процессор XSLT, как обсуждалось в главе 2 (если специально не установить процессор MSXML3 в режиме замены или IE 6.0, о чем также говорилось в главе 2). Если вы работаете с IE 5.5 или младше, у вас в распоряжении таблица стилей Internet Explorer прежнего образца, в которой нет правил по умолчанию и в которой вам придется использовать старое пространство имен XSL, как в этом примере (листинг 10 5). Листинг 10.5. Таблица стилей Internet Explorer старого образца<?xml version="1.0"?> <xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/TR/WD-xsl"> <xsl:template match="/"> <HTML> <HEAD> <TITLE> The Planets Table </TITLE> </HEAD> <BODY> <H1> The Planets Table </H1> <TABLE BORDER="2"> <TR> <TD>Name</TD> <TD>Mass</TD> <TD>Radius</TD> <TD>Day</TD> </TR> <xsl:apply-templates/> </TABLE> </BODY> </HTML> </xsl:template> <xsl:template match="PLANETS"> <xsl:apply-templates/> </xsl:template> <xsl:template match="PLANET"> <TR> <TD><xsl:value-of select="NAME"/></TD> <TD><xsl:value-of select="MASS"/></TD> <TD><xsl:value-of select="RADIUS"/></TD> <TD><xsl:value-of select="DAY"/></TD> </TR> </xsl:template> </xsl:stylesheet> Как видите, при помощи JavaScript и XSLT в Internet Explorer можно сделать весьма многое. Дополнительную информацию можно подучить из руководства разработчика XSLT фирмы Microsoft, которое сейчас расположено по адресу http://msdn.microsoft.com/library/default.asp?URL=/library/psdk/xmlsdk/xslp8tlx.htm. Пришло время рассмотреть взаимодействие XSLT с Java, начав с обращения к Java непосредственно из процессоров XSLT. Вызов Java непосредственно из процессоров XSLTКак мы говорили в главе 5, до недавнего времени процессоры XSLT могли реализовывать функции расширения любым способом, и один из этих способов включал прямой вызов функций Java. Например, в Saxon и Xalan можно выполнять код Java, если определить пространство имен, указывающее класс Java как последнюю часть своего URI — как в следующем примере, где я определил пространство имен Date, соответствующее классу Java Date: <?xml version="1.0"?> <xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:Date="http://www.saxon.com/java/java.util.Date"> . . . Как вы видели в главе 5, это означает, что теперь вы можете применять такие функции Java, как toStringи new, для встраивания текущей даты в заголовок HTML <Н1>, — например, так (листинг 10.6). Листинг 10.6. Работа с функциями класса Date Java <?xml version="1.0"?> <xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:Date="http://www.saxon.com/java/java.util.Date"> <xsl:template match="/PLANETS"> <HTML> <HEAD> <TITLE> The Planets Table </TITLE> </HEAD> <BODY> <H1> The Planets Table </H1> <BR/> <H1> <xsl:value-of select="Date:toString(Date:new())"/> </H1> <TABLE BORDER="2"> <TD>Name</TD> <TD>Mass</TD> <TD>Radius</TD> <TD>Day</TD> <xsl:apply-templates/> </TABLE> </BODY> </HTML> </xsl:template> <xsl:template match="PLANET"> <TR> <TD><xsl:value-of select="NAME"/></TD> <TD><xsl:apply-templates select="MASS"/></TD> <TD><xsl:apply-templates select="RADIUS"/></TD> <TD><xsl:applу-templates select="DAY"/></TD> </TR> </xsl:template> <xsl:template match="MASS"> <xsl:value-of select="."/> </xsl:template> <xsl:template match="RADIUS"> <xsl:value-of select="."/> </xsl:template> <xsl:template match="DAY"> <xsl:value-of select="."/> </xsl:template> </xsl:stylesheet> Такой код, безусловно, работает, но дает лишь ограниченные средства работы и зависит от нестандартных расширений. За исключением случая, когда вы осуществляете только несколько простых вызовов, обычно лучше начать работать в Java и взаимодействовать с процессором XSLT. Каждый из процессоров XSLT Xalan, Saxon, XT и Oracle определяет API, к которому можно обращаться из Java. Достаточно только проверить, что нужные файлы JAR находятся в classpathJava. Мы уже рассматривали, как работать с файлами JAR и путями к классам, в главе 1; теперь мы перейдем к написанию кода на Java, а не просто выполнению предопределенных классов из командной строки. Код можно загрузить с http://www.newriders.com/books/title.cfm?isbn=0735711364, поэтому если вы не программист на Java, можете пропустить эту часть главы. Работа с API XSLT для JavaВо всех основанных на Java процессорах XSLT определен объемный интерфейс, API, для связи с Java. Как правило, при помощи API вызываются методы и создаются объекты Java, как мы увидим в этой главе. Но все процессоры XSLT определяют свои API по-разному, и обычно эти API довольно велики, поскольку каждый процессор может создавать собственные иерархии классов по своему усмотрению. В следующих разделах мы пройдем по этапам создания XSLT-преобразований из Java с использованием процессоров XSLT Xalan, Saxon, XT и Oracle. Все их возможности описаны в документации. Заметьте, что описание API большинства этих процессоров может само занять отдельную книгу, потому наше обсуждение вынужденно представляет собой лишь краткий обзор.
Взаимодействие Xalan с JavaНесмотря на свой размер, Xalan — один из простейших процессоров XSLT для взаимодействия с Java. В качестве примера я создал новый класс Java, xalanjava, и для осуществления XSLT-преобразования к нему положено обращаться следующим образом: C:\>java xalanjava planets.xml planets.xsl planets.html Чтобы создать XSLT-преобразование, я начну с создания объекта класса TransformerFactoryв классе xalanjava: import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerConfigurationException; import java.io.FileOutputStream; import java.iо.FileNotFoundException; import java.io.IOException; public class xalanjava { public static void main(String[] args) throws TransformerException, TransformerConfigurationException, FileNotFoundException, IOException { TransformerFactory tFactory = TransformerFactory.newInstance(); . . . Имена документа XML, документа XSL и результирующего документа были нам переданы в аргументах соответственно как args[0], args[1]и args[2]. На следующем шаге нужно загрузить документ XSL в новый созданный мной объект TransformerFactory. Для этого я создал объект StreamSourceи передал его в метод newTransformerобъекта TransformerFactory, чтобы создать новый объект Transformer: import javax.xml.transform.Transformer; . . . public class xalanjava { public static void main(String[] args) throws TransformerException, TransformerConfigurationException, FileNotFoundException, IOException { TransformerFactory tFactory = TransformerFactory.newInstance(); Transformer transformer = tFactory.newTransformer(new StreamSource(args[1])); . . . Объект transformerреализует XSLT-преобразование. Для того чтобы выполнить такое преобразование, нужно вызвать метод transformэтого объекта, передав ему соответствующий XML-документу объект StreamSourceи соответствующий результирующему документу объект StreamResult: import javax.xml.transform.Transformer; . . . public class xalanjava { public static void main(String[] args) throws TransformerException, TransformerConfigurationException, FileNotFoundException, IOException { . . . transformer.transform(new StreamSource(args[0]), new StreamResult(new FileOutputStream(args[2]))); } } Вот полный файл Java, xalanjava.java (листинг 10.7). Листинг 10.7. xalanjava.java, взаимодействие Xalan с Javaimport javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerConfigurationException; import java.io.FileOutputStream; import java.io.FileNotFoundException; import java.io.IOException; public class xalanjava { public static void main(String[] args) throws TransformerException, TransformerConfigurationException, FileNotFoundException, IOException { TransformerFactory tFactory = TransformerFactory.newInstance(); Transformer transformer = tFactory.newTransformer(new StreamSource(args[1])); transformer transform(new StreamSource(args[0]), new StreamResult(new FileOutputStream(args[2]))); } } Чтобы скомпилировать файл xalanjava.javaв xalanjava.classи выполнить этот класс, задайте classpathтак, чтобы путь включал Xalan и разборщик XML, который вы обычно используете с Xalan, Xerces (о Xerces говорилось в главе 1, в том числе и о том, где его взять), — в Windows это будет выглядеть так (как всегда, пишите пути в соответствии со своей системой): C:\>set classpath=.;c:\xalan\xalan.jar;c:\xalan\xerces.jar Затем скомпилируйте xalanjava.javaкомпилятором с Java, javac: C:\>javac xalanjava.java Здесь считается, что путь к javac.exeпрописан, и его можно сразу активизировать из командной строки. (Как правило, компилятор Java javac.exe находится в каталоге Java bin — поэтому если путь к нему не задан, к нему можно обратиться, например, так: C:\>c:\jdk1.3\bin\javac xalanjava.java.) Компилятор Java создаст файл xalanjava.class, при помощи которого производится преобразование: C:\>java xalanjava planets.xml planets.xsl planets.html При этом из файлов planets.xmlи planets.xslбудет создан файл planets.html— здесь я его создал при помощи своего собственного класса Java.
Взаимодействие Saxon с JavaПроцессор Saxon также определяет API для работы с Java, но, конечно, в деталях этот прикладной интерфейс отличается от API Xalan. Для демонстрации создания преобразований при помощи Saxon API версии 6.0.2 я создам новый класс Java saxonjava. Начать нужно с создания нового объекта XSLTProcessor, вызвав метод newInstanceкласса Processorв файле saxonjava.java: import java.io.*; import org.xml.sax.*; import org.w3c.dom.*; import com.icl.saxon.trax.*: public class saxonjava { public static void main(String args[]) throws ProcessorException, ProcessorFactoryException, TransformException, SAXException, IOException { Processor processor = Processor.newInstance("xslt"); . . . Затем необходимо создать объект Templatesна основе таблицы стилей XSL, которую мы хотим применить, хранимой в args[1]. Это можно сделать при помощи класса InputSource: import java.io.*; . . . public class saxonjava { public static void main(String args[]) throws ProcessorException, ProcessorFactoryException, TransformException, SAXException, IOException { Processor processor = Processor.newInstance("xslt"); Templates templates = processor.process(new InputSource(args[1])); . . . } } При помощи нового объекта Templatesможно создать объект Transformer, который в действительности делает работу: import java.io.*; . . . public class saxonjava { public static void main(String args[]) throws ProcessorException, ProcessorFactoryException, TransformException, SAXException, IOException { Processor processor = Processor.newInstance("xslt"); Templates templates = processor.process(new InputSource(args[1])); Transformer transformer = templates.newTransformer(); . . . } } Наконец, чтобы осуществить XSLT-преобразование, нужно вызвать метод transformобъекта transformer, записывая результат в выходной документ при помощи объекта FileWriter(листинг 10.8). Листинг 10.8. saxonjava.java, взаимодействие Saxon с Java import java.io.*; import org.xml.sax.*; import org.w3c.dom.*; import com.icl.saxon.trax.*; public class saxonjava { public static void main(String args[]) throws ProcessorException, ProcessorFactoryException, TransformException, SAXException, IOException { Processor processor = Processor.newInstance("xslt"); Templates templates = processor.process(new InputSource(args[1])); Transformer transformer = templates.newTransformer(); transformer.transform(new InputSource(args[0]), new Result(new FileWriter(args[2]))); } } Чтобы скомпилировать и использовать новый класс saxonjava, нужно установить classpathтак, чтобы переменная включала путь к saxon.jar: С:\>set сlasspath=.;с:\saxon\saxon.jar Затем при помощи компилятора Java, javac, создается saxonjava.class. Как и многие использующие API процессоры XSLT, Saxon ожидает, что ему будут переданы URL документов, с которыми вы хотите работать, — что я и делаю на следующем шаге: C:\>java saxonjava http://www.starpowder.com/planets.xml http://www.starpowder.com/planets.xsl planets.html Таким образом, создается planets.html, как и раньше. Заметьте, что если документы расположены локально, можно использовать URL файла. Например, в Windows, если документ XML расположен в c:\XSL\saxonjava\planets.xml, а документ XSL в c:\XSL\saxonjava\planets.xsl, можно выполнить такую командную строку: C:\>java saxonjava file:///XSL/saxonjava/planets.xml file:///XSL/saxonjava/planets.xsl planets.html
В этом примере мы работали с Saxon версии 6.0.2, о котором на web-узле Saxon говорится как о вполне надежной версии, но на момент написания книги появилась новая, полностью не протестированная версия Saxon 6.2.2. (Не существовало версии Saxon 6.1.x.) В последней версии Saxon, кажется, собирается вернуться к той же модели API, которую использует Xalan, и код, работоспособный в версии 6.0.2, не будет работать в версии 6.2.2 (сюрприз!). Ниже приведен код saxonjava.javaдля версии 6.2.2 — проверьте, что при работе с этим кодом вы включили в classpathновую версию saxon.jar, и обратите внимание на то, что при его выполнении вам нужно передавать не URL файлов, а только их имена. Этот код идентичен показанному ранее xalanjava.java, за исключением имени класса, saxonjava: import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerConfigurationException; import java.io.FileOutputStream; import java.io.FileNotFoundException; import java.io.IOException; public class saxonjava { public static void main(String[] args) throws TransformerException, TransformerConfigurationException, FileNotFoundException, IOException { TransformerFactory tFactory = TransformerFactory.newInstance(); Transformer transformer = tFactory.newTransformer(new StreamSource(args[1])); transformer transform(new StreamSource(args[0]), new StreamResult(new FileOutputStream(args[2]))); } } Взаимодействие процессора XSLT Oracle с JavaНесколько больше усилий потребуется для осуществления XSLT-преобразования при помощи API процессора XSLT фирмы Oracle. Новый пример, oraclejava.java, продемонстрирует работу с этим API. В oraclejava.javaв первую очередь необходимо считывать требуемые документы при помощи объекта DOMParser: import org.w3c.dom.*; import java.util.*; import java.io.*; import java.net.*; import oracle.xml.parser.v2.*; public class oraclejava { public static void main (String args[]) throws Exception { DOMParser parser; try { parser = new DOMParser(); parser.setPreserveWhitespace(true); . . . Затем, чтобы считать исходный документ XML и документ таблицы стилей XSLT, нужно преобразовать их URL в объекты URLJavaпри помощи метода parseобъекта parser. После этого я вызываю метод разборщика getDocument, для того чтобы извлечь и сохранить документы XML и XSLT в объектах XMLDocument: public class oraclejava { public static void main (String args[]) throws Exception { DOMParser parser; XMLDocument xmldoc, xsldoc; URL xslURL; URL xmlURL; try { parser = new DOMParser(); parser.setPreserveWhitespace(true); xmlURL = new URL(args[0]); parser.parse(xmlURL); xmldoc = parser.getDocument(); xslURL = new URL(args[1]); parser.parse(xslURL); xsldoc = parser.getDocument(); . . . В этот момент planets.xmlи planets.xslзаключены в объекты XMLDocument. Для выполнения преобразования мне необходимы еще объекты XSLStylesheetи XSLProcessorдля таблицы стилей XSLT. Фактическое преобразование XSLT осуществляется методом processXSLобъекта parser, возвращающего фрагмент документа: public class oraclejava { public static void main (String args[]) throws Exception { DOMParser parser; . . . xslURL = new URL(args[1]); parser.parse(xslURL); xsldoc = parser.getDocument(); XSLStylesheet xslstylesheet = new XSLStylesheet(xsldoc, xslURL); XSLProcessor processor = new XSLProcessor(); DocumentFragment docfragment = processor.processXSL(xslstylesheet, xmldoc); . . . Этот код завершает преобразование. Теперь задача состоит в том, чтобы преобразовать данный фрагмент документа в документ XML, который можно записать на диск, — для чего я и создам новый XML-документ, newdoc, и вставлю фрагмент документа в корень нового документа: import org.w3c.dom.*; . . . public class oraclejava { public static void main (String args[]) throws Exception { DOMParser parser; XMLDocument xmldoc, xsldoc, newdoc; URL xslURL; URL xmlURL; try { . . . DocumentFragment docfragment = processor processXSL(xslstylesheet, xmldoc); newdoc = new XMLDocument(); Element rootElement = newdoc.createElement("root"); newdoc.appendChild(rootElement); rootElement.appendChild(docfragment); . . . Теперь осталось только сохранить на диске новый XML-документ с именем, заданным в args[2]. В этих целях я использую объект FileOutputStream, и вот полный код (листинг 10.9). Листинг 10.9. oraclejava.java, взаимодействие процессора XSLT Oracle с Java import org.w3c.dom.*; import java.util.*; import java.io.*; import java.net.*; import oracle.xml.parser.v2.*; public class oraclejava { public static void main (String args[]) throws Exception { DOMParser parser; XMLDocument xmldoc, xsldoc, newdoc; URL xslURL; URL xmlURL; try { parser = new DOMParser(); parser.setPreserveWhitespace(true); xmlURL = new URL(args[0]); parser.parse(xmlURL); xmldoc = parser.getDocument(); xslURL = new URL(args[1]); parser.parse(xslURL); xsldoc = parser.getDocument(); XSLStylesheet xslstylesheet = new XSLStylesheet(xsldoc, xslURL); XSLProcessor processor = new XSLProcessor(); DocumentFragment docfragment = processor.processXSL(xslstylesheet, xmldoc); newdoc = new XMLDocument(); Element rootElement = newdoc.сreateElement("root"); newdoc.appendChild(rootElement); rootElement.appendChild(docfragment); OutputStream out = new FileOutputStream(args[2]); newdoc.print(out); out.close(); } catch (Exception e) {} } } На этом oraclejava.javaзаканчивается. Чтобы скомпилировать пример, включите в classpathпуть к разборщику XML процессора XSLT Oracle, xmlparserv2.jar: C:\>set classpath=.;c:\oraclexml\lib\xmlparserv2.jar Затем скомпилируйте oraclejava.java, как мы это уже делали, компилятором Java javac. Для выполнения XSLT-преобразований нужно указать URL документов, с которыми вы хотите работать (если документы локальны, можно указать URL файлов, как и раньше): C:\>java oraclejava http://starpowder.com/planets.xml http://starpowder.com/planets.xsl planets.html Взаимодействие XT с JavaПроцессор XT также может работать с Java. API XT спроектирован для работы с классами, определенными в Project X TR2 фирмы Sun, которые поддерживают обработку XML. Вам будет необходим файл xml.jarфирмы Sun, который можно получить, загрузив Project X TR2. Чтобы получить xml.jar, необходимо зарегистрироваться на web-узле разработчиков Sun, http://developer.java.sun.com, что, к счастью, бесплатно, хотя и потребует от вас заполнения изрядного количества форм. Файл xml.jarнужен для класса com.sun.xml.tree.XmlDocument. Этот класс поддерживает XML-документы, и я начну свой новый пример, xtjava.java, с создания нового объекта XmlDocumentдля исходного документа, таблицы стилей XSLT и результирующего документа: import java.io.IOException; import java.io.OutputStream; import java.io.FileOutputStream; import org.xml.sax.SAXException; import com.sun.xml.tree.XmlDocument; import com.jclark.xsl.dom.Transform; import com.jclark.xsl.dom.TransformEngine; import com.jclark.xsl.dom.TransformException; import com.jclark.xsl.dom.XSLTransformEngine; class xtjava { public static void main(String[] args) throws IOException. SAXException, TransformException { XmlDocument XMLdoc = new XmlDocument().createXmlDocument(args[0]); XmlDocument XSLdoc = new XmlDocument().createXmlDocument(args[1]); XmlDocument newdoc = new XmlDocument(); . . . После этого я создаю объект XSLTranformationEngineи вызываю его метод createTransformдля создания нового объекта Transformна основе таблицы стилей XSLT: import java.io.IOException; . . . class xtjava { public static void main(String[] args) throws IOException, SAXException, TransformException { XmlDocument doc = new XmlDocument(); XSLTransformEngine transformEngine = new XSLTransformEngine(); Transform transform = transformEngine.createTransform(XSLdoc); . . . Затем я могу преобразовать XML-документ в объект результирующего документа следующим способом: import java.io.IOException; . . . class xtjava { public static void main(String[] args) throws IOException, SAXException, TransformException { XmlDocument XMLdoc = new XmlDocument().createXmlDocument(args[0]); XmlDocument XSLdoc = new XmlDocument().createXmlDocument(args[1]); XmlDocument newdoc = new XmlDocument(); XSLTransformEngine transformEngine = new XSLTransformEngine(); Transform transform = transformEngine.createTransform(XSLdoc); transform transform(XMLdoc, newdoc); . . . Так завершается преобразование. Осталось только записать результирующий документ, newdoc, на диск, что можно сделать при помощи объекта FileOutputStream(листинг 10.10). Листинг 10.10. xtjava.java, взаимодействие XT с Java import java.io.IOException; import java.io.OutputStream; import java.io.FileOutputStream; import org.xml.sax.SAXException; import com.sun.xml.tree.XmlDocument; import com.jclark.xsl.dom.Transform; import com.jclark.xsl.dom.Transform Engine; import com.jclark.xsl.dom.TransformException; import com.jclark.xsl.dom.XSLTransformEngine; class xtjava { public static void main(String[] args) throws IOException, SAXException, TransformException { XmlDocument XMLdoc = new XmlDocument().createXmlDocument(args[0]); XmlDocument XSLdoc = new XmlDocument().createXmlDocument(args[1]); XmlDocument newdoc = new XmlDocument(); XSLTransformEngine transformEngine = new XSLTransformEngine(); Transform transform = transformEngine.createTransform(XSLdoc); transform.transform(XMLdoc, newdoc); OutputStream out = new FileOutputStream(args[2]); newdoc.write(out); out.close(); } } Чтобы запустить пример, включите xt.jarи xml.jarв classpath: C:\>set classpath=.;d:\xt\xt.jar;xml.jar Скомпилируйте теперь xtjava.javaкомпилятором Java javacи запустите на выполнение следующим образом, передав URL документов XML и XSL (можно передать и URL файлов, как было показано ранее): C:\>java xtjava http://www.starpowder.com/planets.xml http://www.starpowder.com/planets.xsl planets.html Теперь все сделано. Преобразование XML в реляционную базу данныхПри обсуждении дополнительных возможностей XSLT стоит упомянуть элементы расширения SQL процессора Saxon. Через драйвер Java Database Connectivity (JDBC) можно работать с реляционными базами данных. Мы уже рассмотрели преобразования из XML в XML, в простой текст, в RTF, в JavaScript и т.д. Теперь пришла очередь преобразованию XML в реляционную базу данных.
В примере я передам данные planets.xmlв базу данных формата Microsoft Access planets.mdb. Если вы хотите повторить пример, создайте этот файл базы данных, в нем — таблицу planetsс четырьмя текстовыми полями Name, Mass, Radiusи Day, а оставшуюся часть файла оставьте пустой. В Windows я зарегистрирую этот файл базы данных в качестве источника ODBC с именем «planets» через значок Data Sources (ODBC) (Источники данных (ODBC)) в панели управления (в Windows 2000 он расположен в панели управления в папке Administrative Tools (Администрирование)). При запуске пример считает данные планет из planets.xmlи добавит их в файл базы данных, planets.mdb. Для подключения к этой базе данных через JDBC я применил элемент <sql:connect>процессора Saxon. Префикс пространства имен sqlопределяется в Saxon следующим образом: <xsl:stylesheet xmlns:sql="http://icl.com/saxon/extensions/com.icl.saxon.sql.SQLElementFactory" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.1"> . . . Для фактического подключения к источнику данных planetsслужит элемент расширения <sql:connect>с атрибутами database, user, passwordи driver. Для работы через JDBC установите атрибут driverв « sun.jdbc.odbc.JdbcOdbcDriver», атрибут database— в источник данных ODBC, « jdbc:odbc:planets», а атрибуты userи password— в имя пользователя и пароль, нужные для подключения к базе данных. Здесь нам не требуется задавать имя пользователя и пароль, но я задал этим параметрам шаблонные значения, так как они требуются в большинстве приложений баз данных: <xsl:stylesheet xmlns:sql="http://icl.com/saxon/extensions/com.icl.saxon.sql.SQLElementFactory" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.1"> <xsl:param name="database" select="'jdbc:odbc:planets'"/> <xsl:param name="user"/> <xsl:param name="password"/> <xsl:template match="PLANETS"> <sql:connect database="{$database}" user="{$user}" password="{$password}" driver="sun.jdbc.odbc.JdbcOdbcDriver" xsl:extension-element-prefixes="sql"/> <xsl:apply-templates select="PLANET"/> </xsl:template> . . . Затем я подключаюсь к источнику данных planets. Я хочу вставить в базу данных данные из каждого элемента <PLANET>, для чего я создаю новый шаблон, который выбирает элементы <PLANET>и вставляет данные в таблицу planetsбазы данных при помощи элемента Saxon <sql:insert>: <xsl:stylesheet xmlns:sql="http://icl.com/saxon/extensions/com.icl.saxon.sql.SQLElementFactory" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.1"> . . . <xsl:template match="PLANETS"> <sql:connect database="{$database}" user="{$user}" password="{$password}" driver="sun.jdbc.odbc.JdbcOdbcDriver" xsl:extension-element-prefixes="sql"/> <xsl:apply-templates select="PLANET"/> </xsl:template> <xsl:template match="PLANET"> <sql:insert table="planets" xsl:extension-element-prefixes="sql"> . . . </sql:insert> </xsl:template> </xsl:stylesheet> Элемент <sql:insert>вставляет в базу данных новую запись. Чтобы присвоить ее полям новые данные, используйте элемент <sql:column>, установив его атрибут name в имя столбца, в который вы хотите записать данные, и присвоив эти данные атрибуту select: <xsl:stylesheet xmlns:sql="http://icl.com/saxon/extensions/com.icl.saxon.sql.SQLElementFactory" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.1"> . . . <xsl:template match="PLANET"> <sql:insert table="planets" xsl:extension-element-prefixes="sql"> <sql:column name="Name" select="NAME"/> <sql:column name="Mass" select="MASS"/> <sql:column name="Radius" select="RADIUS"/> <sql:column name="Day" select="DAY"/> </sql:insert> </xsl:template> </xsl:stylesheet> В идеале этого должно быть достаточно, но при работе с самым последним драйвером Access в конце операции Saxon не сбрасывает все буфера данных. Это значит, что данные о последней планете в planets.xml, Земле, не будут отправлены в базу данных. Чтобы сбросить буферы данных, я явно вызываю шаблон <PLANET>как именованный шаблон, применяя <sql:insert>с данными-заглушкой (листинг 10.11). Листинг 10.11. Работа с реляционной базой данных <xsl:stylesheet xmlns:sql="http://icl.com/saxon/extensions/com.icl.saxon.sql.SQLElementFactory" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.1"> <xsl:param name="database" select="'jdbc:odbc:planets'"/> <xsl:param name="user"/> <xsl:param name="password"/> <xsl:template match="PLANETS"> <sql:connect database="{$database}" user="{$user}" password="{$password}" driver="sun.jdbc.odbc.JdbcOdbcDriver" xsl:extension-element-prefixes="sql"/> <xsl:apply-templates select="PLANET"/> <xsl:call-template name="writer"/> </xsl:template> <xsl:template match="PLANET" name="writer"> <xsl:choose> <xsl:when test="NAME"> <sql:insert table="planets" xsl:extension-element-prefixes="sql"> <sql:column name="Name" select="NAME"/> <sql:column name="Mass" select="MASS"/> <sql:column name="Radius" select="RADIUS"/> <sql:column name="Day" select="DAY"/> </sql:insert> </xsl:when> <xsl:otherwise> <sql:insert table="planets" xsl:extension-element-prefixes="sql"> <sql:column name="Name" select="' '"/> <sql:column name="Mass" select="' '"/> <sql:column name="Radius" select="' '"/> <sql:column name="Day" select="' '"/> </sql:insert> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> Эта таблица стилей правильно добавляет три записи в базу данных planets.mdb: по одной новой записи для каждой из планет. Как я говорил, здесь нельзя использовать готовый исполняемый файл saxon.exe, нужно применять класс Java com.icl.saxon.StyleSheet. Сначала нужно включить в classpathфайл saxon.jar: C:\>set classpath=.;c:\saxon\saxon.jar После этого я могу передать в класс com.icl.saxon.StyleSheetфайл planets.xmlи таблицу стилей из листинга 10.11: C:\>java com.icl.saxon.StyleSheet planets.xml saxonsql.xsl Теперь все сделано — данные планет вставлены в planets.mdb. Результаты применения этой таблицы стилей показаны на рис. 10.4, где я открыл planets.mdbв Microsoft Access. Таким образом, мы рассмотрели преобразование из XML в реляционную базу данных. ![]() Рис. 10.4. Применение расширений SQL Saxon Еще один аспект XSLT, в котором вам потребуется программирование, это поддержка XSLT на серверах. В качестве демонстрации далее я преобразую planets.xmlпри помощи planets.xslс использованием активных серверных страниц (Active Server Pages, ASP) фирмы Microsoft, серверных страниц Java (Java Server Pages, JSP) фирмы Sun и сервлетов (servlet) Java, выполняющихся на web-серверах и возвращающих результирующий документ браузеру пользователя. За недостатком места мы не можем подробно рассмотреть эти технологии, и если вы с ними не знакомы, вы можете получить дополнительную информацию в Интернете (как всегда, URL могут измениться): • ASP. http://msdn.microsoft.com/workshop/c-frame.htm#/workshop/server/Default.asp (руководство и документация по ASP фирмы Microsoft); • JSP. http://java.sun.com/products/jsp/ (главная страница Sun, посвященная JSP); • Сервлеты. http://java.sun.com/products/servlet/ (главная страница Sun, посвященная сервлетам). Применение XSLT с активными серверными страницамиАктивные серверные страницы (Active Server Pages, ASP) выполняются на серверах Microsoft Windows NT или 2000, поэтому в ближайшем примере для преобразования planets.xmlпри помощи planets.xslи возврата результата в виде документа HTML я воспользуюсь процессором Microsoft MSXML. Это все то же преобразование, которое нам уже много раз встречалось, — создание HTML-таблицы данных о планетах — но на этот раз преобразование будет выполнено на web-сервере, который затем отправит его пользователю. В начале сценария ASP я установил тип содержимого MIME результирующего документа в « text/html», поэтому он будет трактоваться как HTML: <%@LANGUAGE="VBScript"%> <% Response.ContentType = "text/html" . . . Затем, во многом аналогично предыдущим примерам в этой главе с JavaScript, я создаю два объекта документа MSXML, один для документа XML, а другой — для документа XSL: <%@LANGUAGE="VBScript"%> <% Response.ContentType = "text/html" Dim docXML Dim docXSL Set docXML = Server.CreateObject("MSXML2.DOMDocument.3.0") Set docXSL = Server.CreateObject("MSXML2.DOMDocument.3.0") . . . Процедура загрузки этих документов на сервере во многом похожа на процедуру с использованием JavaScript, за тем исключением, что здесь правильные пути файлов получаются при помощи метода MapPathобъекта Server. В данном случае я поместил planets.xmlи planets.xslв тот же каталог, что и сценарий ASP, поэтому документы загружаются так: <%@LANGUAGE="VBScript"%> <% Response.ContentType = "text/html" Dim docXML Dim docXSL Set docXML = Server.CreateObject("MSXML2.DOMDocument.3.0") Set docXSL = Server.CreateObject("MSXML2.DOMDocument.3.0") docXML.ValidateOnParse = True docXSL.ValidateOnParse = True docXML.load Server.MapPath("planets.xml") docXSL.load Server.MapPath("planets.xsl") . . . Теперь нам осталось только применить метод transformNode(как в примере с JavaScript раньше) для выполнения XSLT-преобразования и вывода результатов (листинг 10.12). Листинг 10.12. XSLT на сервере с применением ASP <%@LANGUAGE="VBScript"%> <% Response.ContentType = "text/html" Dim docXML Dim docXSL Set docXML = Server.CreateObject("MSXML2.DOMDocument.3.0") Set docXSL = Server.CreateObject("MSXML2.DOMDocument.3.0") docXML.ValidateOnParse = True docXSL.ValidateOnParse = True docXML.load Server.MapPath("planets.xml") docXSL.load Server.MapPath("planets.xsl") strOutput = docXML.transformNode(docXSL) Response.Write strOutput %> Результат этого преобразовании ASP показан на рис. 10.5. Теперь вы научились выполнению XSLT-преобразований на web-серверах. ![]() Рис. 10.5. Применение XSLT с ASP Нужно сделать одно замечание: при выполнении XSLT-преобразований на сервере можно подумать об оптимизации ваших преобразований в зависимости от клиента, так как необязательно генерировать для карманного компьютера тот же экран, что и для браузера настольного компьютера. Например, можно настроить ответ вашего серверного сценария ASP (где я проверяю значение серверной переменной http_user_agentчтобы определить, использует ли клиент Internet Explorer) следующим образом: <%@LANGUAGE="VBScript"%> <% Response ContentType = "text/html" If instr(request,servervariables("http_user_agent"), "MSIE") = 0 then Response.Write "Sorry, not optimized for your device." Response.End End If . . .
Применение XSLT с Java Server PagesДля работы с активными серверными страницами я использовал процессор MSXML фирмы Microsoft, но серверные страницы Java (Java Server Pages, JSP) не обязаны выполняться на серверах на платформе Windows, поэтому с JSP я не использую MSXML. Для выполнения XSLT-преобразования и отправки результатов в браузер клиента я воспользуюсь API процессора Xalan для работы с Java. Например, при помощи Xalan можно создать planets.htmlна сервере как временный документ (этот код предполагает, что planets.xmlи planets.xslрасположены в том же каталоге, что и сценарий JSP) таким образом: <%@ page errorPage="error.jsp" language="java" contentType="text/html" import="org.apache.xalan.xslt.*;java.iо.*" %> <% try { XSLTProcessor processor = XSLTProcessorFactory.getProcessor(); processor.process(new XSLTInputSource("planets.xml"), new XSLTInputSource("planets.xsl"), new XSLTResultTarget("planets.html"));
. . . Теперь все, что нужно сделать, — это открыть документ и отправить его обратно клиенту (листинг 10.13). Листинг 10.13. XSLT на сервере с применением JSP<%@ page errorPage="error.jsp" language="java" contentType="text/html" import="org.apache.xalan.xslt.*;java.iо.*" %> <% try { XSLTProcessor processor = XSLTProcessorFactory.getProcessor(); processor.process(new XSLTInputSource("planets.xml"), new XSLTInputSource("planets.xsl"), new XSLTResultTarget("planets.html")); } catch(Exception e) {} FileReader filereader = new FileReader("planets.html"); BufferedReader bufferedreader = new BufferedReader(filereader); String instring; while((instring = bufferedreader.readLine()) != null) { %> <%= instring %> <% } filereader.close(); pw.close(); %> Теперь все готово. Результаты применения этого сценария JSP показаны на рис. 10.6. ![]() Рис. 10.6. Применение XSLT с JSP Применение XSLT с сервлетами JavaВыполнять XSLT-преобразования на сервере можно также при помощи сервлетов (servlet) Java. Хотя многие процессоры XSLT предоставляют свои собственные версии сервлетов, я считаю, что гораздо проще самостоятельно выполнить преобразование при помощи Xalan или другого процессора XSLT и затем обработать результирующий документ и отправить его обратно клиенту. В следующем примере я при помощи Xalan преобразую planets.xmlво временный файл planets.html, применяя planets.xslв сервлете: import java.net.*; import java.sql.*; import java.awt.*; import java.awt.event.*; import java.io.*; import javax.servlet.*; import org.apache.xalan.xslt.*; public class xslservlet extends GenericServlet { public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { try { XSLTProcessor processor = XSLTProcessorFactory.getProcessor(); processor.process(new XSLTInputSource("planets.xml"), new XSLTInputSource("planets.xsl"), new XSLTResultTarget("planets.html"));
. . . Все, что осталось, — отправить HTML-документ обратно клиенту (листинг 10.14). Листинг 10.14. Применение XSLT на сервере с сервлетами Javaimport java.net.*; import java.sql.*; import java.awt.*; import java.awt.event.*; import java.io.*; import javax.servlet.*; import org.apache.xalan.xslt.*; public class xslservlet extends GenericServlet { public void service(ServletRequest request, ServletResponse response) throws ServletException.IOException { response.setContentType("text/html"); PrintWriter pw = response.getWriter(); try { XSLTProcessor processor = XSLTProcessorFactory.getProcessor(); processor.process(new XSLTInputSource("planets.xml"), new XSLTInputSource("planets.xsl"), new XSLTResultTarget("planets.html")); } catch(Exception e) {} FileReader filereader = new FileReader("planets.html"); BufferedReader bufferedreader = new BufferedReader(filereader); String instring; while((instring = bufferedreader.readLine()) != null) { pw.println(instring); } filereader.close(); pw.close(); } } Теперь все сделано, результат показан на рис. 10.7 — HTML-документ, переданный из сервлета. ![]() Рис. 10.7. Применение XSLT с сервлетами Java На этом мы заканчиваем изучение работы с API процессоров XSLT в программном коде. Мы рассмотрели весьма объемный материал: как взаимодействовать с API процессоров XSLT из JavaScript и Java для процессоров MSXML, Xalan, XT, Saxon и Oracle, а также примеры выполнения XSLT-преобразований на web-серверах при помощи ASP, JSP и сервлетов Java. |
|
||
Главная | В избранное | Наш E-MAIL | Добавить материал | Нашёл ошибку | Наверх |
||||
|