1

I want to loop through xml nodes in SQL Server, and create a copy of each node containing ','.

For example, for the following xml :

 declare @answerXML xml = '<answers><answer part="1">answer,test0</answer><answer part="1">answer,test1</answer></answers>'

I want to be modified to become the following :

declare @answerXML xml = '<answers><answer part="1">answer,test0</answer><answer part="1">answer, test0</answer><answer part="1">answer,test1</answer><answer part="1">answer, test1</answer></answers>'

(Each node is duplicated, and in the added node, a space is added after the comma).

I was planing in using something like this :

SELECT 
    T.ref.value('.', 'varchar(256)') AS Answer 
FROM 
    (SELECT 
         [Xml] = @answerXML.query('for $i in data(/answers/answer) 
                                   return element temp { $i }')
    ) A
CROSS APPLY
    A.Xml.nodes('/temp') T(ref) 

But no use, it seems it's too complicated.

Can anyone help in how to loop and update XML in T-SQL?

Thank you in advance,

3
  • Is this the real structure? Why do you need this? What are you trying to solve with this duplication? Commented Dec 15, 2017 at 21:01
  • Yes this is the real structure. It's an xml that stores all possible values that the user can input. So if he inputs answer,test0 or answer, test0, the input should be considered as a valid one. Commented Dec 15, 2017 at 21:06
  • 1
    I think, this design might be better with a mapping table. I'd maintain a table with all valid values and a 1:n related table with all valid aliases. In this case you can join the user's input to your alias table and find the corresponding value. Commented Dec 15, 2017 at 21:14

1 Answer 1

2

You can try to shred the XML and rebuild it from scratch:

declare @answerXML xml=
'<answers>
  <answer part="1">answer,test0</answer>
  <answer part="1">answer,test1</answer>
</answers>';

SELECT a.value(N'@part',N'int') AS [answer/@part]
      ,a.value(N'text()[1]',N'nvarchar(max)') AS [answer] 
      ,''
      ,a.value(N'@part',N'int') AS [answer/@part]
      ,REPLACE(a.value(N'text()[1]',N'nvarchar(max)'),',',', ') AS [answer] 
FROM @answerXML.nodes(N'/answers/answer') AS A(a)
FOR XML PATH(''),ROOT('answers')

The result

<answers>
  <answer part="1">answer,test0</answer>
  <answer part="1">answer, test0</answer>
  <answer part="1">answer,test1</answer>
  <answer part="1">answer, test1</answer>
</answers>
Sign up to request clarification or add additional context in comments.

8 Comments

Or shred the XML and insert into a table then query the table!
@JacobH What help / advantage would this bring? Using .nodes() there is a (volatile) derived table already...
Added the folowing condition to check if a comma exists. WHERE CHARINDEX(',',a.value(N'text()[1]',N'nvarchar(max)'))>0. Big Thanks -@Shnugo
The advantage of not having to shred and recreate the XML to store in a column each time you modify the data. But it sounds like you're happy with that process, so carry on!
@JacobH This sounds a little - uhm - supercilious... We both don't know, what the OP is doing here. If this is a one time action, if there is any need to keep this data for a second action... The main question is: Is XML the best place for this data at all? But this is the wrong place to discuss this...
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.