Two corrections:
a) Use correct prefix for XPath integer()
function
b) Can't use dfdl:outputValueCalc (or
any other property) with dfdl:inputValueCalc
Regards
Steve Hanson
Strategy, Common Transformation & DFDL
Co-Chair, OGF DFDL WG
IBM SWG, Hursley, UK,
smh@uk.ibm.com,
tel +44-(0)1962-815848
----- Forwarded by Steve
Hanson/UK/IBM on 20/09/2010 17:29 -----
From:
| Alan Powell/UK/IBM
|
To:
| Steve Hanson/UK/IBM@IBMGB
|
Date:
| 20/09/2010 15:57
|
Subject:
| Re: Fw: DFDL functions testOn/Off and
setOn/Off - action 107 |
Steve
The spec doesn't allow inputValueCalc
and outputValueCalc on the same element.
|
Regards
|
|
Alan Powell
|
|
Development - MQSeries, Message Broker,
ESB
|
IBM Software Group, Application and
Integration Middleware Software
|
-------------------------------------------------------------------------------------------------------------------------------------------
|
IBM
|
MP211, Hursley Park
|
Hursley, SO21 2JN
|
United Kingdom
|
Phone: +44-1962-815073
|
e-mail: alan_powell@uk.ibm.com |
----- Forwarded by Steve
Hanson/UK/IBM on 20/09/2010 11:19 -----
From:
| Steve Hanson/UK/IBM
|
To:
| dfdl-wg@ogf.org
|
Date:
| 20/09/2010 11:18
|
Subject:
| DFDL functions testOn/Off and setOn/Off
- action 107 |
The expression language section of the
spec (21.5.3). defines some functions that make it easier to test/set individual
bits in a byte.
Action 107 was raised to question whether
they were needed and if so to complete the definitions. In particular the
spec for setOn/setOff seems odd.
Here's an example of where they are
useful, although upon investigation the functions need changing a bit.
A financial standard exists called ISO8583.
It is widely used with debit/credit card transactions. An ISO8583 data
stream consists of 128 optional fixed length fields with no tags or delimiters,
preceded by a mandatory bitmap that indicates the presence of all the other
fields.
In DFDL a nice approach is to model
each optional field as having dfdl:occursCountKind="expression"
with dfdl:occursCount referencing the corresponding bit in the bitmap and
casting its value to an integer to give 0 or 1. Each bit in the bitmap
would have its output value set using dfdl:outputValueCalc, true if the
corresponding field existed in the infoset.
The representation of the bitmap is
the interesting part. It can either be packed or unpacked.
Packed
In packed format the bitmap is a real
array of bits (8 bytes worth) which must be modelled as individual booleans
(ie, not an array) because each needs to carry a distinct dfdl:outputValueCalc
expression, as shown below. For example:
<complexType name="ISO8583_Packed">
<sequence>
<element name="BitMap">
<complexType>
<sequence>
<!-- each bit in the bitmap modelled individually
-->
<element name="Bit001" type="boolean"
dfdl:representation="binary"
dfdl:binaryBooleanTrueRep="1" dfdl:binaryBooleanFalseRep="0"
dfdl:lengthKind="explicit"
dfdl:length="1" dfdl:lengthUnits="bits"
dfdl:outputValueCalc="{if
fn:exists(../Field001) then true else false}"
/>
...
<element name="Bit064" type="boolean"
dfdl:representation="binary"
dfdl:binaryBooleanTrueRep="1" dfdl:binaryBooleanFalseRep="0"
dfdl:lengthKind="explicit"
dfdl:length="1" dfdl:lengthUnits="bits"
dfdl:outputValueCalc="{if
fn:exists(../Field064) then true else false}"
/>
</sequence>
</complexType>
</element>
<!-- each field
below determines its optional occurrence based on a bit in the bitmap field
-->
<element name="Field001"
type="string" minOccurs="0"
dfdl:occursKind="expression" dfdl:occurs="{xs:integer(../BitMap/Bit001)}"
/>
...
<element name="Field064"
type="string" minOccurs="0"
dfdl:occursKind="expression" dfdl:occurs="{xs:integer(../BitMap/Bit064)}"
/>
</sequence>
</complexType>
Unpacked
However, in the unpacked format the
value of each nibble of the bitmap is taken and unpacked as text (ASCII
or EBCDIC). Eg, bitmap '0000000100100011010001010110011110001001101010111100110111101111'
(64 bits) = x01x23x45x67x89xABxCDxEF (8 bytes) = x30x31x32x33x34x35x36x37x38x39x41x42x43x44x45x46
(16 bytes) in ASCII. This can be modelled as an unsigned long with
representation as a base 16 standard text number.
The problem is then how to test and
set the individual bits in the unsigned long. That's where the DFDL functions
come in useful, because there are no XPath functions for bitwise operations.
If the functions are defined as follows:
xs:boolean dfdl:testBit(xs:unsignedLong,
xs:unsignedShort)
Returns Boolean true if the bit number given by arg #2 is set on
in the integer given by arg #1, otherwise returns Boolean false.
xs:unsignedLong dfdl:setBits(xs:boolean+)
Returns an integer being the value of the bit positions provided
by the Boolean arguments, where true=1, false=0. The # of args must be
a multiple of 8.
Note that the bit numbering
goes from left to right, in accordance with section 12.3.7.2 of the spec.
Applying this to the example above gives:
<complexType name="ISO8583_Unpacked">
<sequence>
<element name="BitMapInt"
type="unsignedLong"
dfdl:representation="text" dfdl:textNumberRep="standard"
dfdl:textNumberBase="16" dfdl:encoding="ascii"
dfdl:lengthKind="explicit" dfdl:length="16"
dfdl:lengthUnits="characters"
dfdl:outputValueCalc="{dfdl:setBits(fn:exists(../Field001),
...
fn:exists(../Field064)}"
/>
<!-- each field
below determines its optional occurrence based on a bit in the bitmap field
-->
<element name="Field001"
type="string" minOccurs="0"
dfdl:occursKind="expression" dfdl:occurs="{xs:integer(dfdl:testBit(../BitMapInt,
1)}" />
...
<element name="Field064"
type="string" minOccurs="0"
dfdl:occursKind="expression" dfdl:occurs="{xs:integer(dfdl:testBit(../BitMapInt,
64)}" />
</sequence>
</complexType>
To keep the unpacked model as close
to the packed model as possible, we can incorporate the logical BitMap
from the packed model and hide BitMapInt. This means the Fieldxxx
elements are the same for each.
<complexType name="ISO8583_Unpacked">
<sequence>
<sequence dfdl:hiddenGroupRef="HiddenBitMap"
/>
<element name="BitMap">
<complexType>
<sequence>
<!-- each bit in the bitmap modelled individually
but derived -->
<element name="Bit001" type="boolean"
dfdl:inputValueCalc="{dfdl:testBit(../BitMapInt,
1)}" />
...
<element name="Bit064" type="boolean"
dfdl:inputValueCalc="{dfdl:testBit(../BitMapInt,
64)}" />
</sequence>
</complexType>
</element>
<!-- each field
below determines its optional occurrence based on a bit in the bitmap field
-->
<element name="Field001"
type="string" minOccurs="0"
dfdl:occursKind="expression" dfdl:occurs="{xs:integer(../BitMap/Bit001)}"
/>
...
<element name="Field064"
type="string" minOccurs="0"
dfdl:occursKind="expression" dfdl:occurs="{xs:integer(../BitMap/Bit064)}"
/>
</sequence>
</complexType>
<group name="HiddenBitMap">
<sequence>
<element name="BitMapInt"
type="unsignedLong"
dfdl:representation="text" dfdl:textNumberRep="standard"
dfdl:textNumberBase="16" dfdl:encoding="ascii"
dfdl:lengthKind="explicit" dfdl:length="16"
dfdl:lengthUnits="characters"
dfdl:outputValueCalc="{dfdl:setBits(fn:exists(../Field001),
...
fn:exists(../Field064)}"
/>
</sequence>
</group>
For both packed and unpacked, the BitMap
element could be hidden as well, as there is no need for it in the infoset.
Regards
Steve Hanson
Strategy, Common Transformation & DFDL
Co-Chair, OGF DFDL WG
IBM SWG, Hursley, UK,
smh@uk.ibm.com,
tel +44-(0)1962-815848
Unless stated otherwise above:
IBM United Kingdom Limited - Registered in England and Wales with number
741598.
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6
3AU
Unless stated otherwise above:
IBM United Kingdom Limited - Registered in England and Wales with number
741598.
Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6
3AU