Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Making Transformations With Dom4j in Mule

DZone's Guide to

Making Transformations With Dom4j in Mule

Dom4j can be used with Mule to perform a number of complex XML parsings and transformations. For Community edition users of Mule, it's a better choice than XSLT.

Free Resource

Share, secure, distribute, control, and monetize your APIs with the platform built with performance, time-to-value, and growth in mind. Free 90 day trial 3Scale by Red Hat

I have previously written about XML to XML transformation in Bushorn using the XSLT transformer, which allows us to can modify an incoming XML file and add a particular node with a value in it. In Mule, generally, there are various ways to solve a particular problem. It's the same with XML: we can create, modify, or transform an XML into a different XML in various ways. One way is to use Mule’s graphical DataWeave or DataMapper tools. Or, you can use the XSLT transformer to manipulate an XML payload.

Although tools like DataWeave are very powerful and capable of transforming and manipulating the structure of XML, some (like DataWeave) are limited to the Enterprise edition of Mule, leaving the Community edition users to go with the XSLT feature for manipulating the XML. This is sometimes not easy for developers who are not comfortable with the XSLT framework.

In this blog, we will see an alternate method of manipulating the existing XML structure, like creating a new node with value in the middle, deleting an existing node from the XML, modifying an existing node value or adding an attribute to a node. We will not be using XSLT this time. We'll be using an alternative method called Dom4j in Mule.

Dom4j is an open-source XML framework for Java. With Mule, it can be used to perform XML parsing and transformations. It is a highly flexible, light-weight, memory-efficient API with high performance.

Create a New Node With a Value

We will start with creating a new node with a value in an existing XML payload in our Mule flow.

We will be receiving the following payload in our Mule flow:

<?xml version="1.0" encoding="UTF-8"?>
<RootTag>
	<name>Anirban Sen Chowdhary</name>
	<id>37</id>
</RootTag>

Our target will be adding a new node, say, in between the XML. We will be using Dom4j. Our Mule flow will be:

<flow name="setXmlNodeFlow">
	<http:listener config-ref="HTTP_Listener_Configuration" path="/set" doc:name="HTTP"/>
	<object-to-string-transformer doc:name="Object to String"/>
	<mulexml:xml-to-dom-transformer returnClass="org.dom4j.Document" doc:name="XML to DOM"/>
	<expression-component doc:name="Expression">
		<![CDATA[
       node = message.payload.rootElement.addElement('designation');
       node.text = 'developer';
       message.payload.rootElement.elements().add(1, node.detach());
       ]]>
	</expression-component>
	<mulexml:dom-to-xml-transformer doc:name="DOM to XML"/>
	<logger message="#[message.payload]" level="INFO" doc:name="Logger"/>
</flow>

Here, we are creating a new node designation with a value developer with the incoming XML payload. When we test with the URL http://localhost:8081/set, we get the following output:

Image title

Modify an Existing Node

We will again use Dom4j to modify an existing XML node value with a new value. Our input payload XML value is:

<?xml version="1.0" encoding="UTF-8"?>
<RootTag>
	<name>Anirban Sen Chowdhary</name>
	<designation>developer</designation>
	<id>37</id>
</RootTag>

We want to change the value of designation node from developer to director. We create our Mule flow as follows:

<flow name="modifyXmlNodeFlow">
	<http:listener config-ref="HTTP_Listener_Configuration" path="/modify" doc:name="HTTP"/>
	<object-to-string-transformer doc:name="Object to String"/>
	<mulexml:xml-to-dom-transformer returnClass="org.dom4j.Document" doc:name="XML to DOM"/>
	<expression-component doc:name="Expression">
		<![CDATA[
        node = message.payload.getRootElement().selectSingleNode('//RootTag/designation');
        node.text = 'Director';
        ]]>
	</expression-component>
	<mulexml:dom-to-xml-transformer doc:name="DOM to XML"/>
	<logger message="#[message.payload]" level="INFO" doc:name="Logger"/>
</flow>

When we send an XML with a value of designation node as developer and hit the URL http://localhost:8081/modify, we can see the output where the value is replaced with director:

Image title

Delete an Existing Node

What if we want to delete an existing node? Yes, again, we can do it with the help of Dom4j!

Suppose we now want to delete an existing node (say, designation) completely from our input XML file. We can do so with following Mule flow:

   <flow name="deleteXmlNodeFlow">
	<http:listener config-ref="HTTP_Listener_Configuration" path="/delete" doc:name="HTTP"/>
	<object-to-string-transformer doc:name="Object to String"/>
	<mulexml:xml-to-dom-transformer returnClass="org.dom4j.Document" doc:name="XML to DOM"/>
	<expression-component doc:name="Expression">
		<![CDATA[
         node = message.payload.getRootElement().selectSingleNode('//RootTag/designation');
         node.detach();
        ]]>
	</expression-component>
	<mulexml:dom-to-xml-transformer doc:name="DOM to XML"/>
	<logger message="#[message.payload]" level="INFO" doc:name="Logger"/>
</flow>     

Now, when we pass our XML into the Mule flow with the node designation and hit the URL http://localhost:8081/delete, we can see the output — the node completely disappears:

Image title

Add an Attribute in an XML Node

Yes, we can even add attributes to a node of the input XML coming into the Mule flow.

If we send the following XML in our Mule flow:

<?xml version="1.0" encoding="UTF-8"?>
<RootTag>
    <name>Anirban Sen Chowdhary</name>
    <designation>developer</designation>
    <id>37</id>
</RootTag>

We can add an attribute to the node ID (such as departmentId) to it with this simple flow:

<flow name="addAttributeinXmlFlow">
	<http:listener config-ref="HTTP_Listener_Configuration" path="/addattribute" doc:name="HTTP"/>
	<object-to-string-transformer doc:name="Object to String"/>
	<mulexml:xml-to-dom-transformer returnClass="org.dom4j.Document" doc:name="XML to DOM"/>
	<expression-component doc:name="Expression">
		<![CDATA[
          import org.dom4j.Element;
          node = message.payload.getRootElement().selectSingleNode('//RootTag/id');
          Element element = (Element) node;
          element.addAttribute("departmentId","mk1230734");
        ]]>
	</expression-component>
	<mulexml:dom-to-xml-transformer doc:name="DOM to XML"/>
	<logger message="#[message.payload]" level="INFO" doc:name="Logger"/>
</flow>

Once we hit the URL, we can see the output with node ID having an attribute departmentId:

Image title

Read an Attribute Value from XML

Now, suppose we are already sending an XML to our Mule flow with a node having an attribute with a value and we need to read the attribute value. We can do so easily with Dom4j.

Let our input XML be:

<?xml version="1.0" encoding="UTF-8"?>
<RootTag>
    <name>Anirban Sen Chowdhary</name>
    <designation>developer</designation>
    <id departmentId="mk1230734">37</id>
</RootTag>

Now, to read the value of attribute departmentId from node ID, we need to have the following Mule flow:

<flow name="getAttributefromXmlFlow">
	<http:listener config-ref="HTTP_Listener_Configuration" path="/getattribute" doc:name="HTTP"/>
	<object-to-string-transformer doc:name="Object to String"/>
	<mulexml:xml-to-dom-transformer returnClass="org.dom4j.Document" doc:name="XML to DOM"/>
	<expression-component doc:name="Expression">
		<![CDATA[
           import org.dom4j.Element;
           import java.util.logging.Logger;

           Logger log = Logger.getLogger("");
           node = message.payload.getRootElement().selectSingleNode("//RootTag/id");
           Element element = (Element) node;
           String attr = element.attributeValue("departmentId");
           log.info(attr);
        ]]>
	</expression-component>
	<mulexml:dom-to-xml-transformer doc:name="DOM to XML"/>
</flow>

Here, once we hit the URL http://localhost:8081/getattribute, the flow will log the attribute value on-console:

Image title

Instead of reading the attribute value in the Expression component with...

String attr = element.attributeValue("departmentId");

...we can alternately also use XPATH to read the value:

String attr = element.valueOf("@departmentId");

Conclusion

Here, we can see that with Mule, there are multiple ways to play with XML payload and create, modify, delete, and reconstruct its structure.

Mule offers flexibility with its technology and provides various options like Dataweave, XSLT, and Dom4j in the Mule flow to play around with XML. We should use Dom4j when we know about our XML structure and want to get information or to restructure it. It contains several Java classes like Document, Element, Node, and Attributes. We have seen several methods for a few of those in this article.

This article provides an overall basic understanding of using Dom4j with Mule and how it can be used to perform many complex XML parsings and transformations that we will cover in next articles.

Discover how you can achielve enterpriese agility with microservices and API management

Topics:
mule ,dom4j ,xslt ,transformations ,xml ,nodes

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}