Reputation: 95
I'm writing an application that will send XML-formatted data to a third-party client. There are 34 sub-flows for me to write, and I want to focus on splitting Transforms into code that can be reused.
This is what a transaction I'm SENDING to my third-party will look like:
<request>
<control>
<senderid>{{sender_id}}</senderid>
<password>{{sender_password}}</password>
<controlid>{{$timestamp}}</controlid>
<uniqueid>false</uniqueid>
<dtdversion>3.0</dtdversion>
<includewhitespace>false</includewhitespace>
</control>
<operation>
<authentication>
<sessionid>{{temp_session_id}}</sessionid>
</authentication>
<content>
<function controlid="{{$guid}}">
---CONTENT---
</function>
</content>
</operation>
</request>
My thought was that I could separate these into separate Transforms and add them together. I don't think I can explicitly write XML in Mule 4, so I've split the JSON out individually into the below calls and am relying on Dataweave's XML translation:
Root:
%dw 2.0
output application/xml
---
{
"request":
{
"control":
{
"senderid": Mule::p("secure::finance.sender.id"),
"password" : Mule::p("secure::finance.sender.password"),
"controlid" : now(),
"uniqueid": Mule::p("secure::finance.uniqueid"),
"dtdversion" : Mule::p("secure::finance.dtdversion"),
"includewhitespace": Mule::p("secure::finance.includewhitespace")
}
}
}
Auth:
%dw 2.0
output application/xml
---
{
"operation":
{
"authentication":
{
"login":
{
"sessionid" : vars.sessionId
}
}
}
}
Content (example):
"content":
{
"function controlid":
{
"create_ictransaction":
{
"datecreated":
{
"year": now().year,
"month": now().month,
"day": now().day
}
}
}
}
I'm not able to set the "Content" as a node after the "Auth" and nested within the "Root" of my final Transform.
How would I make this so I would only have to reference the "Root" and "Auth" and would actually be setting the "Content" within my flows? It doesn't have to be Transforms in Dataweave, if there is another solution.
Expected output would be that I can call the Root and Auth, then specifically define the JSON for the XML within the other Transforms. This would help reduce the length of the code.
Like this:
[Root]
[Auth]
"content":
{
"function controlid":
{
"create_ictransaction":
{
"datecreated":
{
"year": now().year,
"month": now().month,
"day": now().day
}
}
}
}
[Root ending to encapsulate call]
EDIT: I'm thinking this isn't possible in Dataweave.
Upvotes: 0
Views: 794
Reputation: 1296
You can achieve that using the following DataWeave Expression:
%dw 2.0
output application/xml //replace with application/json for a JSON output
---
{
"request": {
"control": {
"senderid": 'sid1', // replace with Mule::p("secure::finance.sender.id"),
"password" : 'somepassword', // replace with Mule::p("secure::finance.sender.password"),
"controlid" : now(),
"uniqueid": "someuid", // replace with Mule::p("secure::finance.uniqueid"),
"dtdversion" : "somedtdver", // replace with Mule::p("secure::finance.dtdversion"),
"includewhitespace": "true" // replace with Mule::p("secure::finance.includewhitespace")
},
"operation": {
"authentication": {
"login": {
"sessionid" : '123' //replace with vars.sessionId
}
}
},
"content": payload.content
}
}
Given the following XML input payload:
<content>
<function controlid="{{$guid}}">
<read>
<object>ARPYMT</object>
<keys>1</keys>
<fields>*</fields>
</read>
</function>
</content>
The resulting output payload will be:
XML output:
<?xml version='1.0' encoding='UTF-8'?>
<request>
<control>
<senderid>sid1</senderid>
<password>somepassword</password>
<controlid>2021-06-10T20:52:08.225041Z</controlid>
<uniqueid>someuid</uniqueid>
<dtdversion>somedtdver</dtdversion>
<includewhitespace>true</includewhitespace>
</control>
<operation>
<authentication>
<login>
<sessionid>123</sessionid>
</login>
</authentication>
</operation>
<content>
<function controlid="{{$guid}}">
<read>
<object>ARPYMT</object>
<keys>1</keys>
<fields>*</fields>
</read>
</function>
</content>
</request>
JSON output:
{
"request": {
"control": {
"senderid": "sid1",
"password": "somepassword",
"controlid": "2021-06-10T20:54:25.568852Z",
"uniqueid": "someuid",
"dtdversion": "somedtdver",
"includewhitespace": "true"
},
"operation": {
"authentication": {
"login": {
"sessionid": "123"
}
}
},
"content": {
"function": {
"read": {
"object": "ARPYMT",
"keys": "1",
"fields": "*"
}
}
}
}
}
NOTE: when transforming XML to JSON, you have to define how tag attributes will be handled
Upvotes: 0
Reputation: 25699
You can either create one DataWeave script to create the entire output at once, or create parts individually as you did but writing the output as application/java and sending each part to a variable. Then you can use those values to compose the total output.
Example: If you store the Auth part in the auth variable:
%dw 2.0
output application/json
---
{
request: {
auth: vars.auth,
...
Upvotes: 1