2009-07-09 10 views
7

Tengo un conjunto de datos existente que utiliza un número entero para almacenar valores múltiples; el front-end heredado hizo una simple comprobación bit a bit (por ejemplo, en C#: iValues ​​& 16 == 16) para ver si se había establecido un valor en particular. ¿Es posible realizar operaciones a nivel de bit en XSL y, más explícitamente, hacer comparaciones de nivel de bits mediante enmascaramiento? El "y" incorporado siempre dará como resultado "verdadero" o "falso", pero tal vez sea posible a través de los operadores matemáticos disponibles.XSLT Bitwise Logic

Actualmente estoy usando .NET 2.0, que usa XSLT 1.0.

Respuesta

3

No he visto nada como esto en XSLT/XPath. Pero he encontrado someone implementing this kind of operations manually. Tal vez podrías usar el mismo enfoque, si realmente lo necesitas.

+0

Buen hallazgo; solo tuve que cambiar la plantilla nombrada para aceptar el número como parámetro y funcionó como un campeón para cualquier valor arbitrario. – pdwetz

13

XSLT es Turing-complete, ver por ejemplo here o here, por lo tanto, se puede hacer. Pero he usado XSLT solo una o dos veces y no puedo dar ninguna solución.

ACTUALIZACIÓN

acabo de leer un tutorial de nuevo y encontrado una solución mediante el siguiente hecho. bitset(x, n) devuelve verdadero, si el n -ésimo bit de x está configurado, falso en caso contrario.

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

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

se convertirán este 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> 

en un documento HTML con una tabla que muestra los bits de los números.

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 

Esto no es ni elegante ni agradable de ninguna manera y es probable que haya una solución mucho más simple, pero funciona. Y dado que es mi primer contacto con XSLT, estoy bastante satisfecho.

+2

¿Cómo puede ser Turing-completo dar la respuesta si existen operadores bit a bit? –

+2

Si es Turing-complete, puede calcular todas las funciones, por lo tanto, operaciones bit a bit en enteros. –

+0

Hmm ...No lo entiendo Estoy familiarizado con la noción de Turing-completitud, pero todavía puedo imaginar un lenguaje que es completo y no tiene operadores de bits, es decir, no hay forma de dividir los números en trozos más pequeños. –

3

XSLT no define operaciones bit a bit. Si los quieres, tienes que hacer los tuyos.

Si está utilizando XSLT específicamente en .NET 2.0 contexto - es decir, XslCompiledTransform clase - a continuación, la solución más sencilla es utilizar un bloque de secuencias de comandos para introducir una función de C# que lo hace, y luego simplemente llamada que:

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

O puede definir las primitivas de más alto nivel en un bloque de scripts, como HasFlag, y luego usarlas.

Al cargar una hoja de estilo tal, tendrá que habilitar explícitamente secuencias de comandos en ella:

XslCompiledTransform xslt = new XslCompiledTransform(); 
xslt.Load("foo.xsl", 
    new XsltSettings { EnableScript = true }, 
    new XmlUrlResolver()); 
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"/> 

esto va a devolver la matriz binaria de la variable (almacenado en $ var)

por la forma en que utilicé XPath 2.0 para hacer esto

+2

Gracias, pero no aplicable a .NET Framework (según la pregunta original, que lamentablemente sigue siendo el caso de .NET 4.0). Su solución solo funciona si está utilizando una biblioteca de terceros con soporte para XPath 2.0. – pdwetz