2009-06-04 3 views
3

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

Есть ли удобно использовать XSLT шаблоны, мне нужно, чтобы научиться делать такие вещи, как:

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

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

<xsl:element> 

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

ответ

8

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

<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()"/> 

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

+0

Прошу прощения, потребовалось время. Это именно то, что я хотел (я думаю). Мне нужно проверить его немного больше. –

3

Самым большим препятствием для преобразования 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

Ну, xslt имеет «другое пространство имен xslt», вы также можете его использовать! – alamar

+1

http://www.w3.org/1999/XSL/Transform - это обычное пространство имен, а http://www.w3.org/1999/XSL/TransformAlias ​​- это еще один :) – alamar

0

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

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^