Можете ли вы смоделировать логический флаг в XSLT? - PullRequest
1 голос
/ 15 апреля 2010

Я хотел бы смоделировать флаг в сценарии xslt. Идея состоит в том, чтобы шаблон foo установил флаг (или переменную счетчика, или что-нибудь еще), чтобы к нему можно было получить доступ из панели шаблонов. Bar вызывается не из foo, а из общего родительского шаблона (в противном случае я бы передал ему параметр). Структура выглядит так:

<xsl:template match="bla">
  <xsl:apply-templates select="foo"/> <!-- depending on the contents of foo... -->
  <xsl:apply-templates select="bar"/> <!-- ... different things should happen in bar -->
</xsl:template>

Любые трюки очень ценятся.

Ответы [ 4 ]

4 голосов
/ 15 апреля 2010

Не совсем ... По крайней мере, в том смысле, что вы пытаетесь это сделать. Переменные в XSLT являются неизменными, когда вы присваиваете им значение, вы не можете их изменить, поэтому попытка вызвать foo несколько раз для изменения значения флага не будет работать. Вы можете попробовать несколько шаблонов, которые могут выполнить то, что вы пытаетесь сделать, например:

<xsl:variable name="myFlag"><xsl:apply-templates select="foo" /></xsl:variable>

<xsl:template match="bla">
      <xsl:apply-templates select="bar" /> <!-- Can use the value of $myFlag --.
</xsl:template>

Что будет работать, если шаблон foo создан для возврата значения флага, однако, если значение флага должно изменяться с течением времени, единственный реальный способ сделать это - включить вызов foo в шаблон бара.

<xsl:template match="bla">
    <xsl:apply-templates select="bar"> />
</xsl:template>

<xsl:template match="bar">
   <xsl:variable name="flag"><xsl:apply-templates name="foo" /></xsl:variable>

   <xsl:if test="$flag=1">

   </xsl:if>
</xsl:template>
1 голос
/ 15 апреля 2010

Есть много способов сделать это. Например:

  • Вы можете использовать условные структуры, такие как xsl: if / xsl: choose.
  • Вы можете использовать переменные для хранения всего, что вычислено из foo, и передачи его в качестве параметра в apply-templates on bar.

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

<xsl:template match="bar[../foo[@a='x']]">
  ...
</xsl:template>
<xsl:template match="bar[../foo[@a='y']]">
  ...
</xsl:template>
0 голосов
/ 15 апреля 2010

Используется подход, который вы упомянули в своем вопросе: передать параметр от foo к bar. ПРИМЕЧАНИЕ. Предполагается, что под каждым bla стоит ровно один foo, иначе шаблон панели будет вызываться никогда или более одного раза для bar элемента.

<xsl:template match="bla">
    <xsl:apply-templates select="foo" />
</xsl:template>

<xsl:template match="foo">
   ...    
   <xsl:apply-templates select="../bar">
     <xsl:with-param name="flag" select="..." />
   </xsl:apply-templates />
</xsl:template>
0 голосов
/ 15 апреля 2010

Если шаблон foo произведет вывод, любое решение, использующее вывод как флаг, не будет работать. В этом случае, если вы используете процессор XSLT на основе Java (например, Saxon или Xalan), вы можете использовать изменяемые объекты Java.

Но учтите, что это имеет свои трудности. Приведенное ниже преобразование использует глобальный флаг, который может быть недостаточным для всех случаев использования. Я хотел бы создать экземпляр флага в шаблоне bla и передать его в качестве параметра foo и bar, но я не смог заставить его работать в Xalan. Также обратите внимание, что я вызываю установщик Java в xsl:value-of, поскольку в противном случае вызов может быть оптимизирован (см. Невозможно получить доступ к обновленному объекту Java из процессора Saxon XSLT ).

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:myflag="java:mypackage.MyFlag">

<xsl:variable name="foo-flag" select="myflag:new()" />

<xsl:template match="bla">
  <xsl:apply-templates select="foo"/> <!-- depending on the contents of foo... -->
  <xsl:apply-templates select="bar"/> <!-- ... different things should happen in bar -->
</xsl:template>

<xsl:template match="foo">
  <xsl:choose>
     <xsl:when ...>
       <xsl:value-of select="myflag:set($foo-flag, true())" />
       ...
     </xsl:when>
     <xsl:otherwise>
       <xsl:value-of select="myflag:set($foo-flag, false())" />
       ...
     </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template match="bar">
  <xsl:choose>
     <xsl:when test="myflag:get($foo-flag)">
       ...
     </xsl:when>
     <xsl:otherwise>
       ...
     </xsl:otherwise>
  </xsl:choose>
</xsl:template>

</xsl:transform>

Класс MyFlag в его основной версии является просто изменяемой логической оболочкой.

public class MyFlag {
private boolean flag;
public void set(boolean flag){
  this.flag = flag;
}
public boolean get(){ return flag; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...