предварительная обработка в XSLT - PullRequest
1 голос
/ 07 декабря 2009

Возможно ли вообще выполнить предварительную обработку в XSLT?

с предварительной обработкой я имею в виду обновление (в представлении памяти) исходного дерева.

это возможно, или мне нужно сделать несколько преобразований для него.

вариант использования: у нас есть справочные руководства по Docbook для наших клиентов, но для определенных клиентов им нужны разные «скины» (разные изображения и т. д.). так что я надеялся сделать, это преобразовать путь fileref в зависимости от параметра. затем примените остальные обычные шаблоны Docbook XSL.

Ответы [ 4 ]

3 голосов
/ 08 декабря 2009

Расширяя ответ Иамона ...

В случае XSLT 1.0 или 2.0 вы должны начать с помещения промежуточного (предварительно обработанного) результата в элемент , объявленный либо глобально (верхний уровень), либо локально (внутри шаблона). ).

<xsl:variable name="intermediate-result">
  <!-- code to create pre-processed result, e.g.: -->
  <xsl:apply-templates mode="pre-process"/>
</xsl:variable>

В XSLT 2.0 значение переменной $ промежуточный результат представляет собой последовательность узлов, состоящую из одного узла документа (в XSLT / XPath 1.0 называлась «корневым узлом»). Вы можете обращаться к нему и использовать его так же, как и к любой другой переменной, например, select = "$ промежуточный-результат / документ"

Но в XSLT 1.0 значение переменной $ промежуточный результат не является набором узлов первого класса. Вместо этого это называется фрагментом дерева результатов. Он ведет себя как набор узлов, содержащий один корневой узел, но вы ограничены в том, как вы можете его использовать. Вы можете скопировать его и получить его строковое значение, но вы не можете развернуть его с помощью XPath, как в select = "$ промежуточный-результат / документ". Чтобы сделать это, вы должны сначала преобразовать его в набор узлов первого класса, используя функцию расширения вашего процессора node-set (). В Saxon 6.5, libxslt и 4xslt вы можете использовать exsl: node-set () (как в ответе Eamon). В MSXML вам нужно использовать msxsl: node-set (), где xmlns: msxsl = "urn: schemas-microsoft-com: xslt", а в Xalan я считаю, что это называется xalan: nodeset () (без дефис, но вам придется Google для URI пространства имен). Например: select = "exsl: node-set ($ промежуточный-результат) / doc"

XSLT 2.0 просто упразднил фрагмент результирующего дерева, сделав ненужным node-set ().

1 голос
/ 08 декабря 2009

Поскольку вы пытаетесь сгенерировать немного другой вывод из одного и того же источника DocBook XML, вы можете захотеть взглянуть на поддержку «профилирования» (условной разметки) в таблицах стилей DocBook XSL. См. Глава 26 в DocBook XSL: Полное руководство Боба Стейтона:

Профилирование - это термин, используемый в DocBook описать условный текст. Условный текст означает, что вы можете создать один документ XML с некоторыми элементы помечены как условные. когда Вы обрабатываете такой документ, вы можете указать, какие условия применяются для эта версия вывода, а таблица стилей будет включать или исключать помеченный текст для удовлетворения условий. Эта функция полезна, когда вам нужно производить более одной версии документ, и версии отличаются второстепенные пути.

Например, чтобы использовать разные изображения, скажем, для версий Windows и Mac одного и того же документа, у вас может быть фрагмент DocBook XML, подобный следующему:

<figure>
  <title>The Foo dialog</title>
  <mediaobject>
    <imageobject os="windows">
      <imagedata fileref="screenshots/windows/foo.png"/>
    </imageobject>
    <imageobject os="mac">
      <imagedata fileref="screenshots/mac/foo.png"/>
    </imageobject>
  </mediaobject>
</figure>

Затем вы должны использовать версии стилей DocBook XSL с поддержкой профилирования, для параметра profile.os установлено значение windows или mac.

1 голос
/ 07 декабря 2009

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

Если ваш процессор xslt поддерживает EXSLT , функция exsl: node-set () сделает то, что вы ищете. msxml также имеет функцию расширения с тем же именем (но с другим пространством имен uri, функции, к сожалению, тривиально несовместимы).

0 голосов
/ 08 декабря 2009

Может быть, вы должны использовать XSLT "ООП" методы здесь. Поместите все общие шаблоны для всех клиентов в таблицу стилей и создайте таблицу стилей для каждого клиента с конкретными шаблонами, перекрывающими общие. Импортируйте общую таблицу стилей в определенные с помощью xsl: import, и вы будете выполнять только одну обработку, вызывая таблицу стилей, соответствующую клиенту.

...