Removing Empty Elements from a Large XML Payload
You sometimes may have large payload structures with most of the elements empty, especially when using canonical schemas. This large payload structure, combined with a large volume of data, can result in a significant part of the payload containing empty elements, leading to transformation errors or service errors.
As an example, in one of our recent projects, we had a service using a canonical schema as input, and in our use case, we passed only the relevant information, leaving the remaining elements empty. This resulted in a null pointer exception in remote service, as it was not configured to handle empty elements correctly. Changes in the implementation of the remote service were out of our purview, hence, the only solution available in this case was not to pass any empty elements.
Another benefit of removing unused empty elements, in such cases, is the reduction in actual payload size, as many of the generic empty elements will be removed from the XML payload.
One way of removing empty elements in the payload is adding “If” conditions in the transformation; however, this will make the transformation complex, especially when dealing with a canonical schema. Further, this would not be a reusable solution, as it would be tied to a particular type of canonical schema. If the canonical schema is complex and large, this would enhance that complexity.
Alternatively, by using an XSLT transformation, we can create a generic reusable solution that can remove all empty elements, regardless of the XML schema, thereby avoiding the need to create complex transformations. The following XSLT will remove all empty elements from the input and assign non-empty elements to the output. You can use the same variable name as input and output, and the resulting XML payload will have only non-empty elements and a much smaller size.
The following is the generic XSLT transformation that can be used, regardless of input and output XML schemas:
<XSL:TEMPLATE MATCH="NODE()" XML:ID="ID_11">
<XSL:IF TEST="COUNT(DESCENDANT::TEXT()[STRING-LENGTH(NORMALIZE-SPACE(.))>0]|@*)" XML:ID="ID_12">
<XSL:APPLY-TEMPLATES SELECT="@*|NODE()" XML:ID="ID_14"/>
<XSL:TEMPLATE MATCH="@*" XML:ID="ID_15">
<XSL:TEMPLATE MATCH="TEXT()" XML:ID="ID_17">
<XSL:VALUE-OF SELECT="NORMALIZE-SPACE(.)" XML:ID="ID_18"/>
To utilize this XSLT transformation, add an XSLT transformation activity in your SOA process and assign the input and output variables. Add the above code snippet to the newly created XSLT transformation. Use the source view to make this change. The end result will look similar to the attached XSLT file, included for your reference.