← Back to Learning & Insights

Groovy for Fixed-Length to XML Conversion

In many integration scenarios, you encounter legacy systems that exchange data in a fixed-length text format. This is a flat file where each field has a predefined, non-variable length. Converting this to a modern, structured format like XML is a common requirement. While you could use a Message Mapping, a dynamic Groovy script offers a more flexible solution, especially when the file structure is defined by external properties in SAP CPI.

The Fixed-Length Challenge

The core challenge with fixed-length files is splitting the raw string into meaningful fields based on their start and end positions. A Groovy script can automate this by reading the field lengths and corresponding XML tags from properties, making the solution highly reusable and maintainable.

Setting up the CPI Properties

First, you need to define the structure of the fixed-length file and the desired XML output as process properties in your Integration Flow. This allows you to change the structure without modifying the Groovy script.

  • Property 'FieldFixedLengths': A comma-separated list of field lengths. For example: '2,8,15,5'.
  • Property 'xmlSegments': A comma-separated list of the XML tags for each corresponding field. For example: 'ID,Date,ProductName,Quantity'.

Fixed Length File:

This is a sample file

00001John Smith     29MNew York      
00002Alice Johnson  34FLos Angeles   
00003Robert Brown   41MChicago       

The Groovy Script

The script below reads the incoming fixed-length message body, uses the properties to parse it, and then generates an XML payload.

  • Property FieldFixedLengths: 5,15,2,1,12.
  • Property xmlSegments: ID,Name,Age,Gender,City.
import com.sap.gateway.ip.core.customdev.util.Message;

def Message processData(Message message) 
{
    def body = message.getBody(java.lang.String) as String;

    def body1 = "<root>\n";  // start root tag

    def prop = message.getProperties();
	
    // Get the fixed-length and XML definitions from properties
    def Segments = prop.get("xmlSegments").split(",") as String[]
    def FieldFixedLengths = prop.get("FieldFixedLengths").split(",") as String[]
    
    def propertyValue = message.getProperty("FieldFixedLengths")
    def sum1 = propertyValue.tokenize(',').collect { it as int }.sum()
    
    def bodyLength = body.length()
    if (bodyLength < sum1) {
        int paddingLength = sum1 - bodyLength
        body = body + ' ' * paddingLength
    }
    
    def lines = body.split("\n");
	
    // build xml
    for (i = 0; i < lines.length; i++) 
    {
        def sum = 0
        body1 += "  <row>\n";

        for (k = 0; k < FieldFixedLengths.length; k++) 
        {
            def l2 = Integer.valueOf(FieldFixedLengths[k]);
            def value = lines[i].substring(sum, sum + l2).trim()
            body1 += "    <" + Segments[k] + ">" + value + "</" + Segments[k] + ">\n"
            sum += l2;
        }

        body1 += "  </row>\n";
    }

    body1 += "</root>";  // close root tag

    message.setBody(body1);
    return message;
}

How the Script Works:

  1. Get Properties: It retrieves the 'FixedLengths' and 'XmlSegments' properties from the Integration Flow, splitting them into Groovy lists. The 'FixedLengths' are converted to integers.
  2. Parse Fixed-Length String: The script iterates through the 'fixedLengths' list. In each loop, it uses 'substring()' with a 'startIndex' and 'length' to extract a field from the message body. The '.trim()' method removes any trailing spaces.
  3. Build XML: Loops through each record:
    • Keeps a running index (sum) to know where each field starts.
    • Reads exactly FieldFixedLengths[k] characters
    • Wraps the extracted substring inside an XML tag <SegmentName>value</SegmentName>
    • Moves pointer to the next field
  4. Set Body: The final XML string is set back as the message body.

Output XML File:

Flat file is converted into XML.

<root>
	<row>
		<ID>00001</ID>
		<Name>John Smith</Name>
		<Age>29</Age>
		<Gender>M</Gender>
		<City>New York</City>
	</row>
	<row>
		<ID>00002</ID>
		<Name>Alice Johnson</Name>
		<Age>34</Age>
		<Gender>F</Gender>
		<City>Los Angeles</City>
	</row>
	<row>
		<ID>00003</ID>
		<Name>Robert Brown</Name>
		<Age>41</Age>
		<Gender>M</Gender>
		<City>Chicago</City>
	</row>
</root>  

Conclusion

This Groovy script provides a flexible and dynamic solution for fixed-length file conversion in SAP CPI. By externalizing the file structure definition, you can easily adapt your integration flow to new fixed-length formats without changing the script, making your solution highly scalable and easy to maintain.