Побитовая логика XSLT - PullRequest
       13

Побитовая логика XSLT

7 голосов
/ 09 июля 2009

У меня есть существующий набор данных, который использует целое число для хранения нескольких значений; Унаследованный интерфейс выполнил простую побитовую проверку (например, в C #: iValues ​​& 16 == 16), чтобы увидеть, было ли установлено определенное значение. Можно ли выполнять побитовые операции в XSL и, более явно, выполнять сравнения на битовом уровне с помощью маскирования? Встроенные «и» всегда приводят к «true» или «false», но, возможно, это возможно с помощью доступных математических операторов?

В настоящее время я использую .NET 2.0, который использует XSLT 1.0.

Ответы [ 4 ]

14 голосов
/ 10 июля 2009

XSLT равен завершено по Тьюрингу , см., Например, здесь или здесь , поэтому это можно сделать Но я использовал XSLT только один или два раза и не могу дать никакого решения.

UPDATE

Я просто снова прочитал учебник и нашел решение, используя следующий факт. bitset(x, n) возвращает true, если установлен n -й бит x, в противном случае - false.

bitset(x, n) := floor(x / 2^n) mod 2 == 1

Следующий XSLT

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/">
    <html>
      <body>
        <table border="1" style="text-align:center;">
          <tr bgcolor="#9acd32">
            <th>Number</th>
            <th>Bit 3</th>
            <th>Bit 2</th>
            <th>Bit 1</th>
            <th>Bit 0</th>
          </tr>
          <xsl:for-each select="numbers/number">
            <tr>
              <td>
                <xsl:value-of select="."/>
              </td>
              <td>
                <xsl:choose>
                  <xsl:when test="floor(. div 8) mod 2 = 1">1</xsl:when>
                  <xsl:otherwise>0</xsl:otherwise>
                </xsl:choose>
              </td>
              <td>
                <xsl:choose>
                  <xsl:when test="floor(. div 4) mod 2 = 1">1</xsl:when>
                  <xsl:otherwise>0</xsl:otherwise>
                </xsl:choose>
              </td>
              <td>
                <xsl:choose>
                  <xsl:when test="floor(. div 2) mod 2 = 1">1</xsl:when>
                  <xsl:otherwise>0</xsl:otherwise>
                </xsl:choose>
              </td>
              <td>
                <xsl:choose>
                  <xsl:when test="floor(. div 1) mod 2 = 1">1</xsl:when>
                  <xsl:otherwise>0</xsl:otherwise>
                </xsl:choose>
              </td>
            </tr>
          </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

превратит этот XML

<?xml version="1.0" encoding="ISO-8859-1"?>
<numbers>
  <number>0</number>
  <number>1</number>
  <number>2</number>
  <number>3</number>
  <number>4</number>
  <number>5</number>
  <number>6</number>
  <number>7</number>
  <number>8</number>
  <number>9</number>
  <number>10</number>
  <number>11</number>
  <number>12</number>
  <number>13</number>
  <number>14</number>
  <number>15</number>
</numbers>

в HTML-документ с таблицей, показывающей биты чисел.

Number | Bit 3 | Bit 2 | Bit 1 | Bit 0 
---------------------------------------
   0   |   0   |   0   |   0   |   0 
   1   |   0   |   0   |   0   |   1 
   2   |   0   |   0   |   1   |   0 
   3   |   0   |   0   |   1   |   1 
   4   |   0   |   1   |   0   |   0 
   5   |   0   |   1   |   0   |   1 
   6   |   0   |   1   |   1   |   0 
   7   |   0   |   1   |   1   |   1 
   8   |   1   |   0   |   0   |   0 
   9   |   1   |   0   |   0   |   1 
  10   |   1   |   0   |   1   |   0 
  11   |   1   |   0   |   1   |   1 
  12   |   1   |   1   |   0   |   0 
  13   |   1   |   1   |   0   |   1 
  14   |   1   |   1   |   1   |   0 
  15   |   1   |   1   |   1   |   1 

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

3 голосов
/ 10 июля 2009

XSLT не определяет побитовые операции. Если вы хотите их, вы должны свернуть свои собственные.

Если вы используете XSLT специально для контекста .NET 2.0, то есть класса * 1003, то самое простое решение - использовать блок сценариев для введения функции C #, которая это делает, а затем просто вызвать это:

<xsl:stylesheet xmlns:bitwise="urn:bitwise">

  <msxsl:script language="CSharp" implements-prefix="bitwise">
  <![CDATA[
    public int and(int x, int y) { return x & y; }
    public int or(int x, int y) { return x | y; }
    ...
  ]]>
  </msxsl:script>

  ...

  <xsl:value-of select="bitwise:and(@foo, @bar)" />
  <xsl:value-of select="bitwise:or(@foo, @bar)" />
  ...

</xsl:stylesheet>

Или вы можете определить более высокоуровневые примитивы в блоке сценариев, такие как HasFlag, а затем использовать их.

При загрузке такой таблицы стилей вам необходимо явно включить в ней скрипты:

XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load("foo.xsl",
  new XsltSettings { EnableScript = true },
  new XmlUrlResolver());
3 голосов
/ 10 июля 2009

Я не видел ничего подобного в XSLT / XPath. Но я нашел кто-то, выполняющий этот вид операций вручную . Может быть, вы могли бы использовать тот же подход, если вам действительно нужно.

1 голос
/ 24 февраля 2011
<xsl:value-of select="for $n in (128, 64, 32, 16, 8, 4, 2, 1) return if ((floor($var div $n) mod 2) = 1) then 1 else 0"/>

это вернет двоичный массив вашей переменной (хранится в $ var)

кстати, я использовал XPath 2.0, чтобы сделать это

...