XSLT Bitwise Logic

前端 未结 4 1722
失恋的感觉
失恋的感觉 2020-12-03 15:45

I have an existing data set that utilizes an integer to store multiple values; the legacy front end did a simple bitwise check (e.g. in C#: iValues & 16 == 16) to see if

相关标签:
4条回答
  • 2020-12-03 16:34

    I haven't seen anything like this in XSLT / XPath. But I've found someone implementing this kind of operations manually. Maybe you could use the same approach, if you really need to.

    0 讨论(0)
  • 2020-12-03 16:36

    XSLT does not define bitwise operations. If you want them, you have to roll your own.

    If you're using XSLT specifically in .NET 2.0 context - that is, XslCompiledTransform class - then the simplest solution is to use a scripting block to introduce a C# function that does it, and then just call that:

    <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>
    

    Or you can define the more high-level primitives in a scripting block, such as HasFlag, and then use those.

    When loading such a stylesheet, you will need to explicitly enable scripting in it:

    XslCompiledTransform xslt = new XslCompiledTransform();
    xslt.Load("foo.xsl",
      new XsltSettings { EnableScript = true },
      new XmlUrlResolver());
    
    0 讨论(0)
  • 2020-12-03 16:41
    <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"/>
    

    this will return the binary array of your variable (stored in $var)

    by the way I used XPath 2.0 to do this

    0 讨论(0)
  • 2020-12-03 16:42

    XSLT is Turing-complete, see for example here or here, hence it can be done. But I have used XSLT only one or two times and can give no solution.

    UPDATE

    I just read a tutorial again and found a solution using the following fact. bitset(x, n) returns true, if the n-th bit of x is set, false otherwise.

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

    The following 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>
    

    will turn this 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>
    

    into a HTML document with a table showing the bits of the numbers.

    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 
    

    This is neither elegant nor nice in any way and there are probably much simpler solution, but it works. And given that it is my first contact with XSLT, I am quite satisfied.

    0 讨论(0)
提交回复
热议问题