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

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>

Related

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

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" ++ $))

XPath doesn't provide proper tag

I'm trying to get tag "" from xml below.
If i execute request like this:
WITH x(col) AS (select'<document xmlns="http://example.com/digital/back/" xmlns:ns2="http://example.com/digital/back/complexId" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="">
<header>
<docId>13a2f29a28b12ecb</docId>
<dt>2018-12-10T11:59:48.112+03:00</dt>
</header>
<pay>
<reqTransfer id="154638">
<source>
<card>
<virtualCardNum>4B74C1EE187</virtualCardNum>
<bsc>VISA</bsc>
</card>
</source>
</reqTransfer>
</pay>
</document>
'::xml)
SELECT xpath('/document/pay/reqTransfer/source/card/bsc/text()', col) AS bsc
FROM x;
I get {}, but if I relpace the document start tag
<document xmlns="http://example.com/digital/back/" xmlns:ns2="http://example.com/digital/back/complexId" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="">
with <document> or even <document xmlns="">, I get { VISA } - that is right.
What should I do to replace <document xmlns="..."> with <document> or get { VISA } without replacement?
If you are working with XML namespaces, they are worth mentioning in your Xpath queries too, i.e. use
SELECT xpath('/d:document/d:pay/d:reqTransfer/d:source/d:card/d:bsc/text()', col,
ARRAY[ARRAY['d', 'http://example.com/digital/back/']]) AS bsc
http://sqlfiddle.com/#!17/9eecb/24719
See also:
how to ignore namespaces with XPath

How to handle For each condition in Data weaver: Mule

I'm getting struggle in looping the entries in data weaver. Below is the Input and the expected response.
Not sure how to make loop(I need to get RecordEntry and each entry with 'IndividualEntry') .
Input xml : Record entry tag in input xml is 3, but I might get many. So need to make a loop as dynamic.
<?xml version="1.0" encoding="UTF-8"?>
<Records>
<storenumber />
<calculated>false</calculated>
<subTotal>12</subTotal>
<RecordsEntries>
<RecordEntry>
<deliverycharge>30.0</deliverycharge>
<entryNumber>8</entryNumber>
<Value>true</Value>
</RecordEntry>
<RecordEntry>
<deliverycharge>20.0</deliverycharge>
<entryNumber>7</entryNumber>
<Value>false</Value>
</RecordEntry>
<RecordEntry>
<deliverycharge>1.0</deliverycharge>
<entryNumber>6</entryNumber>
<Value>false</Value>
</RecordEntry>
</RecordsEntries>
</Records>
Expected Response ( I'm expecting the below response)
<?xml version="1.0" encoding="UTF-8"?>
<orders>
<order>
<StoreID />
<Total>false</Total>
<IndividualEntry>
<Number>8</Number>
<DeliverCharge>30.0</DeliverCharge>
</IndividualEntry>
<IndividualEntry>
<Number>7</Number>
<DeliverCharge>20.0</DeliverCharge>
</IndividualEntry>
<IndividualEntry>
<Number>6</Number>
<DeliverCharge>1.0</DeliverCharge>
</IndividualEntry>
</order>
</orders>
My Data weaver Transformation as below
%dw 1.0
%output application/xml
---
{
orders: {
order: {
StoreID:payload.Records.storenumber,
Total: payload.Records.calculated,
IndividualEntry: payload.Records.RecordsEntries.*RecordEntry map {
Number:$.entryNumber,
DeliverCharge:$.deliverycharge
}
}
}
}
Currently I'm getting response as below ( I don't know how to make each Record entry as a IndividualEntry tag, and also here element tag is added in extra which is not required in my case)
<?xml version="1.0" encoding="UTF-8"?>
<orders>
<order>
<StoreID />
<Total>false</Total>
<IndividualEntry>
<element>
<Number>8</Number>
<DeliverCharge>30.0</DeliverCharge>
</element>
<element>
<Number>7</Number>
<DeliverCharge>20.0</DeliverCharge>
</element>
<element>
<Number>6</Number>
<DeliverCharge>1.0</DeliverCharge>
</element>
</IndividualEntry>
</order>
</orders>
Could any one help me in fix this. Thanks in advance.
One way to do it:
orders: {
order: {
StoreID: payload.Records.storenumber,
Total: payload.Records.calculated,
(payload.Records.RecordsEntries.*RecordEntry map {
IndividualEntry: {
Number:$.entryNumber,
DeliverCharge:$.deliverycharge
}
})
}
}
Inside an object when you put an expression between parenthesis that returns an array of key-value pairs it is evaluated and used to fill the object.
See section5.1.3. Dynamic elements in https://developer.mulesoft.com/docs/dataweave

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)

Linq to XML Insert a new element into the XML for each node

I would like to insert a new element in the following XML for each instance of a data node
Here is the initial XML that I have:
<dataCollection totalCount="12" pageCount="1">
<data>
<date>2011-11-10T00:00:00.000-05:00</date>
<dataType>PRCP</dataType>
<station>GHCND:USW00014739</station>
<value>267</value>
<address>
<home>X</home>
</address>
</data>
<data>
<date>2011-11-10T00:00:00.000-05:00</date>
<dataType>PRCP</dataType>
<station>GHCND:USW00014739</station>
<value>267</value>
<address>
<home>X</home>
</address>
</data>
</dataCollection>
And this is the XML I am trying to achieve
<dataCollection totalCount="12" pageCount="1">
<data>
<date>2011-11-10T00:00:00.000-05:00</date>
<dataType>TMIN</dataType>
<station>GHCND:USW00014739</station>
<value>267</value>
<newValue>60</newValue>
<address>
<home>X</home>
</address>
</data>
<data>
<date>2011-11-10T00:00:00.000-05:00</date>
<dataType>TMAX</dataType>
<station>GHCND:USW00014739</station>
<value>270</value>
<newValue>62</newValue>
<address>
<home>X</home>
</address>
</data>
</dataCollection>
The XML data is used as a data source for a DataGrid using the following Linq.
Dim elements = (From daDsc In xdoc.Descendants("data") _
Select Data_Type = daDsc.Element("dataType").Value, _
Raw_Value = daDsc.Element("value").Value,
newValue = daDsc.Element("newValue"))
Writing this in VB.net, but answers in C# is OK. Thanks.
Try this:
foreach (var xe in xml.Descendants("data"))
{
xe.Element("value")
.AddAfterSelf(new XElement("newValue", 42));
}
If you wish to add newValue into your XML before processing, you could do something like this:
For Each element As XElement In xml.Elements
element.SetElementValue("newValue", "something")
Next
where xml is an XDocument, loaded from your web service.