I would not suggest a string based approach normally. But in this case it might be easiest to do something like this
declare @xml XML=
'<BenutzerEinstellungen>
<State>Original</State>
<VorlagenHistorie>/path/path/test123/file.doc</VorlagenHistorie>
<VorlagenHistorie>/path/path/anothertest/second.doc</VorlagenHistorie>
</BenutzerEinstellungen>';
SELECT CAST(REPLACE(CAST(@xml AS nvarchar(MAX)),'/test123/','/anothertest/') AS xml);
UPDATE
If this approach is to global you might try something like this:
I read the XML as derived table and write it back as XML. In this case you can be sure, that only Nodes with VorlageHistorie
will be touched...
SELECT @xml.value('(/BenutzerEinstellungen/State)[1]','nvarchar(max)') AS [State]
,(
SELECT REPLACE(vh.value('.','nvarchar(max)'),'/test123/','/anothertest/') AS [*]
FROM @xml.nodes('/BenutzerEinstellungen/VorlagenHistorie') AS A(vh)
FOR XML PATH('VorlagenHistorie'),TYPE
)
FOR XML PATH('BenutzerEinstellungen');
UPDATE 2
Try this. It will read all nodes, which are not called VorlagenHistorie
as is and will then add the VorlageHistorie
nodes with replaced values. The only draw back might be, that the order of your file will be different, if there are other nodes after the VorlagenHistorie
elements. But this should not really touch the validity of your XML...
declare @xml XML=
'<BenutzerEinstellungen>
<State>Original</State>
<Unknown>Original</Unknown>
<UnknownComplex>
<A>Test</A>
</UnknownComplex>
<VorlagenHistorie>/path/path/test123/file.doc</VorlagenHistorie>
<VorlagenHistorie>/path/path/anothertest/second.doc</VorlagenHistorie>
</BenutzerEinstellungen>';
SELECT @xml.query('/BenutzerEinstellungen/*[local-name(.)!="VorlagenHistorie"]') AS [node()]
,(
SELECT REPLACE(vh.value('.','nvarchar(max)'),'/test123/','/anothertest/') AS [*]
FROM @xml.nodes('/BenutzerEinstellungen/VorlagenHistorie') AS A(vh)
FOR XML PATH('VorlagenHistorie'),TYPE
)
FOR XML PATH('BenutzerEinstellungen');
UPDATE 3
Use an updateable CTE to first get the values and then set them in one single go:
declare @tbl TABLE(ID INT IDENTITY,xmlColumn XML);
INSERT INTO @tbl VALUES
(
'<BenutzerEinstellungen>
<State>Original</State>
<Unknown>Original</Unknown>
<UnknownComplex>
<A>Test</A>
</UnknownComplex>
<VorlagenHistorie>/path/path/test123/file.doc</VorlagenHistorie>
<VorlagenHistorie>/path/path/anothertest/second.doc</VorlagenHistorie>
</BenutzerEinstellungen>')
,('<BenutzerEinstellungen>
<State>Original</State>
<VorlagenHistorie>/path/path/test123/file.doc</VorlagenHistorie>
<VorlagenHistorie>/path/path/anothertest/second.doc</VorlagenHistorie>
</BenutzerEinstellungen>');
WITH NewData AS
(
SELECT ID
,xmlColumn AS OldData
,(
SELECT t.xmlColumn.query('/BenutzerEinstellungen/*[local-name(.)!="VorlagenHistorie"]') AS [node()]
,(
SELECT REPLACE(vh.value('.','nvarchar(max)'),'/test123/','/anothertest/') AS [*]
FROM t.xmlColumn.nodes('/BenutzerEinstellungen/VorlagenHistorie') AS A(vh)
FOR XML PATH('VorlagenHistorie'),TYPE
)
FOR XML PATH('BenutzerEinstellungen'),TYPE
) AS NewXML
FROM @tbl AS t
)
UPDATE NewData
SET OldData=NewXml;
SELECT * FROM @tbl;