How to extract a nested array value frm XML in DataWeave and convert to CSV - anypoint-studio

I am getting this value from the database
<row>
<file_data>One</file_data>
<time_inserted>2019-01-30T10:29:20.543</time_inserted>
</row>
<row>
<file_data>two</file_data>
<time_inserted>2019-01-30T10:29:20.547</time_inserted>
</row>
<row>
<file_data>three</file_data>
<time_inserted>2019-01-30T10:29:20.550</time_inserted>
</row>
<row>
<file_data>four</file_data>
<time_inserted>2019-01-30T10:29:20.550</time_inserted>
</row>
<row>
<file_data>five</file_data>
<time_inserted>2019-01-30T10:29:20.553</time_inserted>
</row>
And I would like to output it as a CSV like this
one
two
three
four
five

I managed to solved my problem thusly:
Firstly I added a step in my logic to surround the data with a "rows" element so that it ended up looking like this:
<rows>
<row>
<file_data>One</file_data>
<time_inserted>2019-01-30T12:34:00.277</time_inserted>
</row>
<row>
<file_data>two</file_data>
<time_inserted>2019-01-30T12:34:00.277</time_inserted>
</row>
<row>
<file_data>three</file_data>
<time_inserted>2019-01-30T12:34:00.280</time_inserted>
</row>
<row>
<file_data>four</file_data>
<time_inserted>2019-01-30T12:34:00.280</time_inserted>
</row>
<row>
<file_data>five</file_data>
<time_inserted>2019-01-30T12:34:00.283</time_inserted>
</row>
</rows>
I then wrote this code to get the list output that I needed:
def responses = new XmlSlurper().parseText(xmlData)
def payload = ""
responses.row.findAll { p ->
p.file_data
}
.each { p ->
payload = payload + "${p.file_data}" + "\r\n"
}
print payload
And this outputs:
one
two
three
four
five

Hope below logic is works. please check it.
%dw 2.0
output application/java
---
payload.rows.*row map ($.file_data) reduce (($$ ++ "\n" ++ $))

Related

Query XDocument with LINQ to Return List

I have an xml String as so (shortened to only 2 Rows for ease of Testing ):
<?xml version="1.0" encoding="utf-8"?>
<DataTable Uid="DT_RetRes">
<Rows>
<Row>
<Cells>
<Cell>
<ColumnUid>AVAIL</ColumnUid>
<Value>N</Value>
</Cell>
<Cell>
<ColumnUid>ItemCode</ColumnUid>
<Value>PRODUCTID123#</Value>
</Cell>
<Cell>
<ColumnUid>Dscription</ColumnUid>
<Value>Basic Product 1 with hash</Value>
</Cell>
<Cell>
<ColumnUid>U_JOW_CMNT</ColumnUid>
<Value></Value>
</Cell>
</Cells>
</Row>
<Row>
<Cells>
<Cell>
<ColumnUid>AVAIL</ColumnUid>
<Value>Y</Value>
</Cell>
<Cell>
<ColumnUid>ItemCode</ColumnUid>
<Value>PRODUCTID234</Value>
</Cell>
<Cell>
<ColumnUid>Dscription</ColumnUid>
<Value>Basic Product 2 no hash</Value>
</Cell>
<Cell>
<ColumnUid>U_JOW_CMNT</ColumnUid>
<Value></Value>
</Cell>
</Cells>
</Row>
</Rows>
</DataTable>
I am trying to query the Xdocument to return a list of all ItemCode Values where the Value of
AVAIl is Y
My code Currently is as follows:
Dim xdoc As XDocument = XDocument.Parse(xmlString)
Dim result = xdoc.Elements("Rows").
Where(Function(x) x.Elements("ColumnUid").Value = "AVAIL" And
x.Elements("Value").Value = "Y").
Select(Function(x) x.<ItemCode>.Value).ToList
MessageBox.Show(result.Count)
However this never seems to return anything, I have Tried many variations of the Where and Select parts of the Query without Success. I am new to LINQ and can guess the query is constructed incorrectly, possibly not accessing the correct Element in the right way.
Any Help would be greatly appreciated.
I came up with this:
Dim isAvail = xDoc.<DataTable>.<Rows>.<Row>.<Cells>.
Where(Function(x) x.<Cell>.<ColumnUid>.Value = "AVAIL" AndAlso
x.<Cell>.<Value>.Value = "Y")
Dim availItemCodes = isAvail.<Cell>.
Where(Function(y) y.<ColumnUid>.Value = "ItemCode").<Value>.
Select(Function(v) v.Value)
isAvail is the list (well, IEnumerable) of <Cells> which have the desired <Cell> in them.
You can see how breaking it down into smaller statements makes it easier to work with.
An all in one approach, a more complex query admittedly,
First the XML
Dim someXML As XElement
'to load from file
' someXML=XElement.Load("path here")
'OR parse string
' someXML = XElement.Parse("string here")
'OR for testing use a literal
someXML = <DataTable Uid="DT_RetRes">
<Rows>
<Row>
<Cells>
<Cell>
<ColumnUid>AVAIL</ColumnUid>
<Value>N</Value>
</Cell>
<Cell>
<ColumnUid>ItemCode</ColumnUid>
<Value>PRODUCTID123#</Value>
</Cell>
<Cell>
<ColumnUid>Dscription</ColumnUid>
<Value>Basic Product 1 with hash</Value>
</Cell>
<Cell>
<ColumnUid>U_JOW_CMNT</ColumnUid>
<Value></Value>
</Cell>
</Cells>
</Row>
<Row>
<Cells>
<Cell>
<ColumnUid>AVAIL</ColumnUid>
<Value>Y</Value>
</Cell>
<Cell>
<ColumnUid>ItemCode</ColumnUid>
<Value>PRODUCTID234</Value>
</Cell>
<Cell>
<ColumnUid>Dscription</ColumnUid>
<Value>Basic Product 2 no hash</Value>
</Cell>
<Cell>
<ColumnUid>U_JOW_CMNT</ColumnUid>
<Value></Value>
</Cell>
</Cells>
</Row>
</Rows>
</DataTable>
Then the code
Dim ie As IEnumerable(Of String)
ie = From el In someXML.<Rows>.<Row>.<Cells>.<Cell>
Where el.<ColumnUid>.Value = "AVAIL" AndAlso el.<Value>.Value = "Y"
From item In el.Parent.<Cell>
Where item.<ColumnUid>.Value = "ItemCode"
Select item.<Value>.Value

how to delete empty namespace from child element in sql server

I am trying to delete empty namespace from the child element. I tried with following code but its not deleting
SET #xDocTemp.modify('declare default element namespace "mynamepsace";
delete /worksh/Data/row[#xmlns=""]')
xml data:
<worksh xmlns="mynamespace">
<Data>
<row r="1" ht="18">
<row xmlns="" rl="39" spans="2">
<row xmlns="" rl="39" spans="2">
</Data>
<worksh>
Expected output
<worksh xmlns="mynamespace">
<Data>
<row rl="1" ht="18">
<row rl="39" spans="2">
<row rl="39" spans="2">
</Data>
<worksh>
not sure if it's possible with modify(), but you can just replace it like
set #xDocTemp = select cast(replace(cast(#xDocTemp as nvarchar(max)), ' xmlns=""', '') as xml)

Extracting xmlsequence from another xmlsequance in SQL

I have small problem with xmlsequence. I am codding in PL-SQL (Oracle)
Let's say, my XML looks like this:
<Row name="Row1">
<Field name="Filed1">
<Value1>
</Value1>
</Field>
<Row name="Row2inRow1">
<Field name="Filed2">
<Value1>
</Value1>
</Field>
</Row>
<Row name="Row2inRow1">
<Field name="Filed2">
<Value1>
</Value1>
</Field>
</Row>
<Row name="Row1">
<Field name="Filed1">
<Value1>
</Value1>
</Field>
<Row name="Row2inRow1">
<Field name="Filed2">
<Value1>
</Value1>
</Field>
</Row>
<Row name="Row2inRow1">
<Field name="Filed2">
<Value1>
</Value1>
</Field>
</Row>
It has 2x same "Row1" which is multiplicated, what's more inside Row1 I have multiplicated "Row2inRow1".
The problem is, I would like to select values from Ro2InRow1 and from Row1, to concat them, the effect should be:
Value1 (from 1st Row1) || Value1 (from 1st Row2inRow1)
Value1(from 1st Row1) || Value1 (from 2nd Row2InRow1)
Value1 (from 2nd Row1) || Value1 (from 3rd Row2inRow1)
Value1(from 2nd Row1) || Value1 (from 4th Row2InRow1)
I've tried to code is somehow, but I can't force my query to work right:
declare
xml_data xmldata;
begin
for rec1 in(select extractvalue(value(x),'//Field[#name="Filed1"]/Value1') ValueOfField1,
from table(xmlsequence(extract(xml_data.data,'//Row[#name="Row1"]')))x )
loop
dbms_output.put_line('1 : '|| ValueOfField1);
for rec2 in(select extractvalue(value(x),'//Field[#name="Filed2"]/Value1') ValueOfField2,
from table(xmlsequence(extract(xml_data.data,'//Row[#name="Row2inRow1"]')))k ) --? What here!
loop
dbms_output.put_line('1 : '|| ValueOfField2);
end loop;
end loop;
end;
Any ideas ? :(

How to do multiple loops through XML in PL/SQL

My XML looks like this
<data>
<row>
<id>1</id>
<name>John</name>
<name>Jack</name>
</row>
<row>
<id>2</id>
<name>Scott</name>
<name>Chuck</name>
<name>Kim</name>
</row>
</data>
I would like output:
->1
-->John
-->Jack
->2
-->Scott
-->Chuck
-->Kim
My current code looks like this:
DECLARE
X XMLTYPE := XMLTYPE('<?xml version="1.0" ?>
<data>
<row>
<id>1</id>
<name>John</name>
<name>Jack</name>
</row>
<row>
<id>2</id>
<name>Scott</name>
<name>Chuck</name>
<name>Kim</name>
</row>
</data>');
BEGIN
FOR R IN (SELECT EXTRACTVALUE(VALUE(P), '/row/id/text()') AS NAME
FROM TABLE(XMLSEQUENCE(EXTRACT(X, '//data/row'))) P)
LOOP
DBMS_OUTPUT.PUT_LINE('-->' || R.NAME);
END LOOP;
END;
I would need one more loop inside a row to loop through name tag, but I don't know how to do it.
A little help would be appreciated.
I figured it by myself:
DECLARE
X XMLTYPE := XMLTYPE('<?xml version="1.0" ?>
<data>
<row>
<id>1</id>
<promet>
<name>John</name>
<name>Jack</name>
</promet>
</row>
<row>
<id>2</id>
<promet>
<name>Scott</name>
<name>Chuck</name>
<name>Kim</name>
</promet>
</row>
</data>');
BEGIN
FOR R IN (SELECT EXTRACTVALUE(VALUE(P), '/row/id/text()') AS ID,
EXTRACT(VALUE(P), '/row/promet') AS PROMET
FROM TABLE(XMLSEQUENCE(EXTRACT(X, '//data/row'))) P)
LOOP
DBMS_OUTPUT.PUT_LINE('-->' || R.ID);
FOR R1 IN (SELECT EXTRACTVALUE(VALUE(T1), '/name/text()') AS NAME
FROM TABLE(XMLSEQUENCE(EXTRACT(R.PROMET, 'promet/name'))) T1)
LOOP
DBMS_OUTPUT.PUT_LINE('-->' || R1.NAME);
END LOOP;
END LOOP;
END;

Been trying to write an xquery code that converts a flat xml to 5-level hierarchy xml file

Would like to convert the following flax xml file to 5-level hierarchy xml structure using xquery, so far the all the xquery code i have written did not work.
<data>
<row>
<Year>1999</Year>
<Quarter>8</Quarter>
<Month>5</Month>
<Week>10</Week>
<Flight>6/11/1995</Flight>
<Un>WN</Un>
<Air>193</Air>
</row>
<data>
Out result i would like:
<data>
<row>
<Year>
<value>1999</value>
<Quarter>
<value>8</value>
<Month>
<value>5</value>
<Week>10</Week>
<Flight>6/11/1995</Flight>
<Un>WN</Un>
<Air>193</Air>
</Month>
</Quarter>
</Year>
</row>
<data>
It's unclear what XQuery processor you're using, or the exact schema of the data you will need to process, but here is an example of how to transform the data, assuming each row contains a unique set of entries:
let $data :=
<data>
<row>
<Year>1999</Year>
<Quarter>8</Quarter>
<Month>5</Month>
<Week>10</Week>
<Flight>6/11/1995</Flight>
<Un>WN</Un>
<Air>193</Air>
</row>
</data>
for $row in $data/row
return
element row {
element Year {
element value { $row/Year/data() },
element Quarter {
element value { $row/Quarter/data() },
element Month {
element value { $row/Month/data() },
$row/Week,
$row/Flight,
$row/Un,
$row/Air
}
}
}
}
If you want a single element for each year/quarter/month, use this code:
<data>
<row>{
for $year in //row/Year/data()
return
<Year>{
<value>{ $year }</value>,
for $quarter in //row[Year=$year]/Quarter/data()
return
<Quarter>{
<value>{ $quarter }</value>,
for $row in //row[Year=$year and Quarter=$quarter]
return
<Month>{
<value>{ Month/data() }</value>,
$row/*[not(local-name(.) = ('Month', 'Quarter', 'Year'))]
}</Month>
}</Quarter>
}</Year>
}</row>
</data>