merging / coalescing xml records - azure-logic-apps

Is it possible to do a coalesce against 2 records having the same schema?
Suppose I have 2 payloads such as:
<Person>
<Color></Color>
<First>Joe</First
<Last>Smith</Last>
<Date>1/1/2019</Date>
</Person>
And this one:
<Person>
<Color>Blue</Color>
<First></First
<Last>Smith</Last>
<Date></Date>
</Person>
Expected result:
<Person>
<Color>Blue</Color>
<First>Joe</First
<Last>Smith</Last>
<Date>1/1/2019</Date>
</Person>
How do we always take the non-empty value for a specific node?

You can transform your xml to json and use "If" condition in logic app to coalesce the two xml file. Below is the whole screenshot of my logic app.
Details:
First I upload the two xml files to azure storage blob and get them in logic app by "Get blob content" action. Then I initialize a variable named "jsonPersonString1" and use the expression to transform the blob content to json, then use "Parse JSON" action to parse it.(I post the screenshot below)
Second please do same steps as above to transform the second xml file to json and parse it.(also post the screenshot below)
Then I initialize variable named "result" and set its value as null.
After that, create a "If" condition to judge which value we should use and set the outputs to the variable "result". Here I just do the operation for the property "Color", you can also do same operation for other properties.
After complete the "If" condition, we can transform the json to xml.
Hope it would be helpful to your problem~

Related

Passing a List to an sql-component query

I'm having trouble to pass a list of string I'm getting back from my bean to my sql-component query to make a call to the database.
<bean ref="fo" method="transformTo(${body})" />
So in this upper line of code I'm taking data from the body that is an xml and transform it to json.
<bean ref="fot" method="getOTs(${body})" />
Then I'm extracting the part I want from the json and return a list of string (method signature) :
public List<String> getOTs(String jsonOTs)
Now the part that isn't working (I'm getting that one parameter is expected but there are a couple each time)
<to uri="sql:insert into dbo.table_example (OT) VALUES :#body;"/>
My goal is quite simple, retrieving a list of string from my bean (working) and making and an insert into query. I have only one parameter but multiple values. Example:
INSERT INTO table_name (column_list)
VALUES
(value_list_1),
(value_list_2),
...
(value_list_n);
Example taken from here
Bulk insert
For a bulk insert, you need to set the query parameter batch to true, this way, Camel will understand that you want to insert several rows in one batch.
Here is the corresponding to endpoint in your case:
<to uri="sql:insert into dbo.table_example (OT) VALUES (#)?batch=true"/>
Miscellaneous remarks
Actually, for all the use cases that you listed above, you have no need to explicitly refer to the body.
Indeed, in the case of a bean, you could only specify the method to invoke, Camel is able to inject the body as a parameter of your method and automatically converts it into the expected type which is String in your case.
Refers to https://camel.apache.org/manual/bean-binding.html#_parameter_binding for more details.
Regarding the SQL producer, assuming that you did not change the default configuration, the proper way is to rather use the placeholder that is # by default, Camel will automatically use the content of the body as parameters of the underlying PreparedStatement.
So you should retry with:
<to uri="sql:insert into dbo.table_example (OT) VALUES (#)"/>
If you really want to explicitly refer to the body in your query, you can rather use :#${body} as next:
<to uri="sql:insert into dbo.table_example (OT) VALUES (:#${body})"/>
Misuse of named parameter
If you only use #body as you did, Camel interprets it as a named parameter so it will try to get the value from the body if it is a map by getting the value of the key body otherwise it will try to get the value of the header body but in your case, there are no such values, therefore, you end up with an error of type
Cannot find key [body] in message body or headers to use when setting named
parameter in query [insert into developers (name) values :?body;] on the exchange

Include text in ForXMLPath query in SQL Server

I want to include a line (simple text) in ForXMLPath query as
<Cat>
but I am having difficulties.
When I try it brings in weird characters with it.
Please help.
Thanks.
select
'<Cat>'
I expect this
<Cat>
but it displays below
<Cat>
I must admit, that your question is not clear...
XML is not just some text with fancy extras, but a very strictly organised text based container for data.
A simple SELECT '<Cat>' would never return as <Cat> without a FOR XML somewhere in your query. So please show us a (reduced!) example of your full query and the expected output, best provided as MCVE (a stand-alone sample with DDL, sample data, own attempt and expected output).
Just some general remarks:
If you want to place <Cat> within your XML the whole output will be broken XML. This opening tag demands for a closing </Cat> (or - alternatively - a self-closing <Cat />)
Assumably you try to add out-written tags to your XML as you'd do it in XSLT, JS, ASP.Net or any other XML/HTML producing approach.
Assumably your solution will be a FOR XML PATH() approach without the need of an out-written tag within your XML.
Just to give you an idea:
SELECT 'test' AS [SomeElement] FOR XML PATH('SomeRowTag'),ROOT('SomeRootTag');
prouces this XML
<SomeRootTag>
<SomeRowTag>
<SomeElement>test</SomeElement>
</SomeRowTag>
</SomeRootTag>
If you want to add a <Cat> element you could use an XPath like here
SELECT 'test' AS [Cat/SomeElement] --<-- You can add nest-levels here!
FOR XML PATH('SomeRowTag'),ROOT('SomeRootTag');
The result
<SomeRootTag>
<SomeRowTag>
<Cat>
<SomeElement>test</SomeElement>
</Cat>
</SomeRowTag>
</SomeRootTag>

SQL Server: How to Get Large amount of JSON from Store Procedure

I've created one store procedure that returns the JSON. But it not return complete JSON only limited JSON returned. I used "For JSON auto" after Select statement. Have any Solution to get all JSON?
if you are using any Cast or covert operations. Use VARCHAR(MAX) instead of VARCHAR().
I have seen this issue in such cases.
Also if you are using the print output, then it is possible that the text might get truncated, but you can use the Select or Output parameter instead.
make the output parameter of type nvarchar(max)
or check this link :
Format Query Results as JSON with FOR JSON (SQL Server)
This might help
I found my solution here: https://learn.microsoft.com/en-us/sql/relational-databases/json/format-query-results-as-json-with-for-json-sql-server?view=sql-server-ver15#output-of-the-for-json-clause (same as above, but a specific section)
The issue was that I thought SQL Server was returning a single row/cell of JSON data because that is how SSMS displayed it. The truth is that it chops it into multiple rows.
I was retrieving the data in .NET using ExecuteScalar(), but I needed to use ExecuteReader(), and concatenate all rows together. Once I did that, I could deserialize the JSON without issue.

Retrieving and using the output from a "FOR JSON" query in a variable

I'm aware of the option to output a query formatted as JSON, like the following example from the from MSDN page:
SELECT name, surname
FROM emp
FOR JSON AUTO
There are a lot of samples on how to use the resulting json from apps but my question is, how can I store the resulting json in a varchar variable, let's say to store in another table?
DECLARE #Json nvarchar(MAX) = (
SELECT name, surname
FROM emp
FOR JSON AUTO
);
Dan Guzman replied in the MSDN Forum with this neat solution, which corresponds also to #FDavidov's suggestion in his last comment
A JSON is, in fact, a character string. What makes this character string to be a JSON is the combination of two things:
You refer to it as a JSON (using the correct functions within your environment),
It contains the correct delimiters at the correct locations to comply with the rules of a JSON.
So, if you want to store a JSON in a variable, just assign to the variable the source string and, whenever you want to act on your variable, just remember it is a JSON.

How to avoid in SQL to store an XML <option></option> like <option />?

When I try to store a XML in SQL than have an empty Element, SQL just change it and store it with only one tag for the element.
For Example the XML to store is:
<ROOT>
<FIRSTNAME>ROGER</FIRSTNAME>
<MIDDLENAME></MIDDLENAME>
</ROOT>
Then Sql stored it like
<ROOT>
<FIRSTNAME>ROGER</FIRSTNAME>
<MIDDLENAME />
</ROOT>
The sql update is just very simple:
UPDATE
SESIONESREPORTES
SET
SER_PARAMETROS = '
<ROOT>
<FIRSTNAME>ROGER</FIRSTNAME>
<MIDDLENAME></MIDDLENAME>
</ROOT>'
WHERE SER_ID=7
I need like this because I have some query that fails when a element is empty, you can see it here..
Merging many rows in a single
I don't think you can, looking at the following link:
XML Data Type and Columns
According to this (XML Storage Options Section):
The data is stored in an internal representation that preserves the
XML content of the data. This internal representation includes
information about the containment hierarchy, document order, and
element and attribute values. Specifically, the InfoSet content of the
XML data is preserved. For more information about InfoSet, visit
http://www.w3.org/TR/xml-infoset. The InfoSet content may not be an
identical copy of the text XML, because the following information is
not retained: insignificant white spaces, order of attributes,
namespace prefixes, and XML declaration.
So the internal storage will strip out all parts it deems unnecessary, the document goes on to state that if you need an exact copy of the XML document and not just the content, you should use either [n]varchar(max) or varbinary(max)
<MIDDLENAME></MIDDLENAME>
and
<MIDDLENAME/>
are equivalent; any XML parser will treat them identically - as an empty element. If your query fails on an empty element, it will fail on either of them. You'll need to either rewrite your query to handle empty elements, put some content in the <MIDDLENAME> element, or omit the element entirely (if your query can handle it's absence.)

Resources