How to Concatenate multiple repetitive nodes into a single node - BizTalk - dictionary

I have something like this in an input XML
<OrderText>
<text_type>0012</text_type>
<text_content>Text1</text_content>
</OrderText>
<OrderText>
<text_type>ZT03</text_type>
<text_content>Text2</text_content>
</OrderText>
The above data I need to map after concatenating as the below schema
<Order>
<Note>0012:Text1#ZT03:Text2</Note>
</Order>
Can anyone please help?

I'm going to assume that your input actually has a Root node, as otherwise it is not valid XML.
<Root>
<OrderText>
<text_type>0012</text_type>
<text_content>Text1</text_content>
</OrderText>
<OrderText>
<text_type>ZT03</text_type>
<text_content>Text2</text_content>
</OrderText>
</Root>
Then all you need is a map like this
With a String Concatenate functoid with
Input[0] = text_type
Input[1] = :
Input[2] = text_content
Input[3] = #
That goes into a Cumulative Concatenate
This will give you an output of
<Order>
<Note>0012:Text1#ZT03:Text2#</Note>
</Order>
Note: There is a extra # at the end, but you could use some more functoids to trim that off if needed.

You can use the Value-Mapping Flattening functoid in a map, then feed the result of each into a Concatenate functoid to generate the result string. The map can be executed on a port or in an orchestration.

Related

How to filter on dictionary with multiples keys

I have a dictionnary with double key which look like this:
{('Year', 'prix'): 130546.87449454193,
('Year', 'departement'): 11591.47409694357,
('Year', 'annee'): 34.28496633835407,
('Year', 'kilometrage'): 414330.13854019763,
('price', 'prix'): 324162.66684322944,
('price', 'departement'): 466290.81724082783,
('price', 'annee'): 454736.63137143303,
('price', 'kilometrage'): 117557.09720242623}
I want to filter only on the first part of my key which is a tuple. In other words I want to get this result if I specify in my code 'Year':
{('Year', 'prix'): 130546.87449454193,
('Year', 'departement'): 11591.47409694357,
('Year', 'annee'): 34.28496633835407,
('Year', 'kilometrage'): 414330.13854019763}
I reached my result, but only after multiple lines of code. I am wondering if there is a way to do it smoothly.
Thanks in advance
You can use dict comprehension:
# Suppose you have your dict stored in dct
# The line below returns a filtered dictionary, including keys with first tuple element 'Year'
{key: dct[key] for key in dct.keys() if key[0]=='Year'}

How to add a value to the existing element value and return it as a new value

This is the xml file.
<?xml version="1.0" encoding="UTF-8"?>
<root>
<AtcoCode> System-Start-Date= 2018-05-16T12:35:48.6929328-04:00, " ", System-End-Date = 9999-12-31, " ", 150042010003</AtcoCode>
<NaptanCode>esxatgjd</NaptanCode>
<PlateCode>
</PlateCode>
<CleardownCode>
</CleardownCode>
<CommonName>Upper Park</CommonName>
<CommonNameLang>
</CommonNameLang>
<ShortCommonName>
</ShortCommonName>
<ShortCommonNameLang>
</ShortCommonNameLang>
<Landmark>Upper Park</Landmark>
<LandmarkLang>
</LandmarkLang>
<Street>High Road</Street>
<StreetLang>
</StreetLang>
<Crossing>
</Crossing>
<CrossingLang>
</CrossingLang>
<Indicator>adj</Indicator>
<IndicatorLang>
</IndicatorLang>
<Bearing>NE</Bearing>
<NptgLocalityCode>E0046286</NptgLocalityCode>
<LocalityName>Loughton</LocalityName>
<ParentLocalityName>
</ParentLocalityName>
<GrandParentLocalityName>
</GrandParentLocalityName>
<Town>Loughton</Town>
<TownLang>
</TownLang>
<Suburb>
</Suburb>
<SuburbLang>
</SuburbLang>
<LocalityCentre>1</LocalityCentre>
<GridType>U</GridType>
<Easting>541906</Easting>
<Northing>195737</Northing>
<Co-ordinates>51.64255,0.04944</Co-ordinates>
<StopType>BCT</StopType>
<BusStopType>MKD</BusStopType>
<TimingStatus>OTH</TimingStatus>
<DefaultWaitTime>
</DefaultWaitTime>
<Notes>
</Notes>
<NotesLang>
</NotesLang>
<AdministrativeAreaCode>080</AdministrativeAreaCode>
<CreationDateTime>2006-11-06T00:00:00</CreationDateTime>
<ModificationDateTime>2010-01-16T07:58:02</ModificationDateTime>
<RevisionNumber>5</RevisionNumber>
<Modification>rev</Modification>
<Status>act</Status>
</root>
How to achieve this?
Question: Create the path range index for the status element and fetch all the documents that has status del
after fetching all the documents, you need to create the new element called currentreservationnumber under RevisionNumber element.
The value of the currentrevisionnumber will be +1 to the RevisionNumber.
I think the warning about sequential numbers is related to system-wide unique numbers/ids (like Oracle sequence), so not a worry in this case?
If you only ever have one RevisionNumber, and you can find it without a path index, you can maybe get by with element-value query on the RevisionNumber since it's already indexed.
Given that you get the document somehow, it could be as simple as:
let $doc := fn:doc ('/foo.xml')
let $rev-node := $doc/root/RevisionNumber
return xdmp:node-insert-after ($rev-node, <currentreservationnumber>{$rev-node + 1}</currentreservationnumber>)
though remember to consider locking if you are doing a big query/update. And you might need to switch to node-replace if there is already a currentreservationnumber.

XQuery "flattening" an element

I am extracting data from an XML file and I need to extract a delimited list of sub-elements. I have the following:
for $record in //record
let $person := $record/person/names
return concat($record/#uid/string()
,",", $record/#category/string()
,",", $person/first_name
,",", $person/last_name
,",", $record/details/citizenships
,"
")
The element "citizenships" contains sub-elements called "citizenship" and as the query stands it sticks them all together in one string, e.g. "UKFrance". I need to keep them in one string but separate them, e.g. "UK|France".
Thanks in advance for any help!
fn:string-join($arg1 as xs:string*, $arg2 as xs:string) is what you're looking for here.
In your currently desired usage, that would look something like the following:
fn:string-join($record/details/citizenships/citizenship, "|")
Testing outside your document, with:
fn:string-join(("UK", "France"), "|")
...returns:
UK|France
Notably, ("UK", "France") is a sequence of strings, just as a query returning multiple citizenships would likewise be a sequence (the entries in which will be evaluated for their string value when passed to fn:string-join(), which is typed as taking a sequence of strings for its first argument).
Consider the following (simplified) query:
declare context item := document { <root>
<record uid="1">
<person>
<citizenships>
<citizenship>France</citizenship>
<citizenship>UK</citizenship>
</citizenships>
</person>
</record>
</root> };
for $record in //record
return concat(fn:string-join($record//citizenship, "|"), "
")
...and its output:
France|UK

XQuery To Select Related Node

Given the below XML, what would be the proper SQL XQuery to retrieve the SubscriberStatus where the SubscriberID is empty? Given the XML is stored in a column with the XML datatype.
<ObjectEntry>
<Key>Key1</Key>
<DicValue>
<ObjectEntry>
<Key>SubscriberStatus</Key>
<Value xsi:type="xsd:string">Active</Value>
<DicValue />
</ObjectEntry>
<ObjectEntry>
<Key>SubscriberID</Key>
<Value xsi:type="xsd:string" />
<DicValue />
</ObjectEntry>
</DicValue>
</ObjectEntry>
Try this:
If $node holds your xml fragment then
$node//ObjectEntry[DicValue/ObjectEntry[Key eq "SubscriberStatus"] and DicValue/ObjectEntry[Key eq "SubscriberID"][Value ne ""]]
will give you back the ObjectEntry parent for the non empty SubscriberIDs
This is a simply XPath expression, there is no need for true XQuery. XPath is a subset of XQuery. Given that you want the <Value/> element of the SubscriberStatus you can get it like the following:
//ObjectEntry/DicValue[ObjectEntry[Key = "SubscriberID"]/Value = ""]/ObjectEntry[Key = "SubscriberStatus"]/Value
This fetches all ObjectEntries which do have an empty SubscriberID and then navigates to the SubscriberStatus. If you just want the actual string, you cann append /string()
Thanks for the suggestions! Unfortunately they didn't do what I was asking, but did help me get the right syntax. Here's a solution that works.
select Request.query('//ObjectEntry/DicValue/ObjectEntry[Key = "SubscriberStatus"]/Value') as SubscriberStatus
from RequestLog
where
Request.exist('//ObjectEntry/DicValue[ObjectEntry[Key = "SubscriberID" and Value = ""]]') = 1

In Biztalk mapper how to use split array concept

Required suggestion on below part.please any one give solution.
We have mapping from 850 to FlatFile
X12/PO1Loop1/PO1/PO109 and I need to map to field VALUE which is under record Option which is unbounded.
Split PO109 into substrings delimited by '.', foreach subsring after the first, create new Option with value=substring
So in input sample we have value like 147895632qwerqtyuui.789456123321456987
Similarly the field repeats under POLoop1.
So I need to split value based on (.) then pass a value to value field under option record(unbounded).
I tried using below code snippet
public string SplitValues(string strValue)
{
string[] arrValue = strValue.Split(".".ToCharArray());
foreach (string strDisplay in arrValue)
{
return strDisplay;
}
}
But it doesn't works, and I am not really familiar with the String methods and I am not sure if there's an easy way to do this. I have a String which contains couple of values delimited with "." .
So I need to separate values based on delimiter(.) and pass value to field.
How can I do this
As I mentioned, not too clear what is your objective, but I think you want to split a node that has some kind of delimiter into multiple nodes... if so, Try this: https://seroter.wordpress.com/2008/10/07/splitting-delimited-values-in-biztalk-maps/
He is doing exactly that. Given a node with a|b|c|d as value, output multiple nodes, each containing the value after splitted by |, so node1 = a, node2 = b, node3 = c, node4 = d.

Resources