Convert xml to csv using dataweave 2.0 - mule

I have a person.xml,
<?xml version="1.0" encoding="UTF-8"?>
<person>
<firstName>First Name</firstName>
<lastName>Last Name</lastName>
</person
I have person.xsd,
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="person">
<xs:complexType>
<xs:sequence>
<xs:element name="firstName" type="xs:string"/>
<xs:element name="lastName" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
I need to convert it to person.csv,
firstName,lastName
First Name,Last Name
I am using Anypoint Studio 7.3 on windows 10,
I am using a Listener, Read (file) xml.
See Transform Message dw below,
%dw 2.0
output application/csv separator=",", header=true
---
payload
I am getting the following message on executing the flow,
"Cannot coerce Object { encoding: UTF-8, mediaType: text/xml; charset=UTF-8, mimeType: text/xml, raw: org.mule.weave.v2.el.SeekableCursorStream#2fdc554d } ({person: {firstName: "Shahjahan",lastName: "Ravjee"}} as Object {encoding: "U...) to Array, while writing CSV at payload." evaluating expression: "%dw 2.0
output application/csv separator=",", header=true
---
payload
".

The problem is, as the error message is stating, you're trying to convert an object into an array. This is a problem because in order to make a CSV, you need an array of arrays, or an array of objects.
You can see if you're currently outputting an object or array by setting your output to application/dw.
%dw 2.0
output application/dw
---
payload
This will give you the following, which as you can see is an object:
{
person: {
firstName: "First Name",
lastName: "Last Name"
}
}
CSV needs an array, so we'll need to do a little transformation to get it to this:
[
{
firstName: "First Name",
lastName: "Last Name"
}
]
If you set the following script to output application/dw, you'll see that it outputs the above. At this point, you can be sure you have the correct format needed to create a CSV (array of objects, in this case), so switch it back to output application/csv and you should be good to go:
%dw 2.0
output application/csv
---
payload pluck($)

The following dw seems to have worked like a charm,
%dw 2.0
output application/csv headerLineNumber = 0 , header = true
---
[{
firstName: payload.person.firstName,
lastName: payload.person.lastName
}
]

Related

why Multipart/form-data removing Nill in response Mule Dataweave

Please find my request having tag <Date xsi:nil="true"/> when it crosses the Multipart/form-data dataweave it is removing the xsi:nil="true part which is not expected in my scenario. I wanted that to be out as the same.
Also it is removing the namespace which is not the expected case. If i trying declaring ns xsi http://www.w3.org/2001/XMLSchema-instance in the first dataweave. In the response root element it is prefixing xsi:Locations.
Im struggling with this.
Wanted the response as mentioned below, whatever the input is same should come out without altering.
Using writeNilOnNull=true is putting nill on all the fields which i dont want either, wanted only for date.
Could anyone help on this. Thank you.
Input:
<Locations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Location>
<Id>2</Id>
<CarId>78</CarId>
<Packages>1</Packages>
<Date xsi:nil="true"/>
</Location>
</Locations>
Expected Response:
<Locations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Location>
<Id>2</Id>
<CarId>78</CarId>
<Packages/>
<Date xsi:nil="true"/>
</Location>
</Locations>
Flow:
<flow name="question" doc:id="8c836a85-9d0a-47a8-8e5a-f670b16f91eb" >
<http:listener doc:name="Listener" doc:id="52ffdb08-9587-4cb2-8232-9467e85ea0dc" config-ref="HTTP_Listener_config" path="/question"/>
<ee:transform doc:name="Transform Message" doc:id="da995adf-196b-4c7b-a265-874f059ed1bb" >
<ee:message >
<ee:set-payload ><![CDATA[%dw 2.0
output application/xml
---
payload]]></ee:set-payload>
</ee:message>
</ee:transform>
<ee:transform doc:name="Transform Message" doc:id="75e5d876-855e-4d38-8468-3484c859f36e" >
<ee:message >
<ee:set-payload ><![CDATA[%dw 2.0
output multipart/form-data
---
{
"parts": {
"file": {
"headers": {
"Content-Disposition": {
"name": "file",
"filename": "",
"subtype": "form-data"
},
"Content-Type": "application/xml"
},
"content": payload
}
}
}]]></ee:set-payload>
</ee:message>
</ee:transform>
</flow>
</mule>
Add writeNilOnNull=true on your transformation. Like this
%dw 2.0
var x=read('<Locations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Location>
<Id>2</Id>
<CarId>78</CarId>
<Packages>1</Packages>
<Date xsi:nil="true"/>
</Location>
</Locations>','application/xml')
output application/xml writeNilOnNull=true
---
x

Mule ESB Transform Message xml conversion

I am facing one issue while xml format conversion in mule transform message.
I am having one input xml file.
and I have to convert the input xml to output xml where the node structure is different and node names are different.
I used data transform message for this conversion, But at one point, it is showing expected format is object and found string.
Can any one please help me for the same.
"Type mismatch
found :name, :string
required :name, :object (com.mulesoft.weave.mule.exception.WeaveExecutionException). Message payload is of type: WeaveMessageProcessor$WeaveOutputHandler"
input payload
<?xml version="1.0" encoding="utf-8"?>
<AGREEMENT>
<details>
<newTransaction>N</newTransaction>
<type>ddd</type>
</details>
</AGREEMENT>
output Payload
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<TestHeader xmlns="TestWebService">
<Username>aaa</Username>
<Password>aaa</Password>
</TestHeader>
</soap:Header>
<soap:Body>
<AGRMNT>
<testId>
<_-Test_Agrmnt- SEGMENT="1">
<transaction>N</transaction>
</__-Test_Agrmnt->
</testId>
</AGRMNT>
</soap:Body>
</soap:Envelope>
DataWeave code
%dw 1.0
%output application/xml
%namespace soap http://schemas.xmlsoap.org/soap/envelope/
{
soap#Envelope: {
soap#Body: {
AGREEMENT: {
testId: {
'_-Test_Agrmnt-': {
transaction: payload.AGREEMENT.details.newTransaction as :string
}
}
}
}}
I have got following output with your input and script
<?xml version='1.0' encoding='UTF-8'?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<AGREEMENT>
<testId>
<_-Test_Agrmnt->
<transaction>N</transaction>
</_-Test_Agrmnt->
</testId>
</AGREEMENT>
</soap:Body>
</soap:Envelope>
The only change is adding --- in script
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/xml
%namespace soap http://schemas.xmlsoap.org/soap/envelope/
---
{
soap#Envelope: {
soap#Body: {
AGREEMENT: {
testId: {
'_-Test_Agrmnt-': {
transaction: payload.AGREEMENT.details.newTransaction as :string
}
}
}
}}}]]>
</dw:set-payload>
</dw:transform-message>

Looping in DataWeave in MuleSoft

i have a requirement where in i need to extract the LoadReferenceNumber and assign to a variable which is initiated inside the data weave when the LoadReferenceNumberType is MB in mule, below is the xml
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<CIS>
<LoadReferenceNumberList>
<LoadReferenceNumberType>MB</LoadReferenceNumberType>
<LoadReferenceNumber>8070296</LoadReferenceNumber>
</LoadReferenceNumberList>
<LoadReferenceNumberList>
<LoadReferenceNumberType>ACT_SP_DATE</LoadReferenceNumberType>
<LoadReferenceNumber>20160404T14:12:00</LoadReferenceNumber>
</LoadReferenceNumberList>
<LoadReferenceNumberList>
<LoadReferenceNumberType>SP_DATE</LoadReferenceNumberType>
<LoadReferenceNumber>20170404T14:12:00</LoadReferenceNumber>
</LoadReferenceNumberList>
</CIS>
The example below is a dataweave component which extract the LoadReferenceNumber from LoadReferenceNumberList where LoadReferenceNumberType == 'MB':
<dw:set-variable variableName="LoadReferenceNumber"><![CDATA[%dw 1.0
%output application/java
---
value: ((payload.CIS.*LoadReferenceNumberList filter $.LoadReferenceNumberType == 'MB')[0].LoadReferenceNumber) default null]]></dw:set-variable>
</dw:transform-message>
The result is a LinkedHashMap, the example below is logger which logs the LoadReferenceNumber:
<logger message="#[flowVars.LoadReferenceNumber.value]" level="INFO"
doc:name="Logger" />
Hope this helps :)
you use that data weave
%dw 1.0
%output application/java
---
value: ((payload.CIS.*LoadReferenceNumberList filter $.LoadReferenceNumberType == 'MB')[0].LoadReferenceNumber) default null

Output Encoding issue in mule esb

I have used to do create XML using "Transform Message" Node in Mule ESB.
%dw 1.0
%output application/xml
item: {
name: payload."profile_name",
id: payload."profile_Id"
}
This shown a preview of output xml as
<?xml version='1.0' encoding='windows-1252'?>
<item>
<name>
<profile_name>????</profile_name>
</name>
<id>
<profile_Id>1</profile_Id>
</id>
</item>
This resulted encoding as 'windows-1252' how can i change encoding as 'UTF-8' in my outpout xml ?
Go to your Anypoint Studio folder.
Edit AnypointStudio.ini
Add:
-Dfile.encoding=UTF-8
Restart
Easy, define encoding in the output line:
%dw 1.0
%output application/xml encoding="utf-8"
---
name: payload.name?
the result:
<?xml version='1.0' encoding='utf-8'?>
<name>false</name>
For dataweave in runtime above 3.8.4 I implemented this solution:
set output as variable:
Output FlowVar - fv_itemName_xml
inside of Transform Message:
'%output application/xml writeDeclaration=false
item: { name: payload."profile_name", id: payload."profile_Id" }
and output will be:
<item>
<name>
<profile_name>????</profile_name>
</name>
<id>
<profile_Id>1</profile_Id>
</id>
</item>
Then define a variable as below:
Name: fv_outputName_xml
Value: #[flowVars.fv_itemName_xml]
Encoding: ISO 10646/Unicode(UTF-8)
Mime type: application/xml
And you have better control of Encoding and Mime type.
In my case I was need to feed that into Stored Procedure and without this workarround constantly receiving error:
System.Data.SqlClient.SqlException (0x80131904): XML parsing: line 1,
character 39, unable to switch the encoding

HTTPClient.PostAsync<T> with XmlMediaTypeFormatter serialization attributes being ignored

I'm working with an existing xsd which looks something like this (shortened for brevity):
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://www.mycompany.com/Widgets"
xmlns="http://www.mycompany.com/Widgets"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="Widget" type="WidgetDefinition" />
<xs:complexType name="WidgetDefinition">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
When you run this through xsd.exe, you get a class definition like:
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.mycompany.com/Widgets")]
[System.Xml.Serialization.XmlRootAttribute("Widget", Namespace="http://www.mycompany.com/Widgets", IsNullable=false)]
public partial class WidgetDefinition {
private string nameField;
public string Name {
get {
return this.nameField;
}
set {
this.nameField = value;
}
}
}
Fast forward ... I'm using HTTPClient to POST to a REST service. The code here is pretty straightforward.
var widget = new WidgetDefinition();
// do something here to hydrate widget
var httpClient = new HttpClient();
return httpClient.PostAsync<WidgetDefinition>(
uri, terminatedCall, new XmlMediaTypeFormatter());
On the receiving end, I want to take the request payload and convert it back to a WidgetDefinition object. If you examine the request content using:
request.Content.ReadAsStringAsync().Result
The xml looks like:
<WidgetDefinition xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://schemas.datacontract.org/2004/07/\">
...
Based on the XmlTypeAttribute and XmlRootAttribute attributes on the generated WidgetDefinition class, I expect this to look like:
<Widget xmlns:i=\"http://www.mycompany.com/Widgets\">
...
It appears that the XmlTypeAttribute and XmlRootAttribute attributes are ignored when the serialization is happening on the sending side.
Any clue what could be causing this?
EDIT: If I serialize this manually using XmlSerializer, it obeys the serialization attributes on the WidgetDefinition class. I think my issue has to do with the formatter being passed to the PostAsync call.
From this xmlns=\"http://schemas.datacontract.org/2004/07/\" it appears that your REST service is configured to use DataContractSerializer (the default in a WCF service) and not XmlSerializer.
You can configure your service to use XmlSerializer instead which should at least get you further along:
http://msdn.microsoft.com/en-us/library/ms733901.aspx