8

我有一个现有的数据集,它利用整数来存储多个值;旧版前端进行了简单的按位检查(例如在 C# 中:iValues & 16 == 16)以查看是否设置了特定值。是否可以在 XSL 中进行按位运算,更明确地说,可以通过掩码进行位级比较?内置的“and”总是会导致“true”或“false”,但也许可以通过可用的数学运算符来实现?

我目前正在使用 .NET 2.0,它使用 XSLT 1.0。

4

4 回答 4

14

XSLT 是图灵完备的,例如参见此处此处,因此可以完成。但我只使用过一两次 XSLT,无法给出解决方案。

更新

我刚刚再次阅读了一个教程,并使用以下事实找到了解决方案。如果设置了-th 位,bitset(x, n)则返回 true,否则返回false。nx

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,我很满意。

于 2009-07-09T20:05:55.687 回答
3

我还没有在 XSLT/XPath 中看到过这样的东西。但我发现有人手动执行这种操作。如果您真的需要,也许您可​​以使用相同的方法。

于 2009-07-09T21:17:36.150 回答
3

XSLT 没有定义按位运算。如果你想要它们,你必须自己动手。

如果您专门在 .NET 2.0 上下文(即XslCompiledTransform类)中使用 XSLT,那么最简单的解决方案是使用脚本块来引入执行此操作的 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());
于 2009-07-09T21:42:11.483 回答
1
<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 来做到这一点

于 2011-02-24T12:30:34.363 回答