Reputation: 793
I have XML saved into a column in a table as type nvarchar
. Now I need to parse data from that xml
. I do
SELECT
CONVERT(XML, columnX).value('(chatTranscript/message/msgText/text())[1]', 'nvarchar(max)')
as chat but I get only first value. How do I extract all into single line? XML can be long, depends on chat length.
I need to get userNick
and then msgText
and loop it till the end. Something like this:
userX:Hello<>userY:How are you;
XML:
<?xml version="1.0"?>
<chatTranscript startAt="2020-07-30T11:00:12Z" sessionId="......">
<newParty userId="......" timeShift="0" visibility="ALL" eventId="1">
<userInfo personId="" userNick="userX"/>
</newParty>
<message userId="..." timeShift="12" visibility="ALL" eventId="9">
<msgText msgType="text">Hello</msgText>
</message>
<newParty userId="..." timeShift="15" visibility="ALL" eventId="10">
<userInfo userNick="userY"/>
</newParty>
<message userId="..." timeShift="29" visibility="ALL" eventId="12">
<msgText treatAs="NORMAL">how are you?</msgText>
</message>
<partyLeft userId="..." timeShift="36" visibility="ALL" eventId="13" askerId="...">
<reason code="1">left with request to close if no agents</reason>
</partyLeft>
<partyLeft userId="..." timeShift="36" visibility="ALL" eventId="14" askerId="...">
<reason code="4">removed by other party</reason>
</partyLeft>
</chatTranscript>
Upvotes: 0
Views: 426
Reputation: 793
Here is my solution:
ALTER FUNCTION [dbo].[fn_parse_chat_xml] (@xml XML)
RETURNS NVARCHAR(MAX)
BEGIN
DECLARE @n INT, @content NVARCHAR(MAX), @userId NVARCHAR(200), @userNick1 NVARCHAR(200), @userNick2 NVARCHAR(200), @userNickX NVARCHAR(200)
SET @n = 1
SET @userId = @xml.value('(chatTranscript/newParty/@userId)[1]', 'nvarchar(max)')
SET @userNick1 = @xml.value('(chatTranscript/newParty/userInfo/@userNick)[1]', 'nvarchar(max)')
SET @userNick2 = @xml.value('(chatTranscript/newParty/userInfo/@userNick)[2]', 'nvarchar(max)')
WHILE DATALENGTH(@xml.value('(chatTranscript/message/msgText/text())[sql:variable("@n")][1]', 'nvarchar(max)'))>0
BEGIN
IF @userId = @xml.value('(chatTranscript/message/@userId)[sql:variable("@n")][1]', 'nvarchar(max)')
SET @userNickX = @userNick1
else
SET @userNickX = @userNick2
SET @content = concat(@content, ' <> ', @userNickX, ': ', @xml.value('(chatTranscript/message/msgText/text())[sql:variable("@n")][1]', 'nvarchar(max)'))
SET @n = @n + 1
END
RETURN @content
END
Upvotes: 0
Reputation: 352
You need code to do this cleanly. Trying to do what you are asking will be super messy T-SQL. I'd recommend parsing the xml in code to generate what you want based on that xml. You could also create a CLR function using code so that you can create a SQL function to do this. You can do some amazing things with XQuery and T-SQL, but sometimes it just gets to messy. For xml manipulation all within the database, CLR functions are perfect.
Upvotes: 1