Spec-Zone .ru
спецификации, руководства, описания, API
След: API Java для XML, Обрабатывающего (JAXP)
Урок: Преобразования Расширяемого языка таблиц стилей
Преобразование Данных XML с XSLT
Домашняя страница > API Java для XML, Обрабатывающего (JAXP) > Преобразования Расширяемого языка таблиц стилей

Преобразование Данных XML с XSLT

Преобразования Расширяемого языка таблиц стилей (XSLT) API могут использоваться во многих целях. Например, с достаточно интеллектуальной таблицей стилей, Вы могли генерировать PDF или вывод PostScript от данных XML. Но обычно, XSLT используется, чтобы генерировать отформатированный вывод HTML, или создать альтернативное представление XML данных.

В этом разделе преобразование XSLT используется, чтобы преобразовать входные данные XML в вывод HTML.


Отметьте - спецификация XSLT является большой и сложной, таким образом, это учебное руководство может только поцарапать поверхность. Это даст Вам небольшой фон, таким образом, можно будет понять простой XSLT обработка задач, но это не исследует подробно, как записать, что XSLT преобразовывает, скорее концентрирующийся на том, как использовать XSLT JAXP, преобразовывают API. Для более полного основания в XSLT консультируйтесь с хорошим справочником, таким как XSLT Майкла Кея 2.0 и XPath 2.0: Справочник программиста (Wrox, 2008).


Определение Простого Типа документа

Запустите, определяя очень простой тип документа, который может использоваться для того, чтобы написать статьи. Наши документы article будут содержать эти теги структуры:

Немного необычный аспект этой структуры - то, что мы не будем создавать отдельный тег элемента для заголовка раздела. Такие элементы обычно создаются, чтобы отличить возглавляющий текст (и любые теги, которые он содержит) от тела раздела (то есть, любые элементы структуры под заголовком).

Вместо этого мы позволим заголовку объединяться легко в тело раздела. То расположение добавляет некоторую сложность к таблице стилей, но это даст нам шанс исследовать механизмы шаблонного выбора XSLT. Это также соответствует наши интуитивные ожидания о структуре документа, где текст заголовка сопровождается непосредственно элементами структуры, расположение, которое может упростить ориентированное на схему редактирование.


Отметьте - Этот вид структуры легко не проверяется, потому что модель смешанного контента XML позволяет текст где угодно в разделе, тогда как мы хотим ограничить текст и встроенные элементы так, чтобы они появились только перед первым элементом структуры в теле раздела. Основанный на утверждении блок проверки допустимости может сделать, он, но большинство других механизмов схемы не может. Таким образом, мы обойдемся без определения DTD для типа документа.


В этой структуре могут быть вложены разделы. Глубина вложения определит какой форматирование HTML, чтобы использовать для заголовка раздела (например, h1 или h2). Используя плоскость тег SECT (вместо пронумерованных разделов) также полезен с ориентированным на схему редактированием, потому что это позволяет Вам перемещать разделы по желанию, не имея необходимость волноваться об изменении нумерации для любого из разделов, на которые влияют.

Для списков мы будем использовать атрибут типа, чтобы определить, неупорядочиваются ли записи списка (маркируемые), альфа (перечисленные со строчными буквами), АЛЬФА (перечисленный с прописными буквами), или пронумеровали.

Мы также учтем некоторые встроенные теги, которые изменяют появление текста.


Отметьте - встроенный тег не генерирует разрыв строки, таким образом, изменение стиля, вызванное встроенным тегом, не влияет на поток текста на странице (хотя это будет влиять на появление того текста). Тег структуры, с другой стороны, разграничивает новый сегмент текста, так как минимум это всегда генерирует разрыв строки в дополнение к другим изменениям формата.


Тег <DEF> будет использоваться для слов, которым дают определение в тексте. Такие сроки будут выведены на экран курсивом, способ, которым они обычно находятся в документе. Но использование специального тега в XML позволит индексировать программе находить такие определения и добавлять их к индексированию, наряду с ключевыми словами в заголовках. В предыдущем Примечании, например, определения встроенных тегов и тегов структуры, возможно, были отмечены с тегами <DEF> для будущей индексации.

Наконец, тег LINK служит двум целям. Во-первых, это позволит нам создавать ссылку к URL, не имея необходимость вставлять URL дважды; таким образом, мы можем кодировать <link>http//...</link> вместо <a href="http//...">http//...</a>. Конечно, мы будем также хотеть позволить форму, которая похожа на <link target="...">...name...</link>. Это приводит к второй причине тега <link>. Это даст нам возможность играть с условными выражениями в XSLT.


Отметьте - Хотя структура статьи чрезвычайно проста (состоящий только из одиннадцати тегов), она повышает достаточно многие интересные проблемы высказать нам хорошее мнение основных возможностей XSLT. Но мы все еще оставим большие площади спецификации нетронутыми. В Чем еще Может XSLT Делать?, мы укажем на основные функции, которые мы пропускали.


Создание Тестового Документа

Здесь, Вы создадите простой тестовый документ, используя, вкладывал элементы <SECT>, несколько <ПАРАГРАФ> элементы, элемент <NOTE>, <LINK>, и <LIST type="unordered">. Идея состоит в том, чтобы создать документ с одним из всего так, чтобы мы могли исследовать более интересные механизмы преобразования.


Отметьте - код, обсужденный в этом разделе, находится в article1.xml, который находится в каталоге xslt/data после того, как Вы разархивировали XSLT examples в install-dir/jaxp-1_4_2-release-date/samples каталог.


Чтобы сделать тестовый документ, создайте файл под названием article.xml и введите следующие данные XML.

<?xml version="1.0"?>
<ARTICLE>
   <TITLE>A Sample Article</TITLE>
   <SECT>The First Major Section
      <PARA>This section will introduce a subsection.</PARA>
      <SECT>The Subsection Heading
         <PARA>This is the text of the subsection.
         </PARA>
      </SECT>
   </SECT>
</ARTICLE>

Отметьте, что в XML-файле, подраздел полностью содержится в пределах главного раздела. (В HTML, с другой стороны, заголовки не содержат тело раздела). Результатом является структура схемы, которую более трудно отредактировать в форме простого текста, как это, но намного легче отредактировать с ориентированным на схему редактором.

Когда-нибудь, учитывая ориентированный на дерево XML-редактор, который понимает встроенные теги, такие как <B> и <I>, должно быть возможно отредактировать статью этого вида в форме схемы, не требуя сложной таблицы стилей. (Такой редактор позволил бы писателю сосредотачиваться на структуре статьи, оставляя расположение до намного позже в процессе). В таком редакторе выглядел бы примерно так фрагмент статьи:

<ARTICLE> 
 <TITLE>A Sample Article 
  <SECT>The First Major Section 
   <PARA>This section will 
            introduce a subsection.
    <SECT>The Subheading 
     <PARA>This is the text of the subsection. 
         Note that ...

Отметьте - В настоящее время, редакторы с древовидной структурой существуют, но они обрабатывают встроенные теги, такие как <B> и <I> таким же образом, что они обрабатывают теги структуры, и это может сделать "схему" немного трудной читать.


Запись XSLT Преобразовывает

Теперь пора начать писать, что XSLT преобразовывает, который преобразует статью XML и представит ее в HTML.


Отметьте - код, обсужденный в этом разделе, находится в article1a.xsl, который находится в каталоге xslt/data после того, как Вы разархивировали XSLT examples в install-dir/jaxp-1_4_2-release-date/samples каталог.


Запустите, создавая нормальный XML-документ:

<?xml version="1.0" encoding="ISO-8859-1"?>

Затем добавьте следующие выделенные строки, чтобы создать таблицу стилей XSL:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet 
 xmlns:xsl=
    "http://www.w3.org/1999/XSL/Transform" 
 version="1.0"
 >

</xsl:stylesheet>

Теперь установите это, чтобы произвести совместимый с HTML вывод.

<xsl:stylesheet 
[...]

   >
<xsl:output method="html"/>

[...]

</xsl:stylesheet>

Мы войдем в подробные причины той записи позже в этом разделе. Пока, отметьте, что, если Вы хотите вывести что-нибудь кроме правильно построенного XML, тогда Вы будете нуждаться в теге <xsl:output> как один показанный, определяя или text или html. (Значением по умолчанию является xml).


Отметьте - Когда Вы определяете вывод XML, можно добавить атрибут отступа, чтобы произвести приятно расположенный с отступом вывод XML. Спецификация похожа на это: <xsl:output method="xml" indent="yes"/>.


Обработка Элементов Базовой структуры

Вы начнете заполнять таблицу стилей, обрабатывая элементы, которые входят в создание оглавления: корневой элемент, элемент title, и заголовки. Вы также обработаете элемент PARA, определенный в тестовом документе.


Отметьте - Если на первом чтении Вы пропускали раздел, который обсуждает механизмы адресации XPath, Как Работы XPath, теперь хорошее время, чтобы возвратиться и рассмотреть тот раздел.


Начните, добавляя основную инструкцию, которая обрабатывает корневой элемент:

 <xsl:template match="/">
      <html><body>
         <xsl:apply-templates/>
      </body></html>
   </xsl:template>

</xsl:stylesheet>

Новые команды XSL показывают полужирным. (Отметьте, что они определяются в пространстве имен xsl). Инструкция <xsl:apply-templates> обрабатывает дочерние элементы текущего узла. В этом случае текущий узел является корневым узлом.

Несмотря на его простоту, этот пример иллюстрирует много важных идей, таким образом, он стоит понять полностью. Первое понятие - то, что таблица стилей содержит много шаблонов, определенных с помощью тега <xsl:template>. Каждый шаблон содержит атрибут соответствия, который использует механизмы адресации XPath, описанные в том, Как Работы XPath, чтобы выбрать элементы, что шаблону применятся к.

В пределах шаблона просто копируются теги, которые не запускаются с префикса xsl: namespace. Новые строки и пробел, которые следуют за ними, также копируются, и это помогает сделать получающийся вывод читаемым.


Отметьте - Когда новая строка не присутствует, пробел обычно игнорируется. Чтобы включать пробел в вывод в таких случаях, или включать другой текст, можно использовать тег <xsl:text>. В основном таблица стилей XSLT ожидает обрабатывать теги. Так все это видит потребности быть или тегом <xsl:..>, некоторым другим тегом, или пробелом.


В этом случае теги non-XSL являются HTML-тэгами. Так, когда корневой тег является соответствующим, выводы XSLT, HTML запускает теги, обрабатывает любые шаблоны, которые применяются к дочерним элементам корня, и затем выводит конечные тэги HTML.

Обработайте Элемент <TITLE>

Затем, добавьте шаблон, чтобы обработать статью title:

 <xsl:template match="/ARTICLE/TITLE">
 <h1 align="center"> 
    <xsl:apply-templates/> </h1>
 </xsl:template>

</xsl:stylesheet>

В этом случае Вы определяете полный путь к элементу ЗАГОЛОВКА и выводите некоторый HTML, чтобы превратить текст title в большой, центрируемый заголовок. В этом случае тег apply-templates гарантирует, что, если title содержит какие-либо встроенные теги, такие как курсив, ссылки, или подчеркивание, они также будут обработаны.

Что еще более важно инструкция apply-templates заставляет текст title быть обработанным. Как модель данных ДОМА, модель данных XSLT основана на понятии текстовых узлов, содержавшихся в узлах элемента (который, поочередно, может содержаться в других узлах элемента, и так далее). Та иерархическая структура составляет исходное дерево. Есть также дерево результата, которое содержит вывод.

XSLT работает, преобразовывая исходное дерево в дерево результата. Чтобы визуализировать результат операций XSLT, полезно понять структуру тех деревьев, и их содержание. (Для больше на этом предмете, см. Модель данных XSLT/XPath).

Заголовки процесса

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

 <xsl:template match=
    "/ARTICLE/SECT">
 <h2> <xsl:apply-templates
 select="text()|B|I|U|DEF|LINK"/> 
</h2>
 <xsl:apply-templates select=
    "SECT|PARA|LIST|NOTE"/>
 </xsl:template>

</xsl:stylesheet>

Здесь, Вы определяете путь к самым верхним элементам SECT. Но на сей раз, Вы применяете шаблоны на двух этапах, используя атрибут select. Для первой стадии Вы выбираете текстовые узлы, так же как встраиваете теги такой как полужирные и курсив, используя XPath функция text(). (Вертикальный канал (|) используется, чтобы соответствовать многократные элементы: текст или полужирный тег или тег курсива, и т.д.). На втором этапе Вы выбираете другие элементы структуры, содержавшиеся в файле, для разделов, абзацев, списков, и примечаний.

Используя избранный атрибут позволяет Вам помещать текст и встроенные элементы между тегами <h2>...</h2>, удостоверяясь, что все теги структуры в разделе обрабатываются позже. Другими словами Вы удостоверяетесь, что вложение заголовков в XML-документе не отражается в форматировании HTML, различие, которое важно для вывода HTML.

Вообще, использование избранного пункта позволяет Вам применять все шаблоны к подмножеству информации, доступной в текущем контексте. Как другой пример, этот шаблон выбирает все атрибуты текущего узла:

<xsl:apply-templates select="@*"/></attributes>

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

 <xsl:template match=
    "/ARTICLE/SECT/SECT">
 <h3> <xsl:apply-templates
 select="text()|B|I|U|DEF|LINK"/> 
</h3>
 <xsl:apply-templates select=
    "SECT|PARA|LIST|NOTE"/>
 </xsl:template>

</xsl:stylesheet>

Генерируйте сообщение Времени выполнения

Вы могли добавить шаблоны для более глубоких заголовков, также, но в некоторый момент следует остановиться, если только потому, что HTML теряет работоспособность только к пяти уровням. Для этого примера Вы остановитесь на двух уровнях заголовков раздела. Но если ввод XML, окажется, будет содержать третий уровень, то Вы будете хотеть поставить сообщение об ошибке пользователю. Этот раздел показывает Вам, как сделать это.


Отметьте - Мы могли продолжать обрабатывать элементы SECT, которые далее снижаются, выбирая их с выражением /SECT/SECT//SECT. // выбирает любые элементы SECT, в любой глубине, как определено механизмом адресации XPath. Но вместо этого мы воспользуемся возможностью, чтобы играть с обменом сообщениями.


Добавьте следующий шаблон, чтобы генерировать ошибку, когда с разделом встречаются, который вкладывается слишком глубоко:

 <xsl:template match=
    "/ARTICLE/SECT/SECT/SECT">
 <xsl:message terminate="yes">
 Error: Sections can only be nested 2 deep.
 </xsl:message>
 </xsl:template>

</xsl:stylesheet>

Пункт terminate="yes" заставляет процесс преобразования останавливаться после того, как сообщение сгенерировано. Без этого обработка могла все еще продолжиться со всем в том проигнорированном разделе.

Как дополнительное осуществление, Вы могли развернуть таблицу стилей, чтобы обработать разделы, вложенные до четырех разделов глубоко, генерируя теги <h2>...<h5>. Генерируйте ошибку на любом разделе, вложенном пять уровней глубоко.

Наконец, закончите таблицу стилей, добавляя шаблон, чтобы обработать тег PARA:

 <xsl:template match="PARA">
 <p><xsl:apply-templates/></p>
 </xsl:template>
</xsl:stylesheet>

Запись Основной Программы

Теперь Вы измените программу, которая использует XSLT, чтобы повторить неизменный XML-файл, изменяя это так, чтобы это использовало Вашу таблицу стилей.


Отметьте - код, обсужденный в этом разделе, находится в Stylizer.java, который находится в каталоге xslt после того, как Вы разархивировали XSLT examples в install-dir/jaxp-1_4_2-release-date/samples каталог. Результатом является stylizer1a.html, найденный в xslt/data.


Пример Stylizer адаптируется от TransformationApp02, который анализирует XML-файл и пишет в System.out. Основные отличия между этими двумя программами описываются ниже.

Во-первых, Stylizer использует таблицу стилей, создавая объект Transformer.

// ...
import javax.xml.transform.dom.DOMSource; 
import javax.xml.transform.stream.StreamSource; 
import javax.xml.transform.stream.StreamResult; 
// ... 

public class Stylizer {
    // ...
    public static void main (String argv[]) {
        // ...
        try {
            File stylesheet = new File(argv[0]);
            File datafile = new File(argv[1]);

            DocumentBuilder builder = factory.newDocumentBuilder();
            document = builder.parse(datafile);
            // ...
            StreamSource stylesource = new StreamSource(stylesheet); 
            Transformer transformer = Factory.newTransformer(stylesource);
        }
    }
}

Этот код использует файл, чтобы создать объект StreamSource и затем передает исходный объект к фабрике class, чтобы получить преобразователь.


Отметьте - можно упростить код несколько, устраняя DOMSource class. Вместо того, чтобы создать объект DOMSource для XML-файла, создайте объект StreamSource для этого, так же как для таблицы стилей.


Выполнение Выборки Stylizer

  1. Переместитесь к каталогу samples.
    % cd install-dir/jaxp-1_4_2-release-date/samples.
    
  2. Download the XSLT examples by clicking this link и разархивируйте их в install-dir/jaxp-1_4_2-release-date/samples каталог.
  3. Переместитесь к каталогу xslt.
    cd xslt
    
  4. Скомпилируйте выборку Stylizer.

    Введите следующую команду:

    % javac Stylizer.java
    
  5. Выполните выборку Stylizer на article1.xml, используя таблицу стилей article1a.xsl.
    % java Stylizer data/article1a.xsl  data/article1.xml
    

    Вы будете видеть следующий вывод:

    <html>
    <body>
    
    <h1 align="center">A Sample Article</h1>
    <h2>The First Major Section
    
    </h2>
    <p>This section will introduce a subsection.</p>
    <h3>The Subsection Heading
    
    </h3>
    <p>This is the text of the subsection.
    </p>
    
    </body>
    </html>
    

    В этой точке в выводе есть довольно мало избыточного пробела. В следующем разделе Вы будете видеть, как устранить большинство из него.

Обрезка Пробела

Вспомните, что, когда Вы смотрите на структуру ДОМА, есть много текстовых узлов, которые содержат только игнорируемый пробел. Большая часть избыточного пробела в выводе прибывает из этих узлов. К счастью, XSL дает Вам способ устранить их. (Для больше о структуре узла, см. Модель данных XSLT/XPath).


Отметьте - таблица стилей, обсужденная в этом разделе, находится в article1b.xsl, который находится в каталоге xslt/data после того, как Вы разархивировали XSLT examples в install-dir/jaxp-1_4_2-release-date/samples каталог. Результатом является stylizer1b.html, найденный в xslt/data.


Чтобы удалить часть избыточного пробела, добавьте следующую выделенную строку к таблице стилей.

<xsl:stylesheet ...
   >
<xsl:output method="html"/> 
<xsl:strip-space elements="SECT"/>

[...]

Эта инструкция говорит XSL удалять любые текстовые узлы под элементами SECT, которые содержат только пробел. На узлы, которые содержат текст кроме пробела, не будут влиять, ни будут другие виды узлов.

Выполнение Выборки Stylizer с Обрезанным Пробелом

  1. Переместитесь к каталогу samples.
    % cd install-dir/jaxp-1_4_2-release-date/samples.
    
  2. Download the XSLT examples by clicking this link и разархивируйте их в install-dir/jaxp-1_4_2-release-date/samples каталог.
  3. Переместитесь к каталогу xslt.
    cd xslt
    
  4. Скомпилируйте выборку Stylizer.

    Введите следующую команду:

    % javac Stylizer.java
    
  5. Выполните выборку Stylizer на article1.xml, используя таблицу стилей article1b.xsl.
    % java Stylizer 
      data/article1b.xsl  
      data/article1.xml
    

    Вы будете видеть следующий вывод:

    <html>
    <body>
    
    <h1 align="center">A Sample Article</h1>
    
    <h2>The First Major Section
       </h2>
    <p>This section will introduce a subsection.</p>
    <h3>The Subsection Heading
          </h3>
    <p>This is the text of the subsection.
          </p>
    
    </body>
    </html>
    

    Это - настоящее улучшение. Есть все еще символы новой строки и пробел после заголовков, но прибывших от способа, которым пишется XML:

    <SECT>The First Major Section
    ____<PARA>This section will introduce a subsection.</PARA>
    ^^^^
    

    Здесь, можно видеть, что концы заголовка раздела с новой строкой и пространством добавления отступа, прежде, чем запись ПАРАГРАФА запускается. Это не большое беспокойство, потому что браузеры, которые обработают сжатие HTML и обычно игнорировать избыточное пространство. Но есть все еще еще один инструмент форматирования в нашем распоряжении.

Удаление Последнего Пробела


Отметьте - таблица стилей, обсужденная в этом разделе, находится в article1c.xsl, который находится в каталоге xslt/data после того, как Вы разархивировали XSLT examples в install-dir/jaxp-1_4_2-release-date/samples каталог. Результатом является stylizer1c.html, найденный в xslt/data.


Это длится немного пробела, избавляется, добавляя следующий к таблице стилей:

   <xsl:template match="text()">
 <xsl:value-of select="normalize-space()"/>
 </xsl:template>

</xsl:stylesheet>

Выполнение Stylizer с этой таблицей стилей удалит весь остающийся пробел.

Выполнение Выборки Stylizer со Всем Обрезанным Пробелом

  1. Переместитесь к каталогу samples.
    % cd install-dir/jaxp-1_4_2-release-date/samples.
    
  2. Download the XSLT examples by clicking this link и разархивируйте их в install-dir/jaxp-1_4_2-release-date/samples каталог.
  3. Переместитесь к каталогу xslt.
    cd xslt
    
  4. Скомпилируйте выборку Stylizer.

    Введите следующую команду:

    % javac Stylizer.java
    
  5. Выполните выборку Stylizer на article1.xml, используя таблицу стилей article1c.xsl.
    % java Stylizer 
      data/article1c.xsl  
      data/article1.xml
    

    Вывод теперь похож на это:

    <html>
    <body>
    <h1 align="center">A Sample Article
    </h1>
    <h2>The First Major Section</h2>
    <p>This section will introduce a subsection.
    </p>
    <h3>The Subsection Heading</h3>
    <p>This is the text of the subsection.
    </p>
    </body>
    </html>
    

    Это вполне немного лучше. Конечно, было бы более хорошо, если бы это было расположено с отступом, но это, оказывается, несколько более твердо чем ожидаемый. Вот некоторые возможные авеню атаки, наряду с трудностями:

    Опция отступа

    К сожалению, опция indent="yes", которая может быть применена к выводу XML, не доступна для вывода HTML. Даже если бы та опция была доступна, то она не помогла бы, потому что элементы HTML редко вкладываются! Хотя источник HTML часто располагается с отступом, чтобы показать подразумеваемую структуру, сами HTML-тэги не вкладываются в пути, который создает реальную структуру.

    Переменные отступа

    Функция <xsl:text> позволяет Вам добавлять любой текст, который Вы хотите, включая пробел. Таким образом, это могло очевидно использоваться, чтобы вывести пространство добавления отступа. Проблема состоит в том, чтобы изменить количество пространства добавления отступа. Переменные XSLT походят на хорошую идею, но они не работают здесь. Причина состоит в том, что, когда Вы присваиваете значение переменной в шаблоне, значение известно только в пределах того шаблона (статически, во время компиляции). Даже если переменная определяется глобально, присвоенное значение не сохранено в пути, который позволяет этому быть динамически известным другими шаблонами во времени выполнения. Когда <apply-templates/> вызывает другие шаблоны, те шаблоны не сознают любые переменные настройки, сделанные в другом месте.

    Параметризованные шаблоны

    Используя параметризованный шаблон другой способ изменить поведение шаблона. Но определяя количество пространства добавления отступа, чтобы передать, поскольку параметр остается затруднением проблемы.

    В настоящее время, тогда, кажется, нет никакого хорошего способа управлять добавлением отступа отформатированного HTML, выводят. Это было бы неудобно, если Вы должны были вывести на экран или отредактировать HTML как простой текст. Но это не проблема, если Вы делаете свое редактирование на форме XML, используя версию HTML только для дисплея в браузере. (Когда Вы просматриваете stylizer1c.html, например, Вы видите результаты, которые Вы ожидаете).

Обработка Остающихся Элементов Структуры

В этом разделе Вы обработаете LIST и элементы NOTE, которые добавляют больше структуры к статье.


Отметьте - демонстрационным документом, описанным в этом разделе, является article2.xml, и таблицей стилей, используемой, чтобы управлять этим, является article2.xsl. Результатом является stylizer2.html. Эти файлы находятся в каталоге xslt/data после того, как Вы разархивировали XSLT examples в install-dir/jaxp-1_4_2-release-date/samples каталог.


Запустите, добавляя некоторые данные тестирования к демонстрационному документу:

<?xml version="1.0"?>
<ARTICLE>
<TITLE>A Sample Article</TITLE>
 <SECT>The First Major Section
    ...
  </SECT>
  <SECT>The Second Major Section
  <PARA>This section adds a LIST and a NOTE.
    <PARA>Here is the LIST:
      <LIST type="ordered">
        <ITEM>Pears</ITEM>
        <ITEM>Grapes</ITEM>
      </LIST>
  </PARA>
  <PARA>And here is the NOTE:
  <NOTE>Don't forget to go to the 
           hardware store on your way
           to the grocery!
  </NOTE>
  </PARA>
 </SECT> 
</ARTICLE>

Отметьте - Хотя list и note в XML-файле содержатся в их соответствующих абзацах, это действительно не имеет никакого значения, содержатся ли они или нет; сгенерированный HTML будет тем же самым так или иначе. Но содержание их сделает их легче иметь дело с в ориентированном на схему редакторе.


Измените Обработку <PARA>

Затем, измените шаблон PARA, чтобы учесть факт, что мы теперь позволяем некоторым из элементов структуры быть встроенными с абзацем:

<xsl:template match="PARA">
<p> <xsl:apply-templates select=
    "text()|B|I|U|DEF|LINK"/>
 </p>
 <xsl:apply-templates select=
    "PARA|LIST|NOTE"/>
</xsl:template>

Эта модификация использует тот же самый метод, который Вы использовали для заголовков раздела. Единственная разница - то, что элементы SECT не ожидаются в пределах абзаца. (Однако, абзац мог легко существовать в другом абзаце например как заключенный в кавычки материал).

Обработайте Элементы <ITEM> и <LIST>

Теперь Вы готовы добавить шаблон, чтобы обработать элементы LIST:

<xsl:template match="LIST">
 <xsl:if test="@type='ordered'"> 
  <ol>
   <xsl:apply-templates/>
    </ol>
    </xsl:if>
    <xsl:if test="@type='unordered'">
     <ul>
      <xsl:apply-templates/>
     </ul>
 </xsl:if>
</xsl:template>

</xsl:stylesheet>

Тег <xsl:if> использует атрибут test="", чтобы определить Булево условие. В этом случае значение атрибута типа тестируется, и список, который сгенерирован изменения в зависимости от того, упорядочивается ли значение или неупорядочивается.

Отметьте две важных вещи в этом примере:

Теперь закончите Обработку списков, обрабатывая элементы ЭЛЕМЕНТА:

 <xsl:template match="ITEM">
 <li><xsl:apply-templates/>
 </li>
 </xsl:template>

</xsl:stylesheet>

Упорядочивание Шаблонов в Таблице стилей

К настоящему времени у Вас должна быть идея, что шаблоны независимы от друг друга, таким образом, обычно не имеет значения, где они происходят в файле. Так с этого момента мы покажем только шаблон, который Вы должны добавить. (Ради сравнения они всегда добавляются в конце таблицы стилей в качестве примера).

Порядок действительно имеет значение, когда два шаблона могут примениться к тому же самому узлу. В этом случае тот, который определяется последний, является тем, который находится и обрабатывается. Например, чтобы изменить упорядочивание списка с отступом, чтобы использовать нижний регистр alphabetics, Вы могли определить шаблонный образец, который похож на это: //LIST//LIST. В том шаблоне Вы использовали бы опцию HTML, чтобы генерировать алфавитное перечисление вместо числового.

Но такой элемент мог также быть идентифицирован образцом //LIST. Удостовериться, что надлежащая обработка делается, шаблон, который определяет, //LIST должен был бы появиться перед шаблоном, который определяет //LIST//LIST.

Обработайте Элементы <NOTE>

Последний остающийся элемент структуры является элементом NOTE. Добавьте следующий шаблон, чтобы обработать это.

 <xsl:template match="NOTE">
 <blockquote><b>Note:</b><br/>
 <xsl:apply-templates/>
 </p></blockquote>
 </xsl:template>

</xsl:stylesheet>

Этот код переводит в рабочее состояние интересную проблему, которая следует из включения тега <br/>. Для файла, чтобы быть правильно построенным XML, тег должен быть определен в таблице стилей как <br/>, но тот тег не распознается многими браузерами. И хотя большинство браузеров распознает последовательность <br></br>, они все обрабатывают это как конец абзаца вместо однострочного повреждения.

Другими словами преобразование должно генерировать тег <br>, но таблица стилей должна определить <br/>. Это приносит нам к главной причине, по которой специальный выходной тег мы добавили рано в таблице стилей:

<xsl:stylesheet ... >
   <xsl:output method="html"/>
   [...]
</xsl:stylesheet>

Та выходная спецификация преобразовывает пустые теги, такие как <br/> к их HTML-форме, <br>, на выводе. То преобразование важно, потому что большинство браузеров не распознает пустые теги. Вот список тегов, на которые влияют:

area      frame   isindex
base      hr      link
basefont  img     meta
br        input   param
col

Чтобы подвести итог, по умолчанию XSLT производит правильно построенный XML на выводе. И потому что таблица стилей XSL является правильно построенным XML, чтобы запуститься с, невозможно легко поместить тег, такой как <br> в середине этого. Тег <xsl:output method="html"/> решает проблему так, чтобы можно было кодировать <br/> в таблице стилей, но получить <br> в выводе.

Другая главная причина определения <xsl:output method="html"/> состоит в том, что, как со спецификацией <xsl:output method="text"/>, сгенерированного текста не оставляют. Например, если таблица стилей будет включать ссылку на сущность <, то это появится как символ < в сгенерированном тексте. Когда XML сгенерирован, с другой стороны, ссылка на сущность < в таблице стилей была бы неизменна, таким образом, это появится как < в сгенерированном тексте.


Отметьте - Если Вы фактически будете хотеть, чтобы < был сгенерирован как часть вывода HTML, то Вы должны будете закодировать это как &lt;. Та последовательность становится < на выводе, потому что только & преобразовывается в символ &.


Выполнение Выборки Stylizer С LIST и Определенными Элементами NOTE

  1. Переместитесь к каталогу samples.
    % cd install-dir/jaxp-1_4_2-release-date/samples.
    
  2. Download the XSLT examples by clicking this link и разархивируйте их в install-dir/jaxp-1_4_2-release-date/samples каталог.
  3. Переместитесь к каталогу xslt.
    cd xslt
    
  4. Скомпилируйте выборку Stylizer.

    Введите следующую команду:

    % javac Stylizer.java
    
  5. Выполните выборку Stylizer на article2.xml, используя таблицу стилей article2.xsl.
    % java Stylizer data/article2.xsl  data/article2.xml
    

    Вот HTML, который сгенерирован для второго раздела, когда Вы выполняете программу теперь:

    ...
    <h2>The Second Major Section
    </h2>
    <p>This section adds a LIST and a NOTE.
    </p>
    <p>Here is the LIST:
    </p>
    <ol>
    <li>Pears</li>
    <li>Grapes</li>
    </ol>
    <p>And here is the NOTE:
    </p>
    <blockquote>
    <b>Note:</b>
    <br>Do not forget to go to the hardware store on your way to the grocery!
    </blockquote>
    

Процесс, Встроенный (Контент) Элементы

Единственные остающиеся теги в типе ARTICLE являются встроенными тегами - те, которые не создают разрыв строки в выводе, но вместо этого интегрируются в поток текста, из которого они являются частью.

Встроенные элементы отличаются от элементов структуры в тот, встроенные элементы являются частью контента тега. Если Вы думаете об элементе как об узле в дереве документов, то у каждого узла есть и контент и структура. Контент составляется из текста и встроенных тегов, которые это содержит. Структура состоит из других элементов (элементы структуры) под тегом.


Отметьте - демонстрационным документом, описанным в этом разделе, является article3.xml, и таблицей стилей, используемой, чтобы управлять этим, является article3.xsl. Результатом является stylizer3.html.


Запустите, добавляя еще один бит данных тестирования к демонстрационному документу:

<?xml version="1.0"?>
<ARTICLE>
 <TITLE>A Sample Article</TITLE>
  <SECT>The First Major Section
      [...]
  </SECT>
  <SECT>The Second Major Section
      [...]
  </SECT> 
<SECT>The <i>Third</i> 
    Major Section
 <PARA>In addition to the inline tag
    in the heading, 
 this section defines the term  
    <DEF>inline</DEF>,
 which literally means "no line break". 
 It also adds a simple link to the main page 
    for the Java platform 
(<LINK>http://java.sun.com</LINK>),
 as well as a link to the 
 <LINK target="http://java.sun.com/xml">
   XML </LINK> 
 page.
 </PARA>
 </SECT> 
</ARTICLE>

Теперь обработайте встроенные элементы <DEF> в абзацах, переименовывая их к тегам курсива HTML:

<xsl:template match="DEF">
 <i> <xsl:apply-templates/> </i> 
</xsl:template>

Затем, прокомментируйте нормализацию текстового узла. Это служило своей цели, и теперь Вы - то, до такой степени, что Вы должны сохранить важные пробелы:

<!--  
<xsl:template match="text()">
  <xsl:value-of select="normalize-space()"/>
   </xsl:template>
-->

Эта модификация препятствует нам терять пробелы перед тегами, такими как <I> и <DEF>. (Попробуйте программу без этой модификации, чтобы видеть результат).

Теперь обработайте основные встроенные элементы HTML, такие как <B>, <I>, и <U> для полужирного, курсива, и подчеркивания.

<xsl:template match="B|I|U">
 <xsl:element name="{name()}">
 <xsl:apply-templates/>
 </xsl:element> 
</xsl:template>

Тег <xsl:element> позволяет Вам вычислять элемент, который Вы хотите генерировать. Здесь, Вы генерируете соответствующий встроенный тег, используя имя текущего элемента. В частности отметьте использование изогнутых фигурных скобок ({}) в выражении name="..". Те изогнутые фигурные скобки заставляют текст в кавычках быть обработанным как выражение XPath вместо того, чтобы быть интерпретированными как литеральная строка. Здесь, они заставляют XPath функция name() возвращать имя текущего узла.

Изогнутые фигурные скобки распознаются где угодно, что шаблон значения атрибута может произойти. (Шаблоны значения атрибута определяются в разделе 7.6.2 из спецификации XSLT, и они кажутся несколько мест в шаблонных определениях). В таких выражениях изогнутые фигурные скобки могут также использоваться, чтобы обратиться к значению атрибута, {@foo}, или к контенту элемента {foo}.


Отметьте - можно также генерировать атрибуты, используя <xsl:attribute>. Для получения дополнительной информации см. раздел 7.1.3 из Спецификации XSLT.


Последний остающийся элемент является тегом LINK. Самый легкий способ обработать тот тег будет состоять в том, чтобы установить именованный шаблон, которым мы можем управлять с параметром:

<xsl:template name="htmLink">
 <xsl:param name="dest" 
    select="UNDEFINED"/> 
 <xsl:element name="a">
 <xsl:attribute name="href">
 <xsl:value-of select=""/>
 </xsl:attribute>
 <xsl:apply-templates/> 
 </xsl:element> 
</xsl:template>

Существенное различие в этом шаблоне - то, что, вместо того, чтобы определить пункт соответствия, Вы даете шаблону имя, используя пункт name="". Таким образом, этот шаблон выполняется только, когда Вы вызываете его.

В пределах шаблона Вы также определяете параметр под названием dest, используя тег <xsl:param>. Некоторое время проверки на ошибки, Вы используете избранный пункт, чтобы дать тому параметру значение по умолчанию UNDEFINED. Чтобы сослаться на переменную в теге <xsl:value-of>, Вы определяете.


Отметьте - Отзыв, что запись в кавычках интерпретируется как выражение, если это далее не включается в одинарные кавычки. Именно поэтому одинарные кавычки были необходимы ранее в "@type='ordered'", чтобы удостовериться, что упорядочивал, интерпретировался как строка.


Тег <xsl:element> генерирует элемент. Ранее, Вы были в состоянии просто определить элемент, который мы хотим, кодируя что-то как <html>. Но вот, пожалуйста динамически генерируя контент привязки HTML (<a>) в теле тега <xsl:element>. И Вы динамически генерируете атрибут href привязки, используя тег <xsl:attribute>.

Последняя важная часть шаблона является тегом <apply-templates>, который вставляет текст от текстового узла под элементом LINK. Без этого в сгенерированной ссылке HTML не было бы никакого текста.

Затем, добавьте шаблон для тега LINK, и вызовите именованный шаблон изнутри этого:

<xsl:template match="LINK">
 <xsl:if test="@target">
 <!--Target attribute specified.-->
 <xsl:call-template 
    name="htmLink">
 <xsl:with-param name="dest" 
    select="@target"/> 
 </xsl:call-template>
 </xsl:if>
</xsl:template>
<xsl:template name="htmLink">

[...]

Пункт test="@target" возвращает true, если целевой атрибут существует в теге ССЫЛКИ. Таким образом, этот тег <xsl-if> генерирует ссылки HTML, когда текст ссылки и цели, определенной для него, отличается.

Тег <xsl:call-template> вызывает именованный шаблон, тогда как <xsl:with-param> определяет параметр, используя пункт имени и определяет его значение, используя избранный пункт.

Как самый последний шаг в процессе конструкции таблицы стилей, добавьте тег <xsl-if>, чтобы обработать теги LINK, у которых нет целевого атрибута.

<xsl:template match="LINK">
   <xsl:if test="@target">
      [...]
   </xsl:if>

   <xsl:if test="not(@target)">
 <xsl:call-template name="htmLink">
 <xsl:with-param name="dest">
 <xsl:apply-templates/>
 </xsl:with-param>
 </xsl:call-template>
 </xsl:if>
</xsl:template>

Пункт not(...) инвертирует предыдущий тест (помните, нет никакого выражения else). Таким образом, эта часть шаблона интерпретируется, когда целевой атрибут не определяется. На сей раз значение параметра прибывает не из избранного пункта, а из содержания элемента <xsl:with-param>.


Отметьте - Только, чтобы сделать это явным: Параметры и переменные (которые обсуждаются через несколько моментов в том, Что еще Может XSLT Делать? могли определить их значение или избранным пунктом, который позволяет Вам использовать выражения XPath, или контентом элемента, который позволяет Вам использовать теги XSLT.


В этом случае контент параметра сгенерирован тегом <xsl:apply-templates/>, который вставляет содержание текстового узла под элементом LINK.

Выполнение Выборки Stylizer Со Встроенными Определенными Элементами

  1. Переместитесь к каталогу samples.
    % cd install-dir/jaxp-1_4_2-release-date/samples.
    
  2. Download the XSLT examples by clicking this link и разархивируйте их в install-dir/jaxp-1_4_2-release-date/samples каталог.
  3. Переместитесь к каталогу xslt. <
    cd xslt
    
  4. Скомпилируйте выборку Stylizer.

    Введите следующую команду:

    % javac Stylizer.java
    
  5. Выполните выборку Stylizer на article3.xml, используя таблицу стилей article3.xsl.
    % java Stylizer data/article3.xsl  data/article3.xml
    

    Когда Вы выполняете программу теперь, результаты должны выглядеть примерно так:

    [...]
    <h2>The <i>Third</i> Major Section</h2>
    <p>In addition to the inline tag in the heading, this section  defines the term <i>inline</i>, which literally means "no line break". It also adds a simple link to the main page for the Java platform (<a href="http://java.sun.com">http://java.sun.com</a>),  as well as a link to the <a href="http://java.sun.com/xml">XML</a> page.</p>
    

    Очень хорошо! Вы теперь преобразовали довольно сложный XML-файл в HTML. (Столь же простой, как это появляется сначала, это, конечно, обеспечивает большую возможность для исследования).

Печать HTML

Вы теперь преобразовали XML-файл в HTML. Однажды, кто-то произведет осведомленный о HTML механизм печати, который Вы будете в состоянии найти и использовать через API Службы Печати Java. В той точке у Вас будет возможность напечатать произвольный XML-файл, генерируя HTML. Все, что необходимо сделать, должно установить таблицу стилей и использовать Ваш браузер.

Что еще Может XSLT Делать?

Столь же длинный, как этот раздел был, он только поцарапал поверхность возможностей XSLT. Много дополнительных возможностей ждут Вас в спецификации XSLT. Вот несколько вещей искать:

import (Раздел 2.6.2) и include (раздел 2.6.1)

rt (Раздел 2.6.2) и включает (раздел 2.6.1) Использование эти операторы, чтобы построить из модулей и объединить таблицы стилей XSLT. Включать оператор просто вставляет любые определения от включенного файла. Оператор импорта позволяет Вам переопределять определения в импортированном файле с определениями в Вашей собственной таблице стилей.

Циклы for-each (раздел 8)

Цикл по набору элементов и процесса каждый поочередно.

choose (оператор выбора) для условной обработки (раздел 9.2)

Ответвление к одному из многократных путей обработки в зависимости от входного значения.

Генерирование чисел (раздел 7.7)

Динамически генерируйте пронумерованные разделы, пронумерованные элементы, и числовые литералы. XSLT обеспечивает три режима нумерации:

  • Единственный: элементы Чисел в соответствии с единственным заголовком, как упорядоченный список в HTML

  • Многократный: Производит многоуровневую нумерацию такой как "1.3"

  • Любой: Последовательно элементы чисел везде, где они появляются, как со сносками в уроке.

Форматирование чисел (раздел 12.3)

Форматирование перечисления управления так, чтобы Вы получили численные данные (format="1"), верхний регистр alphabetics (format="A"), нижний регистр alphabetics (format="a"), или соединили числа, как "1", так же как числа и количество валюты, которому удовлетворяют для определенной международной локали.

Сортировка вывода (раздел 10)

Произведите вывод в требуемом порядке сортировки.

Основанные на режиме шаблоны (раздел 5.7)

Обработайте элемент многократно, каждый раз в различном "режиме". Вы добавляете, что режим приписывает шаблонам и затем определяет <apply-templates mode="...">, чтобы применить только шаблоны с соответствующим режимом. Объединитесь с атрибутом <apply-templates select="...">, чтобы применить основанную на режиме обработку к подмножеству входных данных.

Переменные (раздел 11)

Переменные - что-то как параметры метода, в которых они позволяют Вам управлять поведением шаблона. Но они не столь же ценны, как Вы могли бы думать. Значение переменной известно только в рамках текущего шаблона или тега <xsl:if> (например), в котором это определяется. Невозможно передать значение от одного шаблона до другого, или даже от включенной части шаблона к другой части того же самого шаблона.

Эти операторы являются истиной даже для "глобальной" переменной. Можно изменить его значение в шаблоне, но изменение применяется только к тому шаблону. И когда выражение, используемое, чтобы определить глобальную переменную, оценивается, та оценка имеет место в контексте корневого узла структуры. Другими словами глобальные переменные являются чрезвычайно константами этапа выполнения. Те константы могут быть полезными для изменения поведения шаблона, особенно когда вместе с включают и импортируют операторы. Но переменные не являются механизмом управления данными общего назначения.

Проблема с Переменными

Заманчиво создать единственный шаблон и установить переменную для места назначения ссылки, вместо того, чтобы пойти в проблему установить параметризованный шаблон и вызвать это два различных пути. Идея состоит в том, чтобы установить переменную в значение по умолчанию (скажите, текст тега LINK), и затем, если целевой атрибут существует, устанавливает целевую переменную в значение целевого атрибута.

Это было бы хорошей идеей - если бы она работала. Но снова, проблема - то, что переменные известны только в контексте, в пределах которого они определяются. Так, когда Вы кодируете тег <xsl:if>, чтобы изменить значение переменной, значение известно только в пределах контекста тега <xsl:if>. Как только с </xsl:if> встречаются, любое изменение к установке переменной теряется.

Так же заманчивая идея является возможностью замены спецификации text()|B|I|U|DEF|LINK с переменной (). Но потому что значение переменной определяется тем, где это определяется, значение встроенной переменной глобальной переменной состоит из текстовых узлов, узлов <B>, и так далее, которые, оказывается, существуют на корневом уровне. Другими словами значение такой переменной, в этом случае, является нулем.


Проблемы с примерами? Попытайтесь Компилировать и Выполнить Примеры: FAQ.
Жалобы? Поздравление? Предложения? Дайте нам свою обратную связь.

Предыдущая страница: Генерирование XML от Произвольной Структуры данных
Следующая страница: Потоковая передача API для XML