I'm trying to figure out the syntax for modifying the value of an xml variable conditionally. If this were a table, it would be easy because I would just use a WHERE clause to specify which of multiple nodes I want to update. But when all I have is a variable, I use the SET command to do the modify, and that doesn't allow a WHERE clause.
Example:
DECLARE @xml xml = '
<Container>
<Collection>
<foo>One</foo>
<bar>true</bar>
<baz>false</baz>
</Collection>
<Collection>
<foo>Two</foo>
<bar>true</bar>
<baz>true</baz>
</Collection>
<Collection>
<foo>Three</foo>
<bar>true</bar>
<baz>true</baz>
</Collection>
</Container>
'
SELECT node.value('(foo/text())[1]', 'varchar(10)') AS Item,
node.value('(bar/text())[1]', 'varchar(10)') AS IsBar,
node.value('(baz/text())[1]', 'varchar(10)') AS IsBaz
FROM @xml.nodes('/*/Collection') t(node)
So I have two questions I can't seem to figure out the syntax for:
1) I want to modify JUST the 'two' mode so that 'IsBar' is false, while not touching the value of 'IsBar' for the other nodes.
2) I want to, in one statement, update all "IsBar" values to "false".
I can't find the right magic incantation for (1), and for (2) if I try the obvious, I get an error that replace can only update at most one node.
For (1) I've tried this, and it doesn't modify anything (though it doesn't give me any error), so I'm clearly missing something obvious in my pathing:
SET @xml.modify('replace value of ((/*/Collection)[(foo/text())[1] = "Two"]/bar/text())[0] with "false"')
For (2), I want something like this, but it just gives an error:
SET @xml.modify('replace value of (/*/Collection/bar/text()) with "false"')
XQuery [modify()]: The target of 'replace' must be at most one node, found 'text *'
I googled around and simply couldn't find anyone trying to update an xml variable conditionally (or all nodes at once). And frankly, I'm clearly doing something wrong because none of my attempts have ever modified the @xml variable values, so I just need another set of eyes to tell me what I'm getting wrong.