Introduction

This is the second part of the two-part series on achieving file content conversion for deep structure with XSLT. The first part covered the approach to flatten a deep structure XML prior to receiver FCC conversion.

This second part will focus on deepening a flat XML after FCC conversion at a sender channel.

Source Code and Explanation

The full source code, example input and output files are available in the GitHub repository listed in the first part of this series.

Prerequisite: To deepen an XML, the segments that will be structured in a parent-child relationship needs to have a field with the same value on both the parent and the child.

The logic comprises of three different types of XSLT template match sections.

1. Selecting child segments at root element level

At root element level, the segments that should be immediate child segments are explicitly selected.

There are two different versions of the code as this is dependent on the FCC configuration of the sender channel. For NFS/FTP channels configured with ignoreRecordsetName = true, the generated XML from FCC will not have the Recordset segment as a child of the root element. Due to slight behavioral difference of the MessageTransformBean module, it does not support the above parameter and will always have a Recordset segment.

In the example below, segments Header, Delivery and Footer are “designated” as direct child elements of the root element (or Recordset element.)

With Recordset

<!-- At the root element level, manually select the child segments -->
<xsl:template match="*[local-name() = 'MT_Deep']">
  <xsl:copy>
   <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>
<xsl:template match="Recordset">
  <xsl:copy>
   <xsl:apply-templates select="Header"/>
   <xsl:apply-templates select="Delivery"/>
   <xsl:apply-templates select="Footer"/>
  </xsl:copy>
</xsl:template>

Without Recordset

<!-- At the root element level, manually select the child segments -->
<xsl:template match="*[local-name() = 'MT_Deep']">
  <xsl:copy>
   <xsl:apply-templates select="Header"/>
   <xsl:apply-templates select="Delivery"/>
   <xsl:apply-templates select="Footer"/>
  </xsl:copy>
</xsl:template>

2. Deepening segments with parent-child relationship

For subsequent segments with parent-child relationship, first the key field in the parent segment is saved in a variable, then the immediate child fields are copied, finally, child segments which have its key field matching the parent are selected.


The similar match template logic is repeated as required for all parent segments that will contain child segments.


<xsl:template match="Delivery">
  <!-- (1) - Save parent key value to be used to select corresponding child segments -->
  <xsl:variable name="deliveryno" select="DeliveryNo"/>
  <xsl:copy>
   <!-- (2) - Select the child elements that are fields -->
   <xsl:apply-templates select="*[not(*)]"/>
   <!-- (3) - Select the child segments which have matching value as parent key value -->
   <xsl:apply-templates select="../Order[DeliveryNo=$deliveryno]"/>
  </xsl:copy>
</xsl:template>

3. Identity transformation for all other attributes and nodes

Finally, for all other attributes and nodes, identity (1-1) transformation is applied.


<!-- Match all other attributes (@*) and other node types (elements, comments) -->
<!-- Copy the current element, and select child attributes and nodes -->
<xsl:template match="@* | node()">
  <xsl:copy>
   <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

Example Scenario

We will reuse the example structure used in the first part. The goal is to achieve creation of a deep XML payload from the flat file with deep/nested structure.

The input file will be a shipment file which contains all the details for the shipment. Each shipment file can have multiple deliveries, each delivery in turn can have multiple orders, and each order multiple items. Each segment occurs under the parent segment, therefore indicating a deep/nested structure.

Segment Name Parent Segment Type Indicator Occurrence
Header H 1
Delivery D 1 – unbounded
Order Delivery O 1 – unbounded
OrderText Order T 0 – 1
Item Order I 1 – unbounded
Footer F 1

Design

This article will only focus on the sections that are required to enable this XSLT approach, therefore common steps for design and configuration will not be covered.

Source structure definition

The data type for the source structure will be defined as a deep XML schema. No flat DT definition that is required for FCC needs to be defined. Below are the sample deep XML schema representation of the input format, depending on whether Recordset is ignored during FCC or not.

For the remainder of the example, the design will be based on the structure with Recordset as it will be using the MessageTransformBean module in a sender SFTP channel.

Without Recordset With Recordset
/wp-content/uploads/2015/02/dt_646508.png /wp-content/uploads/2015/02/dt_rs_646486.png

Message Mapping

Create a normal graphical message mapping to map the deep source structure above to the intended target structure.

Import XSLT code

Zip the XSL file and import it to ESR as an Imported Archive.

Operation Mapping

Typically the XSLT mapping will be used as the first step of the Operation Mapping that will deepen the XML generated from FCC. Then the message mapping will map the deep source to intended target.

Step Mapping Type Name
1 XSL Flat2Deep_WithRecordset
2 Message Mapping <Message Mapping object created above>

Below is a sample execution of the first step of the OM to deepen the XML that was created by the FCC at sender. The result shows that the XSLT have deepened the XML to the intended structure.

Note: As seen in the test tab, the XML output of the sender FCC is not a valid XML document when validated against the original data type definition (the segments indicated in red icons.) It does not matter as the main purpose of the XML is to be further deepened by the XSLT.

/wp-content/uploads/2015/02/omtest_646526.png

Configuration

The normal configuration steps are performed. At the sender channel, specify the FCC parameters. The following screenshot shows the FCC parameters using MessageTransformBean on an SFTP channel.

Note: The recordset structure order needs to be set to variable (xml.recordsetStructureOrder = var) because due to input flat file having deep structure, the segments are not in an ascending order.

/wp-content/uploads/2015/02/mtb_646528.png

Testing Results

After execution of the interface, we can view the logs to see the content of the original file prior to sender FCC.

/wp-content/uploads/2015/02/ori_646559.png

After the XSLT transformation (and using a 1-1 graphical message mapping) the target payload in the receiver proxy is displayed. As we can see below, the XML generated has a deeply nested structure.

/wp-content/uploads/2015/02/moni_646533.png

Conclusion

Similar to the first part, we have achieved a deep XML structure after sender FCC with a relatively simple XSLT logic. However, note that the logic cannot be coded so that it can be generically reused because the exact parent-child relationship needs to be specified.

To report this post you need to login first.

3 Comments

You must be Logged on to comment or reply to a post.

  1. Charan R

    Hello Eng,

    I’ve a requirement where I have to group Order (Occurence – 1-1 under each Delivery node) and Item (Occurence – 0-unbounded) under Delivery node until the next Order occurs. Following is the structure.

    Input—

    Delivery

    Order

    Item

    Order

    Item

    Item

    Item

    Order

    Order

    Item

     

    Output —

    Delivery

    Order

    Item

    Delivery

    Order

    Item

    Item

    Item

    Delivery

    Order

    Delivery

    Order

    Item

     

     

    I have no key fields like DeliveryNo or OrderNo which allows me to group them. Only condition is every new Order node and the immediately following Item nodes should go into one Delivery node.

     

    Just wondering if this is indeed possible.

     

    Thanks

    Charan

     

    (0) 
  2. shameer shaik

    Hi eng swee yeaoh,
    Could you please help me here in the nested loop case.

    My Source xml is :

    <?xml version=”1.0″ encoding=”UTF-8″?>
    <AB>
    <Record>
    <A>
    <RecordType/>
    </A>
    <B>
    <RecordType>a</RecordType>
    </B>
    <C>
    <RecordType>1</RecordType>
    </C>
    <B>
    <RecordType>b</RecordType>
    </B>
    <C>
    <RecordType>2</RecordType>
    </C>
    </Record>
    </AB>

    The output should be as below:

    <?xml version=”1.0″ encoding=”UTF-8″?>
    <AB>
    <A>
    <RecordType/>
    </A>
    <B>
    <RecordType>a</RecordType>
    <C>
    <RecordType>1</RecordType>
    </C>
    </B>

    <B>
    <RecordType>b</RecordType>
    <C>
    <RecordType>2</RecordType>
    </C>
    </B>
    </AB>

    B and C segments are repeated.Under each B node C node should get repeated in  target.

    Thanks,

    Shameer

    (0) 

Leave a Reply