0

I have the following code that contains 3 variables which values depend on an xml.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" 
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:xs="http://www.w3.org/2001/XMLSchema"
            xmlns:date="java.util.Date"                
            xmlns:vector="java.util.Vector"                
            xmlns:math="java.lang.Math"
            xmlns:int="java.lang.Integer"
            xmlns:saxon="http://saxon.sf.net/"
            extension-element-prefixes="date vector math int saxon">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:variable name="var1">
    code to generate the value
</xsl:variable>
<xsl:variable name="var2">
    code to generate the value
</xsl:variable>
<xsl:variable name="var3">
    code to generate the value
</xsl:variable>

The problem is that I have to combine this values for another variable:

<xsl:variable name="var4">
    value = var1 | var2 | var3
</xsl:variable>

Is there an elegant way of doing this? I have already looked at this answer but I did not find it useful.

The only solution that comes to my mind is

  1. Transform the numbers into strings containing their binary representation
  2. Take 2 strings and compare each letter and hold the result
  3. Take the result and compare it with the last string
  4. Transform the binary representation back to integer
Community
  • 1
  • 1
Alexandru Cimpanu
  • 1,029
  • 2
  • 14
  • 38
  • What kind of values do your variables hold? Which version of Saxon do you use? Have you checked whether you can make use of a Java extension function to perform the bitwise operation on numbers? – Martin Honnen Oct 24 '14 at 09:08
  • The variables hold 8bit values, I don't know where to check the Saxon version and I don't know how to use a Java extension function. – Alexandru Cimpanu Oct 24 '14 at 10:09
  • Can you show us the code that defines a variable value? Or at least tell us which type the variable has in the XSLT/XPath type system. As for checking the Saxon version, if you run Saxon from the command line then use the `-t` option, it will output details like `Saxon-PE 9.6.0.1J from Saxonica`. – Martin Honnen Oct 24 '14 at 10:18
  • it looks like this `` I had documented a bit more and I was wandering if I could use Java.math.BigInteger – Alexandru Cimpanu Oct 24 '14 at 11:13

3 Answers3

4

Here's a XSLT 1.0 implementation of bitwise OR on decimal parameters, using a recursive template:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:variable name="n" select="49" />
<xsl:variable name="m" select="50" />

<xsl:template match="/">
    <output>
        <xsl:call-template name="bitwise-or">
            <xsl:with-param name="n" select="$n"/>
            <xsl:with-param name="m" select="$m"/>
        </xsl:call-template>
    </output>
</xsl:template>

<xsl:template name="bitwise-or">
    <xsl:param name="n"/>
    <xsl:param name="m"/>
    <xsl:param name="power" select="1"/>
    <xsl:param name="value" select="0"/>

    <xsl:variable name="bit" select="$n mod 2 or $m mod 2"/>
    <xsl:variable name="nextN" select="floor($n div 2)"/>
    <xsl:variable name="nextM" select="floor($m div 2)"/>
    <xsl:variable name="result" select="$value  + $bit * $power"/>

    <xsl:choose>
        <xsl:when test="$nextN or $nextM">
            <xsl:call-template name="bitwise-or">
                <xsl:with-param name="n" select="$nextN"/>
                <xsl:with-param name="m" select="$nextM"/>
                <xsl:with-param name="power" select="2 * $power"/>
                <xsl:with-param name="value" select="$result"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$result" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

The result of the given example:

<?xml version="1.0" encoding="UTF-8"?>
<output>51</output>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
2

If you use a commercial edition of Saxon 9 then you can call into Java and use the BigInteger class. Here is an example meant to be used with Saxon 9.6 PE or EE making use of that class and of XSLT 3.0 to implement bitwise or and and for two xs:integer values and for sequences of xs:integer values:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:math="http://www.w3.org/2005/xpath-functions/math"
  xmlns:bigint="java:java.math.BigInteger"
  xmlns:mf="http://example.com/mf"
  exclude-result-prefixes="xs math bigint mf"
  version="3.0">

<xsl:param name="integer-seq1" as="xs:integer*" select="1, 2, 4, 16"/>

<xsl:function name="mf:or" as="xs:integer">
  <xsl:param name="i1" as="xs:integer"/>
  <xsl:param name="i2" as="xs:integer"/>
  <xsl:sequence select="bigint:or(bigint:new(string($i1)), bigint:new(string($i2)))"/>
</xsl:function>

<xsl:function name="mf:or" as="xs:integer">
  <xsl:param name="integers" as="xs:integer+"/>
  <xsl:sequence select="fold-left(
                          $integers[position() gt 1],
                          $integers[1],
                          mf:or#2
                        )"/>
</xsl:function>

<xsl:function name="mf:and" as="xs:integer">
  <xsl:param name="i1" as="xs:integer"/>
  <xsl:param name="i2" as="xs:integer"/>
  <xsl:sequence select="bigint:and(bigint:new(string($i1)), bigint:new(string($i2)))"/>
</xsl:function>

<xsl:function name="mf:and" as="xs:integer">
  <xsl:param name="integers" as="xs:integer+"/>
  <xsl:sequence select="fold-left(
                          $integers[position() gt 1],
                          $integers[1],
                          mf:and#2
                        )"/>
</xsl:function>


<xsl:template name="main">
  <xsl:value-of select="mf:or(1, 16), mf:and(1, 16), mf:or($integer-seq1), mf:and($integer-seq1), '&#10;'"/>
</xsl:template>

</xsl:stylesheet>

With earlier versions of Saxon you can't use the fold-left based solution for sequences but the two argument versions should work. As math:pow returns an xs:double, you would need to cast to an integer first before trying to use the functions.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
0

Saxon 9.6 (PE or higher) implements the EXPath Binary module

http://expath.org/spec/binary

This provides operations such as bin:or, bin:and, bin:xor on Base64Binary values, as well as operations such as bin:pack-integer which converts an integer to a Base64Binary value.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164