Книга: XSLT

Internet Explorer и динамические стили

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" VALUE="Sort by name"></INPUT>
<INPUT TYPE="BUTTON" VALUE="Sort by mass"></INPUT>
<INPUT TYPE="BUTTON" VALUE="Sort by radius"></INPUT>
<INPUT TYPE="BUTTON" 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() {
   .
   .
   .
  }

  function sort(sortNode) {

   (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>
  <CENTER>
   <DIV></DIV>
   <BR>
   <BR>
   <INPUT TYPE="BUTTON" VALUE="Sort by name"></INPUT>
   <INPUT TYPE="BUTTON" VALUE="Sort by mass"></INPUT>
   <INPUT TYPE="BUTTON" VALUE="Sort by radius"></INPUT>
   <INPUT TYPE="BUTTON" 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 WIDTH="0" HEIGHT="0"
 CLASSID="clsid:f5078f32-c551-11d3-89b9-0000f81fe221">
</OBJECT>
<OBJECT 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.

Оглавление книги


Генерация: 2.485. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз