Couple of things.

So you are headed down a problematic path here.


DFDL is a format description language, not a data transformation system.


So if you start out saying "this is what I want the XML to look like", you are 
headed in a way that may be unsatisfying.


Rather you have to approach it from "What IS the data format?".


See really you have two problems here:

(1) what is the data format?

(2) what do I want to transform that into?


DFDL is really only about problem (1) here.


To DFDL, the output XML is just one serialization format for the DFDL infoset. 
You could also output JSON, or just consume the infoset events, and not create 
a serialization at all.


Now, all that said, as you have noticed using 
dfdl:inputValueCalc/outputValueCalc, you have some interesting transformation 
capabilities you can slide in there.


What you have to embrace here is that your "simple" hexBinary pointer here, 
because you want to transform it, requires a "complex" representation. This 
will allow you to reuse your type, but you are going to have something like:


<startAddress><pointer>40 00 00 00</pointer></startAddress>


The extra 'pointer' element is an artifact of needing a complex type to carry 
the complexity of this.


The way you get a reusable group to do your transform is then like so:


<element name="startAddress" type="tns:pointerType"/>


<complexType name="pointerType">

      <sequence>

        <sequence dfdl:hiddenGroupRef="tns:rawPointer"/>

        <element name="pointer" type="xs:string"

            dfdl:inputValueCalc='{

               fn:concat(  xs:string(../Hidden_byte4),
                xs:string(../Hidden_byte3),
                xs:string(../Hidden_byte2),
                xs:string(../Hidden_byte1)) }' />

       </sequence>

</complexType>


I've left out the details of the rawPointer group, but they're like your 
hidden_hexBinary4_Group.


The above is what I'd call the "reusable transformation pattern" for DFDL.


You inevitably get an extra tier of element here. Instead of <startAddress>40 
00 00 00</startAddress> you are going to get <startAddress><pointer>40 00 00 
00</pointer></startAddress>, but this is an artifact of the inability of XSD 
(which DFDL extends/subsets) to express complex structure in the representation 
of a simple type. We have no way in XSD to have a simple type with a complex 
representation that involves child elements.

________________________________
From: Costello, Roger L. <[email protected]>
Sent: Thursday, January 10, 2019 4:25:46 AM
To: [email protected]
Subject: How to have the input bytes reversed in the XML output?

Hello DFDL community,

My input file is binary and in little endian order.

Some fields in the input file represent addresses/pointers. For example:

        00 00 00 40

I've decided that the XML should show the hex digits, so I do this:

<xs:element      name="Address_of_relocation_table"
                 type="xs:hexBinary"
                 dfdl:length="4"
                 dfdl:lengthKind="explicit"
                 dfdl:lengthUnits="bytes" />

However, that results in this XML output:

<Address_of_relocation_table>00000040</Address_of_relocation_table>

I'm sure the person who views that XML will not realize that the hex digits are 
shown in little endian form. I really want the XML output to show the hex 
digits as we humans ordinarily view numbers: from most significant digit to 
least significant digit. So, I want the XML output to be this:

<Address_of_relocation_table>40000000</Address_of_relocation_table>

In other words, I want to reverse the input's bytes.

I figured out one way to accomplish this reversal. In a hidden group, have 4 
elements, one for each byte:

<xs:group name="hidden_hexBinary4_Group">
    <xs:sequence>
        <xs:element name="Hidden_byte1" type="hexBinary1" 
dfdl:outputValueCalc='{ . }' />
        <xs:element name="Hidden_byte2" type="hexBinary1" 
dfdl:outputValueCalc='{ . }' />
        <xs:element name="Hidden_byte3" type="hexBinary1" 
dfdl:outputValueCalc='{ . }' />
        <xs:element name="Hidden_byte4" type="hexBinary1" 
dfdl:outputValueCalc='{ . }' />
    </xs:sequence>
</xs:group>

where hexBinary1 is this simpleType:

<xs:simpleType name="hexBinary1" dfdl:length="1" dfdl:lengthKind="explicit" 
dfdl:lengthUnits="bytes">
    <xs:restriction base="xs:hexBinary"/>
</xs:simpleType>

Then, when I declare the Address_of_relocation_table element, I reverse the 4 
elements and concatenate their values:

<xs:sequence dfdl:hiddenGroupRef="hidden_hexBinary4_Group" />
<xs:element name="Address_of_relocation_table" type="xs:string" 
dfdl:inputValueCalc='{
    fn:concat(  xs:string(../Hidden_byte4),
                xs:string(../Hidden_byte3),
                xs:string(../Hidden_byte2),
                xs:string(../Hidden_byte1))}'/>

That works, but for the next address/pointer I have to create another hidden 
group. Ugh! I've got dozens of these hidden groups containing four 1-byte 
elements. There has to be a better way!

Is there a better way to reverse the input bytes?

/Roger

Reply via email to