Transforming XML to JSON in DataWeave: A Comprehensive Guide

An XML stands for extensible markup language, and it is used to structure data for storage and transport. In XML data, there are both tags and text. The tags provide the structure to the data. The text in the data that you wish to store is surrounded by these tags, which adhere to specific syntax guidelines. At its core, an XML is a standard data that utilizes customized tags, to describe the structure of the record and how it should be stored and transported.

In many of the mule applications, we have requirements where we want to transform XML data coming from different data sources into JSON or maybe in any other format, To do so, we generally use dataweave language. In this article, we’ll cover some scenarios in which we’ll see how we can perform certain transformation logics on XML data.

Throughout the article, we’re going to use the following XML data (Input data):

<foods:myns xmlns:foods="http://training.mulesoft.com/foods">
<breakfast_menu>
<food>
	<name>Belgian Waffles</name>
	<price currency="USD">5.95</price>
	<description>Two of our famous Belgian Waffles with plenty of real maple syrup</description>
	<calories>650</calories>
</food>
<food>
	<name>Strawberry Belgian Waffles</name>
	<price currency="USD">7.95</price>
	<description>Light Belgian waffles covered with strawberries and whipped cream</description>
	<calories>900</calories>
</food>
<food>
	<name>Berry-Berry Belgian Waffles</name>
	<price currency="USD">8.95</price>
	<description>Light Belgian waffles covered with an assortment of fresh berries and whipped cream</description>
	<calories>900</calories>
</food>
<food>
	<name>French Toast</name>
	<price currency="INR">450</price>
	<description>Thick slices made from our homemade sourdough bread</description>
	<calories>600</calories>
</food>
<food>
	<name>Homestyle Breakfast</name>
	<price currency="USD">6.95</price>
	<description>Two eggs, bacon or sausage, toast, and our ever-popular hash browns</description>
	<calories>950</calories>
</food>
</breakfast_menu>
</foods:myns>

Converting XML to JSON

Values of JSON data will be mapped in one to one manner with XML data values.

Dataweave expression:

%dw 2.0
output application/json
---
payload

Output:

{
  "myns": {
    "breakfast_menu": {
      "food": {
        "name": "Belgian Waffles",
        "price": "5.95",
        "description": "Two of our famous Belgian Waffles with plenty of real maple syrup",
        "calories": "650"
      },
      "food": {
        "name": "Strawberry Belgian Waffles",
        "price": "7.95",
        "description": "Light Belgian waffles covered with strawberries and whipped cream",
        "calories": "900"
      },
      "food": {
        "name": "Berry-Berry Belgian Waffles",
        "price": "8.95",
        "description": "Light Belgian waffles covered with an assortment of fresh berries and whipped cream",
        "calories": "900"
      },
      "food": {
        "name": "French Toast",
        "price": "450",
        "description": "Thick slices made from our homemade sourdough bread",
        "calories": "600"
      },
      "food": {
        "name": "Homestyle Breakfast",
        "price": "6.95",
        "description": "Two eggs, bacon or sausage, toast, and our ever-popular hash browns",
        "calories": "950"
      }
    }
  }
}

Extracting the namespace

To separate the namespace from the XML component utilize the hash “#

Dataweave Expression:

%dw 2.0
output application/json
---
payload.myns.#

Output:

"http://training.mulesoft.com/foods"

Transforming XML Fields

While transforming XML into JSON you may encounter a couple of difficulties:

  1. In XML, we can only have one root element while JSON may have multiple.
  2. There is no array concept in XML (only repeated elements). However, the JSON data structure is based on arrays and objects.

Thus, to overcome the above difficulties, you can use dataweave selector “*” which will transform XML repeated elements into JSON array.

Dataweave Expression:

%dw 2.0
output application/json
---
payload.myns.breakfast_menu.*food

Output:

[
  {
    "name": "Belgian Waffles",
    "price": "5.95",
    "description": "Two of our famous Belgian Waffles with plenty of real maple syrup",
    "calories": "650"
  },
  {
    "name": "Strawberry Belgian Waffles",
    "price": "7.95",
    "description": "Light Belgian waffles covered with strawberries and whipped cream",
    "calories": "900"
  },
  {
    "name": "Berry-Berry Belgian Waffles",
    "price": "8.95",
    "description": "Light Belgian waffles covered with an assortment of fresh berries and whipped cream",
    "calories": "900"
  },
  {
    "name": "French Toast",
    "price": "450",
    "description": "Thick slices made from our homemade sourdough bread",
    "calories": "600"
  },
  {
    "name": "Homestyle Breakfast",
    "price": "6.95",
    "description": "Two eggs, bacon or sausage, toast, and our ever-popular hash browns",
    "calories": "950"
  }
]

If you want to specify your output format with particular fields, you need to iterate over the items in the array. For this, you can use the map function along with selectors in dataweave.

Dataweave Expression:

%dw 2.0
output application/json
---
payload.myns.breakfast_menu.*food map {
    'foodName': $.name,
    'calories': $.calories
}

Output:

[
  {
    "foodName": "Belgian Waffles",
    "calories": "650"
  },
  {
    "foodName": "Strawberry Belgian Waffles",
    "calories": "900"
  },
  {
    "foodName": "Berry-Berry Belgian Waffles",
    "calories": "900"
  },
  {
    "foodName": "French Toast",
    "calories": "600"
  },
  {
    "foodName": "Homestyle Breakfast",
    "calories": "950"
  }
]

Extracting/transforming XML attributes:

DataWeave provides a mechanism that allows the reading of attributes from an XML element using the @ symbol followed by the key.

Dataweave Expression:

%dw 2.0
output application/json
---
payload.myns.breakfast_menu.*food map {
    'foodName': $.name,
    'price': $.price,
    'currency': $.price.@currency
}

Output:

[
  {
    "foodName": "Belgian Waffles",
    "price": "5.95",
    "currency": "USD"
  },
  {
    "foodName": "Strawberry Belgian Waffles",
    "price": "7.95",
    "currency": "USD"
  },
  {
    "foodName": "Berry-Berry Belgian Waffles",
    "price": "8.95",
    "currency": "USD"
  },
  {
    "foodName": "French Toast",
    "price": "450",
    "currency": "INR"
  },
  {
    "foodName": "Homestyle Breakfast",
    "price": "6.95",
    "currency": "USD"
  }
]