【问题标题】:XSLT Bitwise LogicXSLT 位逻辑
【发布时间】:2010-11-09 12:20:32
【问题描述】:

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

我目前使用的是 .NET 2.0,它使用 XSLT 1.0。

【问题讨论】:

    标签: xslt logic bit-manipulation


    【解决方案1】:

    XSLT 是Turing-complete,例如参见herehere,因此可以这样做。但是我只用过一两次XSLT,无法给出解决方案。

    更新

    我刚刚再次阅读教程并使用以下事实找到了解决方案。 bitset(x, n) 如果设置了xn-th 位,则返回true,否则返回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,我很满意。

    【讨论】:

    • 图灵完备如何确定位运算符是否存在?
    • 如果它是图灵完备的,它可以计算每个函数,因此可以对整数进行按位运算。
    • 嗯...我不明白。我熟悉图灵完备的概念,但我仍然可以想象一种图灵完备且没有按位运算符的语言,即无法将数字拆分为更小的块。
    • 不需要按位运算 - 您可以模拟它们。取一些变量(可能是 32 个),将它们初始化为零,然后将它们视为一个数组。取另一个包含输入值的变量 X。查看最右边的变量。是零吗?将其设置为一个。是一个吗?从右到左遍历数组并将所有 1 设置为零,直到找到第一个零。将此设置为一个。现在从 X 中减去 1 并交互所有内容,直到 X 为零。当你达到零时,数组将包含 X 的二进制表示。
    • 全部完成,将变量设置为两个任意符号“零”和“一”,将变量与符号进行比较,从变量中减去 1,进行一点分支,以及一种间接访问.这仍然远远超过所需 - 例如,您可以用更少的东西解决这个问题,例如,您不需要减法。这就是图灵完备性的意义所在——你可以在每个图灵完备系统上做完全相同的事情。
    【解决方案2】:

    我还没有在 XSLT / XPath 中看到过类似的东西。但我找到了someone implementing this kind of operations manually。如果你真的需要,也许你可以使用相同的方法。

    【讨论】:

    • 不错的发现;只需更改命名模板以接受数字作为参数,它就像任何任意值的冠军。
    【解决方案3】:

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

    如果您专门在 .NET 2.0 上下文中使用 XSLT(即XslCompiledTransform 类),那么最简单的解决方案是使用脚本块来引入执行此操作的 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());
    

    【讨论】:

      【解决方案4】:
      <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 来做到这一点

      【讨论】:

      • 谢谢,但不适用于 .NET 框架(根据原始问题,遗憾的是 .NET 4.0 仍然是这种情况)。仅当您使用支持 XPath 2.0 的 3rd 方库时,您的解决方案才有效。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-09
      • 1970-01-01
      • 2011-10-30
      • 2011-04-11
      • 2012-08-10
      • 1970-01-01
      • 2023-01-09
      相关资源
      最近更新 更多