XSLT 1.0 идиома для троичного, если? - PullRequest
8 голосов
/ 12 января 2012

Эта Java-программа использует Ternary if для отображения логических значений в выходные строки: ("*" для true, пустая строка для false).

public class ternary {
  public static void main(String[] args) {
    boolean flags[]={true,false,true};
    for (boolean f : flags) {
      System.out.println(f?"*":"");
    }
  }
}

То есть вывод *, [пусто], *.

У меня есть входной XML-документ, что-то вроде:

<?xml version="1.0" ?>
<?xml-stylesheet type="text/xsl" href="change.xsl"?>
<root>
  <change flag="true"/>
  <change flag="false"/>
  <change flag="true"/>
</root>

И у меня есть следующий шаблон XSLT, который отображает true на '*' и false на '(это работает):

<xsl:template match="change">
  <xsl:variable name="flag" select="translate(substring(@flag,1,1),'tf','*')"/>
  <xsl:value-of select="$flag"/>
</xsl:template>

Есть ли более краткая версия этого?

a) Могу ли я автоматически получить значение логического true | false непосредственно из строки 'true | false'? б) Существует ли (xpath?) конструкция для сопоставления логического true | false с '*', ''?

Ответы [ 2 ]

8 голосов
/ 12 января 2012

a) Могу ли я автоматически получить значение логического true | false непосредственно из строки 'true | false'?

b) Существует ли конструкция (xpath?) Для сопоставления логического true | false с '*', ''?

Это на самом деле вопрос XPath .

I.XPath 1.0

Существует несколько выражений XPath, вычисление которых дает желаемый результат:

substring('*', 2 -(@flag = 'true'))

Это также отвечает б) - обратите внимание, что строки 'true' и 'false' не являются логическими значениями!Единственными двумя логическими значениями являются true() и false(), и они не являются строками.

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

number(true()) равно 1

и

number(false()) равно 0

Таким образом, второй аргумент вызоваsubstring() выше:

2 - (@flag = 'true')

оценивается как 1 при @flag = 'true' и 2 в противном случае.

Более общее выражение XPath 1.0, которое создает строку$s1, если $val равно "x" и генерирует строку $s2, если $val равно "y":

concat(substring($s1, 1 div ($val = "x")),
       substring($s2, 1 div ($val = "y"))
      )

Это приводит к строке $s1 при $val = "x", строка $s2, когда $val = "y", и пустая строка - если не выполняется ни одно из этих двух условий.

Вышеприведенное выражение XPath 1.0 можно обобщить, чтобы получить N различных результатов строки $s1, $2, ..., $sN точно, когда $val является одним из значений $v1, $v2, ..., $vN, потому что функция concat() может иметь любое количество аргументов.


II.XPath 2.0 (XSLT 2.0)

'*'[current()/@flag = 'true']

И в более общем смысле, учитывая 2 * N атомных значений $s1, $s2, ... $sN и $v1, $v2, ..., $vN, так что все значения $vi различны, результат вычисления выражения XPath 2.0:

 ($s1, $s2, ..., $sN)[index-of(($v1, $v2, ..., $vN), $v)]

равен $sK точно, когда $v eq $vK.

1 голос
/ 12 января 2012

Для этого вы можете использовать простое сопоставление с образцом в шаблонах.

<xsl:template match="change[@flag = 'true']">

<xsl:template match="change">

Итак, первый соответствует true записям, а другой соответствует всем другим случаям (которые в вашемСлучаи просто false

Итак, учитывая следующую таблицу стилей

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="text" indent="yes"/>

   <xsl:template match="change[@flag = 'true']">
      <xsl:text>*&#13;</xsl:text>
   </xsl:template>

   <xsl:template match="change">
      <xsl:text>&#13;</xsl:text>
   </xsl:template>

   <xsl:template match="@*|node()">
      <xsl:apply-templates select="@*|node()"/>
   </xsl:template>
</xsl:stylesheet>

При применении к вашему примеру XML, выводится следующее

*

*
...