5

I am attempting to map a response from a 3rd party call into a different structure using the DataMapper transform within Mule.

From the 3rd party we receive an array of items (amongst other things) and I want to map a single item within the array to an object (JSON). I receive an identifier for the item in the request which is available as an input argument.

My question is, how can I map the fields of the item based on the identifier?

Example XML response

<account>
    <accountNumber>1234567</accountNumber>
    <books>
        <book>
            <id>1</id>
            <title>Sample title1</title>
            <availableFrom>21-03-16</availableFrom>
        </book>
        <book>
            <id>2</id>
            <title>Sample title2</title>
            <availableFrom>21-03-16</availableFrom>
        </book>
        <book>
            <id>3</id>
            <title>Sample title3</title>
            <availableFrom>21-03-16</availableFrom>
        </book>
    </books>
</account>

Needs to become:

{
    "person": {
        "accountNumber": 1234567,
        "selectedBook": {
            "id": 1, 
            "title": "Sample title1"
        },
        "otherBooks": [
            {
                "id": 2, 
                "title": "Sample title2"
            },
            {
                "id": 3, 
                "title": "Sample title3"
            }
        ]
    }
}

The id of the book selected is held in an inputArgument.bookId.

I can complete the mapping using an xpath rule for each of the fields, however, I have to hardcode the bookId in the xpath. Instead, I need to be able to substitute the actual id for the one provided (and available in the inputArgument).

xpath for title

/account/books/book[child::id=1]/title

I have tried adding MEL to replace the id and various other fixes but nothing seems to work. Is there a way to substitute the bookId field.

Note: Due to client restrictions, I cannot use DataWeave.

Priya
  • 1,359
  • 6
  • 21
  • 41
user2294382
  • 871
  • 3
  • 11
  • 25
  • Can you try for-each to /account/books/book. Then for each payload get the value of each param. The json is just a straight forward just create a POJO then transform object to json transformer after doing the mapping from the for-each payload. – Ralph Rimorin Mar 22 '16 at 17:40
  • Thanks Ralph. I didn't quite understand the bit about "get the value of each param" - could you provide a bit more information? – user2294382 Mar 29 '16 at 13:17
  • I mean when you iterate to the /account/books/ using foreach, then you can get each book item. Inside the foreach you can transform to json then do something like #[payload.id], #[payload.title] – Ralph Rimorin Mar 29 '16 at 14:34

3 Answers3

0

Using dataweave, you can do something like this.

<dw:transform-message metadata:id="0ce877a9-29ed-401b-bd54-b90d42a1609f" doc:name="Transform Message">
                <dw:set-payload><![CDATA[%dw 1.0
    %var bookId = "1"
    %var account = payload.account
    %var books = payload.account.books
    %output application/json
    ---
    {
        person : {
            accountNumber: account.accountNumber,
            selectedBooks: (books.*book map {
                id : $.id,
                title: $.title
            } filter $.id == bookId)[0],
            otherBooks: books.*book map {
                id : $.id,
                title: $.title
            } filter $.id != bookId
        }
    }]]></dw:set-payload>
            </dw:transform-message>
Manik Magar
  • 1,403
  • 2
  • 10
  • 20
Arden Vallente
  • 216
  • 1
  • 1
-1

You should use the Group By operation to transform your XML file into required JSON format. you can do something like this:

Example of DataWeave Transformation:

%dw 1.0
%output application/dw
---
classrooms: payload.school.teachers groupBy $.subject mapObject ((teacherGroup, subject) -> {
    class: {
      name: subject,
      teachers: { (teacherGroup map {
        teacher:{
            name: $.name,
            lastName: $.lastName
        }
      }) },
      attendees: { (payload.school.students filter ($.*hobby contains subject) map {
        attendee: {
          name: $.name,
          lastName: $.lastName
        }
      }) }
    }
})
-1
In Case of Mule in case of single XML element convert to Array 

xml files : 

<usrId>10120</usrId>

IN Rule file use double dot($..usrId) instead ofsinfle ($.usrId) it will revert array element for single element.

RULE FILE:
<parameter parameter_name_client="$..usrId"
parameter_name_server="facture_ids" format_required="false"
data_type="Array" value_change_required="false"
is_TLV="false" is_mandatory="false" to_be_logged="false"/>