Каковы некоторые полезные конструкции для использования XSLT для создания XSLT? - PullRequest
3 голосов
/ 04 июня 2009

У меня есть существующая таблица стилей XSLT, которая принимает XML и создает красиво отформатированный XHTML. Я хочу сделать XSL-FO версию этой таблицы стилей для создания PDF через Apache FOP. То, что я хочу знать, это:

Существуют ли какие-либо удобные для использования шаблоны xslt, которые мне нужно научиться выполнять, например:

  • копирование некоторых узлов без изменений
  • копирование большей части узла, но добавление дополнительных атрибутов

Я знаю, что могу создавать новые узлы, используя

<xsl:element>

но есть ли другие полезные вещи, которые мне понадобятся. Обратите внимание, что, хотя я не много копировал из одного формата XSLT в другой, я сделал TONS XML-> XHTML через XSLT, поэтому я знаком с большей частью ядра языка.

Ответы [ 3 ]

8 голосов
/ 05 июня 2009

Шаблон, который вы ищете, является «измененным преобразованием идентичности». Основой этого подхода является правило преобразования идентификаторов, первое правило шаблона в таблице стилей ниже. Каждое правило после этого представляет исключение из поведения копирования.

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

  <!-- By default, copy all nodes unchanged -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- But strip out <foo> elements (including their content) -->
  <xsl:template match="foo"/>

  <!-- For <bar> elements, strip out start & end tags, but leave content --> 
  <xsl:template match="bar">
    <xsl:apply-templates/>
  </xsl:template>

  <!-- For <bat> elements, insert an attribute and append a child --> 
  <xsl:template match="bat">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:attribute name="id">123</xsl:attribute>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

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

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

  <!-- By default, copy all nodes unchanged -->
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates mode="add-atts" select="."/>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

          <!-- By default, don't add any attributes -->
          <xsl:template mode="add-atts" match="*"/>

  <!-- For <bat> elements, insert an "id" attribute -->
  <xsl:template mode="add-atts" match="bat">
    <xsl:attribute name="id">123</xsl:attribute>
  </xsl:template>

</xsl:stylesheet>

Наконец, это можно продвинуть гораздо дальше, используя разные режимы для каждого вида редактирования, который вы, возможно, захотите сделать:

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

  <!-- For <bat> elements, insert an "id" attribute -->
  <xsl:template mode="add-atts" match="bat">
    <xsl:attribute name="id">123</xsl:attribute>
  </xsl:template>

  <!-- Append <new-element/> to <bat> -->
  <xsl:template mode="append" match="bat">
    <new-element/>
  </xsl:template>

  <!-- Insert an element in <foo> content -->
  <xsl:template mode="insert" match="foo">
    <inserted/>
  </xsl:template>

  <!-- Add content before the <bar/> and <bat/> elements -->
  <xsl:template mode="before" match="bar | bat">
    <before-bat-and-bar/>
  </xsl:template>

  <!-- Add content only after <bat/> -->
  <xsl:template mode="after" match="bat">
    <after-bat/>
  </xsl:template>

  <!-- Here's the boilerplate code -->
  <!-- By default, copy all nodes unchanged -->
  <xsl:template match="@* | node()">
    <xsl:apply-templates mode="before" select="."/>
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates mode="add-atts" select="."/>
      <xsl:apply-templates mode="insert" select="."/>
      <xsl:apply-templates/>
      <xsl:apply-templates mode="append" select="."/>
    </xsl:copy>
    <xsl:apply-templates mode="after" select="."/>
  </xsl:template>

          <!-- By default, don't add anything -->
          <xsl:template mode="add-atts" match="*"/>
          <xsl:template mode="insert"   match="*"/>
          <xsl:template mode="append"   match="*"/>
          <xsl:template mode="before"   match="@* | node()"/>
          <xsl:template mode="after"    match="@* | node()"/>

</xsl:stylesheet>

В XSLT 2.0 некоторые шаблоны могут быть немного упрощены благодаря многорежимным правилам шаблонов:

          <!-- By default, don't add anything -->
          <xsl:template mode="add-atts
                              insert
                              append
                              before
                              after" match="@* | node()"/>

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

3 голосов
/ 04 июня 2009

Самым большим препятствием на пути преобразования XSLT является то, что префикс выходного пространства имен совпадает с префиксом фактических команд XSL в вашем преобразовании. Если вы используете «xsl:» как в своих инструкциях XSL, так и в своих выходных данных, ваш механизм XSLT не будет знать разницы между инструкциями XSL, которые он должен выполнять, и теми, которые он должен выводить, поэтому ваш XSLT не будет анализироваться. То есть, если вы не используете псевдоним пространства имен:

<xsl:namespace-alias stylesheet-prefix="x" result-prefix="xsl"/>

Эта инструкция, которая находится внутри <xsl:stylesheet />, позволяет вам записать вашу разметку результата в преобразовании, используя префикс замещающего пространства имен. Позже, когда будет создан выходной документ, префикс, который вы на самом деле хотите, будет вставлен вместо псевдонима. Так, например, вот шаблон, который создает шаблон в вашем выходном документе:

<xsl:template match="xsl:template[@match='title']>
   <x:template match="title>
      <x:apply-templates />
   </x:template>
</xsl:template>

Вот хорошая статья: http://www.xml.com/pub/a/2001/04/04/trxml/

0 голосов
/ 21 августа 2009

В прошлом я разрабатывал таблицы стилей XSL-FO, а затем использовал таблицу стилей Render-X FO2HTML для преобразования XSL-FO в HTML. Он преобразует <block> элементы в <div>, <inline> в <span> и т. Д.

Я не использовал их раньше, но вы можете попробовать таблицы стилей HTML2FO . Или, по крайней мере, просматривая их, чтобы позаимствовать некоторые идеи.

Поскольку в HTML отсутствуют некоторые конструкции разбиения на страницы, которые предоставляет FO, он может не дать вам всего того, что вам нужно для вывода XSL-FO, но, вероятно, может обрабатывать большую часть логики преобразования из HTML в элемент XSL-FO / атрибуты в теле документа.

...