Динамически включать другие файлы XSL в XSLT - PullRequest
8 голосов
/ 29 октября 2011

У меня небольшая проблема, есть ли способ динамически включить другой xsl? Например:

<xsl:variable name="PathToWeb" select="'wewe'"/>
<xsl:include href="http://{$PathToWeb}/html/xsl/head.xsl" />
<xsl:include href="http://{$PathToWeb}/html/xsl/navigation.xsl" />
<xsl:include href="http://{$PathToWeb}/html/xsl/promo.xsl" />
<xsl:include href="http://{$PathToWeb}/html/xsl/3columns.xsl" />

<xsl:include href="http://{$PathToWeb}/html/xsl/footer.xsl" />

Ответы [ 5 ]

5 голосов
/ 29 октября 2011

У меня небольшая проблема, есть ли способ динамически включить другой xsl?Например:

<xsl:variable name="PathToWeb" select="'wewe'"/> 
<xsl:include href="http://{$PathToWeb}/html/xsl/head.xsl" /> 
<xsl:include href="http://{$PathToWeb}/html/xsl/navigation.xsl" /> 
<xsl:include href="http://{$PathToWeb}/html/xsl/promo.xsl" /> 
<xsl:include href="http://{$PathToWeb}/html/xsl/3columns.xsl" /> 

<xsl:include href="http://{$PathToWeb}/html/xsl/footer.xsl" />

Недопустимо иметь переменную ссылку в атрибуте href <xsl:include>.В соответствии со спецификациями W3C XSLT 1.0 и XSLT 2.0 значение этого атрибута должно быть ссылкой на URI.

Однако, если значение переменной $PathToWeb известно до начала преобразования, оно можетиспользоваться различными способами для динамического создания представления таблицы стилей, в котором вышеприведенные операторы <xsl:include> содержат URI желаний (после замены ссылки на $PathToWeb требуемым значением:

  1. Создание новой таблицы стилей из текущей с использованием XSLT.

  2. Загрузка таблицы стилей в виде объекта XmlDocument . Затем найдите соответствующий <xsl:include> элементов и установите для их атрибутов href требуемые значения. Наконец, вызовите преобразование, используя измененный таким образом XmlDocument, который представляет таблицу стилей.

Метод 2.используется в течение 11 лет в XPath Visualizer для динамического задания точного значения атрибута select, используемого для выбора всехузлы, которые выбирает пользовательское выражение XPath, и генерируют HTML-документ, представляющий XML-документ со всеми выделенными и видимыми узлами, выделенными.

5 голосов
/ 07 сентября 2012

Я решил эту проблему по-другому, может быть полезно для тех, кто работает с Java и XSLT (это решение специально для людей, использующих пакет javax.xml.transform).

XSLT трансформаторная фабрика позволяет устанавливать пользовательский распознаватель URI. Скажите, выглядит ли ваш XSLT

<?xml version="1.0" encoding="utf-8"?>
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" version="4.0" encoding="UTF-8"/>
    <xsl:include href="import://stackoverflow.com/xsl"/>
    ...

Метод распознавателя URI resolve получит import://stackoverflow.com/xsl в качестве параметра href. import:// может служить «специальной» схемой идентификатора для пользовательских включений, так что вы можете обнаружить ее и создать / вернуть javax.xml.transform.Source, которая указывает на нужный файл. Например:

TransformerFactory tf = TransformerFactory.newInstance();
URIResolver delegate = tf.getURIResolver();
tf.setURIResolver( new CustomURIResolver( delegate ) );

Тогда внутри CustomURIResolver:

  public Source resolve( String href, String base )
    throws TransformerException {
    Source result = null;
    URI uri = null;

    try {
      uri = new URI( href );
    }
    catch( Exception e ) {
      throw new TransformerException( e );
    }

    // The XSLT file has a URI path that allows for a file to be included
    // dynamically.
    if( "import".equalsIgnoreCase( uri.getScheme() ) &&
        "stackoverflow.com".equalsIgnoreCase( uri.getAuthority() ) ) {
      result = openTemplate();
    }
    else {
      result = getDelegate().resolve( href, base );
    }

    return result;
  }

Добавьте метод openTemplate(), который включает логику для динамического определения открываемого файла XSL.

2 голосов
/ 29 октября 2011

Вы не можете сделать это. Причины просты:

XSL сначала расширит xsl: include во время компиляции, прежде чем делать что-либо еще. В этот момент ваша «переменная» не известна и не может быть известна, и вы не сможете изменить скомпилированное преобразование после его компиляции. Кроме того, href - это унифицированный указатель ресурса, а не выражение XPath, поэтому нельзя просто развернуть в нем переменную.

0 голосов
/ 20 февраля 2017

Мои 2 пенса стоят на простой (но эффективной) альтернативе (для иллюстрации предоставлен только psuedocode. Действовать осторожно :)

Схема подхода: Альтернативное решение может состоять из простого сценария-оболочки (например, shell, bash-скрипта или другого) для вызова вашего основного xsl, использования режимов name xslt, основного файла xslt, простого (пустого) статически определенного xslt-файла.

В основной xsl включите статический xsl-файл, который вызовет / загрузит все динамически включенные xslt. Основной xsl будет тогда работать в 2 режимах: нормальный режим (режим не указан), где он будет загружать файлы расширения xsl, включенные в него сам, и в статический xls, и обрабатывать любые входные файлы, или делать все, что когда-либо было полезно делать. Второй режим, режим препроцессора, будет предназначен для загрузки двоично указанных экземпляров / файлов xsl. Этот режим будет вызываться как этап препроцессора для основного цикла обработки. Поток процесса для основного xslt будет вызывать его с указанным режимом препроцессора, а затем вызывать его снова с указанным нормальным режимом обработки.

Советы по реализации: Для каждого xlator определите файл xslt расширения n, ext_xsl_container, целью которого является включение любого расширения xslt. например,

    <xsl:stylesheet  >
     <!-- main xslt --> 
        <xsl:import href="../xsl/ext_xsl_container.xsl/>
         <!--param: list  of  dynamically specified  extension  xsl --> 
         <xsl:param name="extXslUrlList"/>
        <!--param:preprocessor  mode  flag, with default set to false --> 
        <xsl:param name="preProcModeLoadXslF" select="false()" type="xs:boolean"
<!-- param: path to the staticall included ext_xsl_container: with default  value set --> 
    <xsl:param name="extXslContainerUrl" select="'../xsl/ext_xsl_container.xsl'"/>

        <xsl:if test=" ($preProcModeLoadXslF=true())" >
            <xsl:call-template name="loadDynamicXsl" mode="preprocess_load_xsl"
        </xsl:if>
        ....
    </xsl:stylesheet>

Таблица стилей ext_xslt_container будет включать любые расширения xslts. Он может динамически обновляться во время выполнения, редактируя его (как XML-документ), добавляя оператор включения для расширенных таблиц стилей xsl. например,

 <!-- ext xsl container : ext_xsl_container.xsl--> 
<xsl:stylesheet
    <xsl:include href="ext_xsl_container.xsl"/>

    ....
</xsl:stylesheet 

Создайте небольшой шаблон, скажем template_load_ext_xsl, с назначенным режимом, скажем mode = "preprocess_load_xsl" например,

<xsl:template name="loadDynamicXsl" mode="preprocess_load_xsl">
    <!-- param: path to the staticall included ext_xsl_container--> 
    <xsl:param name="extXslContainerUrl"/> 
    <!--param: list  of  dynamically specified  extension  xsl --> 
    <xsl:param name="extXslUrlList"/>

   <!-- step 1, [optional ]  open  the  ext Xsl container  file  --> 
   <!-- step 2  [optional]  clear  contexts of the ext X  -- > 
   <!-- step3  compile a  list of include elements, one  per each ext Xsl file -->
   <!-- step 4 [optional] create a union of the  include  elements  created  with the  content of the xsl container file : ie append  content > 
<!-- step 5 :  write the  union  list of  incudes to the ext XSL  container file -->
<!-- DONE ---> 

</xsl:template>

Шаблон будет принимать в качестве аргументов имя ex_xsl_container и список расширенных файлов xsl (включая их пути). Затем он откроет файл ext_xsl_container в виде XML-документа, добавит (параметры для добавления или очистки файла и добавления нового кода) для каждого расширения: xsl, сохранит файл и выйдет

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

Создайте простой скрипт-обертку (например, bash или shell-скрипт), который будет принимать аргументы для основного xslt, и опцию для запуска режима препроцессора. Сценарий просто вызовет основной xslt дважды, если включена опция режима препроцессора, и включается режим препроцессора при первом запуске, а затем второй вызов в обычном режиме

0 голосов
/ 07 мая 2015

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

1) Создание объекта SimpleXML или DOMDocument из файла XSL.

2) Создайте объект XSLTProcessor.

3) Импортируйте объект документа XSL в объект процессора.

4) Запустите преобразование в файле данных XML.

После 1)XSL можно манипулировать перед компиляцией как часть шага 3).Именно здесь элементы xsl: include могут динамически вставляться из корневого элемента по мере необходимости.

Поэтому для динамической вставки xsl: includes:

1.1) Используйте Xpath | getElementById| getElementsByTagname для проверки данных XML на наличие элементов, для которых вам могут потребоваться дополнительные таблицы стилей.

1.2) Динамически создавать элементы xsl:include из корневого элемента объекта XML XSL.

Вот и все.На шаге 3) измененный объект XSL XML будет скомпилирован так, как если бы он был построен таким образом с самого начала.

Конечно, на уровне 1.2), ЛЮБЫЕ узлы (не просто xsl:include или xsl:import)из других объектов документа XSL могут быть добавлены к ЛЮБЫМ узлам в базовом объекте документа XSL, что обеспечивает более точное управление.Тем не менее, правильная xsl:template конструкция всех таблиц стилей XSL должна значительно упростить вставку xsl:include элементов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...