Reputation: 111
I've these 2 XML which is stored in 2 tables.
Question XML
<Question>
<Choice ID="1">
<Value>Choice A</Value>
</Choice>
<Choice ID="2">
<Value>Choice B</Value>
</Choice>
<Choice ID="3">
<Value>Choice C</Value>
</Choice>
<Choice ID="4">
<Value>Choice D</Value>
</Choice>
<Choice ID="5">
<Value>Choice E</Value>
</Choice>
</Question>
Response XML
<Response>
<Question>
<Value>Choice B</Value>
<Value>Choice C</Value>
</Question>
</Response>
I need to add a new attribute called ID, to all the Value elements present in the Response XML. The value of the new ID attribute can be found in the Question XML.
For Instance, If you see the Question XML, the correct ID
of the value Choice B is 2
and Choice C is 3
So the final Response XML which i need, should be like this
<Response>
<Question>
<Value ID="2">Choice B</Value>
<Value ID="3">Choice C</Value>
</Question>
</Response>
Can someone please tell me how to do this ?
Upvotes: 1
Views: 70
Reputation: 16146
You can convert the XML to tables (question & response) and then link on the value. You then look up the ID from the question table. Example:
DECLARE @xml_q XML = N'
<Question>
<Choice ID="1">
<Value>Choice A</Value>
</Choice>
<Choice ID="2">
<Value>Choice B</Value>
</Choice>
<Choice ID="3">
<Value>Choice C</Value>
</Choice>
<Choice ID="4">
<Value>Choice D</Value>
</Choice>
<Choice ID="5">
<Value>Choice E</Value>
</Choice>
</Question>';
DECLARE @xml_r XML = N'
<Response>
<Question>
<Value>Choice B</Value>
<Value>Choice C</Value>
</Question>
</Response>';
;WITH q_id AS (
SELECT
n.c.value('(./Value)[1]','NVARCHAR(128)') AS value,
n.c.value('@ID','INT') AS id
FROM
@xml_q.nodes('//Choice') AS n(c)
),
r_v AS (
SELECT
n.c.value('(.)[1]','NVARCHAR(128)') AS value
FROM
@xml_r.nodes('//Value') AS n(c)
)
SELECT
(
SELECT
q_id.id AS "Value/@ID",
r_v.value AS "Value"
FROM
r_v
INNER JOIN q_id ON
q_id.value=r_v.value
FOR
XML PATH(''), TYPE
)
FOR
XML PATH('Question'), ROOT('Response');
Will give the response:
<Response>
<Question>
<Value ID="2">Choice B</Value>
<Value ID="3">Choice C</Value>
</Question>
</Response>
Upvotes: 1
Reputation: 67321
If you want to modify more than one place in an XML in most cases the best is to shredd the information and re-build the XML from scratch:
DECLARE @q XML=
N'<Question>
<Choice ID="1">
<Value>Choice A</Value>
</Choice>
<Choice ID="2">
<Value>Choice B</Value>
</Choice>
<Choice ID="3">
<Value>Choice C</Value>
</Choice>
<Choice ID="4">
<Value>Choice D</Value>
</Choice>
<Choice ID="5">
<Value>Choice E</Value>
</Choice>
</Question>';
DECLARE @r XML=
N'<Response>
<Question>
<Value>Choice B</Value>
<Value>Choice C</Value>
</Question>
</Response>';
WITH QuestionCTE AS
(
SELECT c.value('@ID','int') AS qID
,c.value('Value[1]','nvarchar(max)') AS qVal
FROM @q.nodes('Question/Choice') AS A(c)
)
,ResponseCTE AS
(
SELECT r.value('.','nvarchar(max)') AS rVal
FROM @r.nodes('Response/Question/Value') AS A(r)
)
SELECT
(
SELECT q.qID AS [Value/@ID]
,q.qVal AS [Value]
FROM ResponseCTE AS r
LEFT JOIN QuestionCTE AS q ON r.rVal=q.qVal
FOR XML PATH(''),TYPE
)
FOR XML PATH('Question'),ROOT('Response')
Upvotes: 2