DFDL customizations

You can customize DFDL; for example, by selecting a different namespace, changing the element names, or changing the string data types. Several customizations are described in the following sections.

targetNamespace

The targetNamespace of generated files is in one of the following formats:


http://www.ibm.com/xmlns/prod/ztpf/dfdl/gen/filename
http://www.ibm.com/xmlns/prod/ztpf/dfdl/tpfdf/filename

This namespace is specific to the z/TPF system. The z/TPF convention for this namespace is to match the targetNamespace to the file name. Because the data definitions that are defined in the generated files are not owned by IBM®, it is a good practice to use a namespace that conforms to your company standards.

When you change the targetNamespace, you must update any XML namespace prefix declaration that refers to the namespace. The following sample highlights the targetNamespace and XML namespace prefix declaration.
<xs:schema targetNamespace="http://www.ibm.com/xmlns/prod/ztpf/dfdl/gen/sample"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:ns0="http://www.ibm.com/xmlns/prod/ztpf/dfdl/gen/sample"
      xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
      xmlns:tddt="http://www.ibm.com/xmlns/prod/ztpf/xml/lib/tpfattributes"
      xmlns:tpfbase="http://www.ibm.com/xmlns/prod/ztpf/dfdl/lib/tpfbase">

Element names

The names that are used in DFDL do not need to match the C/C++ language structure or basic assembler language (BAL) DSECT names. The names are used only for external representation in JSON, XML, BSON, CSV, and so on. Therefore, the DFDL element names should reflect how the data is known to your enterprise system. The following sample highlights the element name attribute in the DFDL element definition.
<xs:element name="Address" type="xs:string" dfdl:lengthKind="explicit"
        dfdl:length="30" dfdl:lengthUnits="bytes" nillable="true"
        dfdl:useNilForDefault="yes" dfdl:nilKind="literalCharacter"
        dfdl:useNilValue="%NUL;" />

Data type representation

When DFDL is generated from C/C++ language structures or BAL DSECT names, some data types might not accurately reflect how the field is used. The following sample highlights the element type attribute in the DFDL element definition.
<xs:element name="Address" type="xs:string" dfdl:lengthKind="explicit"
        dfdl:length="30" dfdl:lengthUnits="bytes" nillable="true"
        dfdl:useNilForDefault="yes" dfdl:nilKind="literalCharacter"
        dfdl:nilValue="%NUL;" />
For more information about how data types are converted, see Table 1 in z/TPF DFDL generation utility (tpfdfdlgen).

String type

The DFDL specification permits several modifications that are specific to string data types. One modification is the ability to trim and pad string values by using a specific character. When a string value is smaller than the data area that it is stored in, the string is padded with the specified pad character. Conversely, to add the string to a document, you can trim the trailing pad characters from the string that is output. On the z/TPF system, the default character for trimming and padding is 0x00 as defined in tpfbase.lib.dfdl.xsd as textStringPadCharacter="%NUL;". You can change this on a per-schema or per-element basis by defining the DFDL textStringPadCharacter attribute. The following sample highlights the element definition for a string that uses spaces for pad and trim characters.
<xs:element name="Address" type="xs:string" dfdl:lengthKind="explicit"
        dfdl:length="30" dfdl:lengthUnits="bytes" nillable="true"
        dfdl:useNilForDefault="yes" dfdl:nilKind="literalCharacter"
        dfdl:nilValue="%NUL;" dfdl:textStringPadCharacter="%SP;" />
Another modification is that DFDL can handle several different string encodings. This refers to the encoding of the string as stored in the z/TPF system, not the encoding of the transmitted string. On the z/TPF system, the default encoding is EBCDIC 1047, which is defined in tpfbase.lib.dfdl.xsd as encoding="x-ibm-1047-s390". You can change this by defining the DFDL encoding attribute. The following sample highlights the element definition for a string that is encoded in UTF-8.
<xs:element name="Address" type="xs:string" dfdl:lengthKind="explicit"
        dfdl:length="30" dfdl:lengthUnits="bytes" nillable="true"
        dfdl:useNilForDefault="yes" dfdl:nilKind="literalCharacter"
        dfdl:nilValue="%NUL;" dfdl:encoding="utf-8" />

Numeric type

Numbers can be represented in different ways; for example, you can store some numbers in packed decimal or binary coded decimal formats. These formats are defined in DFDL by using the binaryNumberRep attribute. The following sample highlights the element definition for a packed decimal number.
<xs:element name="accountNumber" type="xs:unsignedLong" 
        dfdl:lengthKind="explicit" dfdl:length="12" dfdl:lengthUnits="bytes"
        dfdl:binaryNumberRep="packed" default="0" /> 
A number can also be represented as a decimal with an implicit decimal position. The following sample highlights the element definition for a decimal number that is stored with 1/100th precision.
<xs:element name="balance" type="xs:decimal" dfdl:lengthKind="explicit"
        dfdl:length="8" dfdl:lengthUnits="bytes"
        dfdl:binaryDecimalVirtualPoint="2" default="0" />
A float or double number can be represented in a document by using scientific or decimal notation. These document formats are defined in DFDL by using the tddt:floatingPointFormat attribute. The following sample highlights the element definition for a float number by using decimal notation that is specified by the printf function.
<xs:element name="price" type="xs:float" dfdl:lengthKind="explicit"
               dfdl:length="4" dfdl:lengthUnits="bytes" tddt:floatingPointFormat="%f" 
               default="0"/>
An integer type number can be represented in a document by using various formats. These formats are defined in DFDL by using the tddt:integerFormat attribute. All signed integer types are converted to a long type before being formatted by the sprintf function. All unsigned integer types are converted to an unsigned long type. Therefore, the length specifier for the tddt:integerFormat attribute is always an l. The following sample highlights the element definition for an int type by using one of the format specifiers that are available to the printf function.
<xs:element name="price" type="xs:int" dfdl:lengthKind="explicit"
               dfdl:length="4" dfdl:lengthUnits="bytes" tddt:integerFormat="%ld" 
               default="0"/>

Bit field declarations

A 1-byte field can contain a number of bit field indicators that are defined in application code, rather than in the field definition, by referencing the bits through logical AND operations with a bit mask. DFDL can define fields at a byte level and a bit level. These fields can be set by using a Boolean type to convey whether the status of the bit indicator is set to true or false. Bits that are not used can be skipped by using either the DFDL leadingSkip or trailingSkip attribute. The following sample shows how a single byte with bits 0x40 and 0x20 can be defined as several Boolean elements composing 8 bits.
<xs:element name="mobile" type="xs:boolean" dfdl:lengthKind="explicit"
      dfdl:length="1" dfdl:lengthUnits="bits" dfdl:leadingSkip="1"
      dfdl:alighnmentUnits="bits" default="0" />
<xs:element name="home" type="xs:boolean" dfdl:lengthKind="explicit"
      dfdl:length="1" dfdl:lengthUnits="bits" dfdl:trailingSkip="5"
      dfdl:alignmentUnits="bits" default="0" />

Required and not required elements

The DFDL that is generated by tooling typically defines all elements as not required. You might want some elements to be required for input. A DFDL element is viewed as not required if there is a default value defined. If no default value is defined, the element is required. Additionally, you can define the default value to be that of the nillable value. This is controlled through the DFDL useNilForDefault attribute. The following sample highlights the element definition for a number and string that are not required. Removing the parts that are highlighted in bold would make them required.
<xs:element name="accountNumber" type="xs:unsignedLong"
      dfdl:lengthKind="explicit" dfdl:length="12" dfdl:lengthUnits="bytes"
      dfdl:binaryNumberRep="packed" default="0" />
<xs:element name="Address" type="xs:string" dfdl:lengthKind="explicit"
      dfdl:length="30" dfdl:lengthUnits="bytes" nillable="true"
      dfdl:useNilForDefault="yes" dfdl:nilKind="literalCharacter"
      dfdl:nilValue=%NUL;" />

Multiple layout definitions

The definition of unions in C/C++ language structures or ORGs in BAL DSECTs indicates that there are multiple layout definitions for a data area. When the layouts are not equivalent, you must provide DFDL with information about how to choose which layout is correct for the given data. This is true only when you are converting data to XML, JSON, BSON, and so on. When DFDL does conversions to serialize the data, the labels in the XML, JSON, and so on are used to indicate which layout is correct. One way the layout is determined during parsing is through the use of the DFDL discriminator annotation. A discriminator is a test to determine the existence of a statement. A previous field is typically referenced in a discriminator by using XPath notation to determine either the layout of the subsequent data or the existence of the layout. The following sample shows how discriminators are used to determine the layout of a z/TPFDF logical record.
<xs:element dfdl:lengthKind="implicit" name="lrec90" type="ns0:LREC90">
       <xs:annotation>
              <xs:appinfo source="http.ogf.org/dfdl/">
                     <dfdl:discriminator>{../lrecKey eq xs:hexBinary('90')}
                     </dfdl:discriminator>
              </xs:appinfo>
       </xs:annotation>
</xs:element>

Hidden elements

You might want to keep some elements hidden, either because they have an internal use but no external value, or because they contain personally identifiable information (PII). Because DFDL is aware of both internal and external representation, an element can have visible internal-only representation through the use of hidden groups. Such elements do not appear in the JSON, XML, BSON, and so on. Using hidden groups is one way to have different views of the data, depending on a DFDL variable. A hidden group uses a standard group definition but uses a DFDL hiddenGroupRef attribute to indicate that it is hidden. The hiddenGroupRef attribute can be used on only an empty sequence statement. The following sample shows the definition of hidden element age, which depends on the value of DFDL variable allowPII.
<xs:annotation>
	<xs:appinfo source="http://www.ogf.org/dfdl/">
	      <dfdl:defineVariable name="allowPII" type="xs:boolean"
                   external="true"/>
       </xs:appinfo>
</xs:annotation>

<xs:group name="PII_Info">
      <xs:sequence>
            <xs:element name="age" type="xs:unsignedByte"
                  dfdl:lengthKind="explicit" dfdl:length="1"
                  dfdl:lengthUnits="bytes" default="0" />
      </xs:sequence>
</xs:group>

<xs:choice>
      <xs:group ref="PII_Info">
            <xs:annotation>
                  <xs:appinfo source="http://www.ogf.org/dfdl/">
                        <dfdl:discriminator>{$allowPII}</dfdl:discriminator>
                  </xs:appinfo>
            </xs:annotation>
      </xs:group>
      <xs:sequence dfdl:hiddenGroupRef="PII_Info" />
</xs:choice>

Name-value pair variables

Any name-value pair can be accessed in a DFDL schema by using a DFDL external variable. The name-value pair variable must be defined in tpfNameValue.lib.dfdl.xsd. System generated name-value pairs such as ISrvcName are already defined in that file. The following example illustrates how to use REST provider support to set the operationId name-value pair variable, which can be stored in a 16-byte string element in the REST provider request structure.
<xs:schema
      targetNamespace="http://www.ibm.com/xmlns/prod/ztpf/dfdl/gen/sample"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:nv="http://www.ibm.com/xmlns/prod/ztpf/name-value"
      xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
      xmlns:tpfbase="http://www.ibm.com/xmlns/prod/ztpf/dfdl/lib/tpfbase">

<xs:import namespace="http://www.ibm.com/xmlns/prod/ztpf/name-value" 
           schemaLocation="tpfNameValue.lib.dfdl.xsd"/>

<xs:group name="srvcName">
      <xs:sequence>
            <xs:element name="operationId" type="xs:string" dfdl:length="16"
                  dfdl:outputValueCalc="{$nv:ISrvcName}"/>
      </xs:sequence>
</xs:group>

<xs:sequence dfdl:hiddenGroupRef="srvcName"/>

Variable length strings

You might need some strings to be variable in length. You can use a DFDL expression to indicate that a string has a variable length and define the length of the string. To calculate the length of the field, the DFDL expression uses XPath notation to reference a previous field to define the length. Because string lengths are not usually passed in documents, DFDL supports calculated fields to store calculated results, such as string lengths, in an element. These elements also can be hidden so that the element that contains the length is not present in documents that are created by DFDL. The following sample shows the definition of a variable length string with a hidden string length element.
<xs:group name="hiddenLen">
      <xs:sequence>
            <xs:element name="addrLen" type="xs:unsignedShort"
                  dfdl:lengthKind="explicit" dfdl:length="2"
                  dfdl:lengthUnits="bytes"
                  dfdl:outputValueCalc="{dfdl:valueLength(../Address,'bytes')}"
            />
      </xs:sequence>
</xs:group>

<xs:sequence dfdl:hiddenGroupRef="hiddenLen" />
<xs:element name="Address" type="xs:string" dfdl:lengthKind="explicit"
       dfdl:length="{../addrLen}" dfdl:lengthUnits="bytes" />

Variable size arrays

You might need some arrays to be variable in size; that is, in the number of items in the array. You can use a DFDL expression to indicate that an array has a variable number of items and define the number of items in the array. To calculate the size of the array, the DFDL expression uses XPath notation to reference a previous field to define the size. Because array sizes are not usually passed in documents, DFDL supports calculated fields to store calculated results, such as array sizes, in an element. These elements also can be hidden so that the element that contains the array size is not present in documents that are created by DFDL. The following sample shows the definition of a variable size array with a hidden array size element.
<xs:schema
      targetNamespace="http://www.ibm.com/xmlns/prod/ztpf/dfdl/gen/sample"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:fn="http://www.w3.org/2005/xpath-functions"
      xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
      xmlns:tpfbase="http://www.ibm.com/xmlns/prod/ztpf/dfdl/lib/tpfbase">

<xs:group name="hiddenSize">
      <xs:sequence>
            <xs:element name="arrayCount" type="xs:unsignedShort"
                  dfdl:lengthKind="explicit" dfdl:length="2"
                  dfdl:lengthUnits="bytes"
                  dfdl:outputValueCalc="{fn:count(../Numbers)}" />
      </xs:sequence>
</xs:group>

<xs:sequence dfdl:hiddenGroupRef="hiddenSize" />
<xs:element name="Numbers" type="xs:int" dfdl:lengthKind="explicit"
       dfdl:length="4" dfdl:lengthUnits="bytes" minOccurs="0"
       maxOccurs="unbounded" dfdl:occursCountKind="expression"
       dfdl:occursCount="{../arrayCount}" />

Pointer references

DFDL is used to describe a contiguous area of data. However, you can use attributes that are specific to the z/TPF system in DFDL to describe non-contiguous data, such as is often used in C/C++ language structures or BAL DSECTs. The z/TPF specific attributes support the definition of pointers on element definitions, which can be useful for variable length strings. The DFDL length attributes do not change but are instead commuted to the pointed-to element. The pointers can be 4 bytes or 8 bytes in length. The following sample highlights how you can change a string element to an 8-byte pointer to the string.
<xs:schema
      targetNamespace="http://www.ibm.com/xmlns/prod/ztpf/dfdl/gen/sample"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:tddt="http://www.ibm.com/xmlns/prod/ztpf/xml/lib/tpfattributes"
      xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
      xmlns:tpfbase="http://www.ibm.com/xmlns/prod/ztpf/dfdl/lib/tpfbase">

<xs:element name="Address" type="xs:string" dfdl:lengthKind="explicit"
       dfdl:length="{../addrLen}" dfdl:lengthUnits="bytes"
       tddt:indirectKind="pointer" tddt:indirectLength="8" />