2009-08-27 2 views
6

У меня есть блок XSLT, который может применяться несколько раз во всем преобразовании. Но я хочу, чтобы он на самом деле запускался только в первый раз, когда он был применен, это shoul будет пропущено все субкультурные времена. Как мне это сделать?В XSLT, могу ли я запустить шаблон только один раз

В качестве примера, это такая вещь, что я хочу сделать: В таблице стилей я определить глобальную переменную:

<xsl:variable name="run_once" select="0"/> 

Тогда я шаблон, который называется несколько раз:

<xsl:template name="some_template"> 
    <xsl:if test="$run_once != 1"> 
     <xsl:variable name="run_once" select="1"/> 
     <xsl:text>THIS TEXT SHOULD APPEAR ONLY ONCE</xsl:text> 
    </xsl:if> 
</xsl:template> 

Это не работает, потому что переменные не могут быть изменены, только перегружены. Итак, как только some_template выходит из $ run_once, снова 0, и текст применяется каждый раз при вызове шаблона. Есть ли какой-либо тип функции ifdef или другой глобальный объект, который я могу установить?

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

  • Мой ввод данных в необработанном XML, мой вывод является отчет в формате WordML.
  • На входе у меня есть ряд узлов (по имени theNode). Некоторые, но не все, из этих узлов должно быть , отображаемое на выходе. Узел должен отображаться только в том случае, если истинна длина строки (x): (0) hairyLogic (волосистая логика, очевидно, длинная и ).
  • theNode также имеет тип (хранится в подэлемент). На входе все theNode того же типа будут всегда сгруппированы вместе. На выходе все номера этого типа должны быть сгруппированы под конкретным заголовком для этого типа (там должен быть только одним заголовком для каждого типа ).

Это решение, которое я закончил с использованием:

... 
<xsl:apply-templates select="theNode[hairyLogic]"/> 
... 

<xsl:template match="theNode"> 
    <xsl:if test="count(preceding-sibling::theNode[type = current()/type and hairyLogic])=0"> 
     <xsl:choose> 
      <xsl:when test="type = 'TYPE1a' or type = 'TYPE1b'"> 
       <xsl:call-template name="TYPE1Heading"/> 
      </xsl:when> 
      <xsl:when test="type = 'TYPE2'"> 
       <xsl:call-template name="TYPE2Heading"/> 
      </xsl:when> 
     </xsl:choose> 
    </xsl:if> 
    ... 
</xsl:template> 

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

Мне не нравится это решение, потому что hairyLogic повторяется, а инструкция if свернута и трудно читается. Может быть, у вас есть лучшее решение, которое не требует переменных переменных?

ответ

2

Я бы предложил использовать шаблоны совпадений по именованным шаблонам, потому что это больше, ну, что такое XSLT-эквивалент pythonic? XSLT-у?Я думаю, вы обнаружите, что в этой методологии обработки вы можете решить проблемы.

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

Можете ли вы пояснить, почему вы не можете обнаружить, когда нужен первый экземпляр? Возможно, мы сможем обработать выражение xpath, которое позволит вам делать то, что вы хотите. Например.

<xsl:template name="some_template"> 
    <xsl:variable name="EXPRESSION" select=".[somelogic='true']"/> 
    <xsl:if test="$EXPRESSION"> 
     <xsl:text>THIS TEXT SHOULD APPEAR ONLY ONCE</xsl:text> 
    </xsl:if> 
</xsl:template> 

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

+0

«Что такое XSLT, эквивалентный pythonic? Xslt-y?» - это «декларативный» –

+0

Да, у меня есть ограничения, которые я не полностью детализировал (добавил к вопросу, если вам интересно). Я решил проблему так, как вы описываете. Мне это не нравится, потому что «somelogic» длинный, грязный и теперь повторяется несколько раз. Это было бы не так плохо, если бы я мог диктовать, когда код XPATH анализируется, как я могу на других функциональных языках. Затем я мог бы хранить бит «somelogic» в переменной и вставлять его в мои выражения, когда это необходимо. – oillio

2

Поскольку XSLT является чисто функциональным языком, есть no глобальные переменные, которые вы можете установить.

Вам придется выбирать обстоятельства, при которых вы вызываете свой шаблон some_template. Если вы хотите только один раз вызвать его, сделайте только один вызов.

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