Skip to Content
Technical Articles

How to remove all empty tags from an XML in SAP PI… It’s Simple!

Hi Guys!

Today I will share a little tip that can be very useful in some cases, how to remove all empty tags from an XML.

In some cases, you need to remove tags that are empty (Ex. <tag> </tag> or <tag/>), and creating this rule in all fields by graphical mapping would be a lot of work.

The tip is to use the code below in your message mapping:

Source code:

public void transform(TransformationInput transformationInput, TransformationOutput transformationOutput) throws StreamTransformationException {
	try {
		InputStream inputstream = transformationInput.getInputPayload().getInputStream();
		OutputStream outputstream = transformationOutput.getOutputPayload().getOutputStream();

		byte[] b = new byte[inputstream.available()];
		inputstream.read(b);
		String encoding ="UTF-8";
		String inputXML=new String(b);

		inputXML = inputXML.replaceAll("<\\s*[\\w:]+?\\s*\\/>", "");
		inputXML = inputXML.replaceAll("<\\s*[\\w:]+>(<\\/?\\w+>)*<\\/\\s*[\\w:]+>", "");
	
		outputstream.write(inputXML.getBytes(encoding));

	} catch (Exception exception) {
		getTrace().addDebugMessage(exception.getMessage());
		throw new StreamTransformationException(exception.toString());
	}
}

 

Test:

Below is an example of the mapping performed, where the field <complemento2\> was removed:

 

Another Solution (XSLT)

It’s possibile use another solution, a XSLT mapping, below the source code of an XSLT shared by our colleague @Evgeniy Kolmakov.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="*[not(@*|*|comment()|processing-instruction()) and normalize-space()='']"/>
</xsl:stylesheet>

I recommend testing both solutions to see which one best applies to your project.

Notes:

  1. You can use this code and roles in graphical mapping
  2. The java code is executed after the graphical mapping.
  3. If you want to remove only one field, apply the role below in your field:

I hope I helped you with this little tip… 😀

 

 

12 Comments
You must be Logged on to comment or reply to a post.
  • Thanks for this great post!

    SAP PI/PO (Process Integration/Process Orchestration) is a tool that allows you to integrate solutions. It makes it easy to synchronize data between different systems. Let’s say you are using the SAP ERP system, and you wish to integrate with the CRM system.

  • Hi Alexander,

    Good you got the problem solved.

    I would be very careful about adding Java Mapping code into a message mapping. It may be really difficult for someone else to see that it is going on. I get that it is easy to set up and compile than creating a manage a java mapping.

    I would also recommend using a SAX parser that is a little more stable than manipulating XML Strings via regex.

    Daniel

  • Hi Alexandre

    One small comment related to the code below:

    byte[] b = new byte[inputstream.available()];

    Have you read about available() method?

    https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#available()

    According to that documentation:  It is never correct to use the return value of this method to allocate a buffer intended to hold all data in this stream.

    BTW, I recommend you to specify the charset when you construct a new String based on an array of bytes.

    Regards,

    Andrzej

     

  • Hi Alexandre!

    I used to avoid java mappings whenever it’s possible,so, I prefer to use simple XSL transformation for such cases:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output indent="yes"/>
        <xsl:strip-space elements="*"/>
        
        <xsl:template match="node()|@*">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:copy>
        </xsl:template>
        
        <xsl:template match="*[not(@*|*|comment()|processing-instruction()) and normalize-space()='']"/>
        
    </xsl:stylesheet>

    Regards, Evgeniy.