我想用新节点替换 XML 节点。我正在尝试使其动态化,因此替换节点名称是一个变量
DECLARE @xmlSource AS XML = '<Root><Transactions><ReplaceMe>This information should be gone</ReplaceMe></Transactions></Root>'
DECLARE @xmlInsert AS XML = '<NewNode>New Information</NewNode>'
DECLARE @NodeName NVARCHAR(500) = 'ReplaceMe'
生成的 XML 应该如下所示:
<Root><Transactions><NewNode>New Information</NewNode></Transactions></Root>
最佳答案
没有直接的方法可以用另一个节点替换一个完整的节点。
但是你可以删除它并插入新的:
DECLARE @xmlSource AS XML = '<Root><Transactions><ReplaceMe>This information should be gone</ReplaceMe></Transactions></Root>'
DECLARE @xmlInsert AS XML = '<NewNode>New Information</NewNode>'
DECLARE @NodeName NVARCHAR(500) = 'ReplaceMe'
SET @xmlSource.modify('delete /Root/Transactions/*[local-name(.) eq sql:variable("@NodeName")]');
SELECT @xmlSource; --ReplaceMe is gone...
SET @xmlSource.modify('insert sql:variable("@xmlInsert") into (/Root/Transactions)[1]');
SELECT @xmlSource;
结果
<Root>
<Transactions>
<NewNode>New Information</NewNode>
</Transactions>
</Root>
更新通用解决方案
根据您的评论,我了解到您对 XML 一无所知,只需要用另一个节点替换您知道名称的一个节点...
这个解决方案是基于字符串的(无论如何都非常丑陋)并且有一些缺陷:
- 如果有多个节点同名,则只取第一个
- 如果节点多次存在且内容相同,则两处都替换
- 如果您的 xml 包含
CDATA
部分,它们将被隐式地转移到正确转义的普通 XML 中。没有语义损失,但这可能会破坏结构验证...
即使是特殊字符,这也应该有效,因为所有的转换都是从 XML 到 NVARCHAR
并返回。转义字符应在两侧保持相同。
否则必须使用递归方法来获取节点的完整路径并动态构建我的第一个语句。这更干净但更重...
DECLARE @xmlSource AS XML = '<Root><Transactions><ReplaceMe>This information should be gone</ReplaceMe></Transactions></Root>'
DECLARE @xmlInsert AS XML = '<NewNode>New Information</NewNode>'
DECLARE @NodeName NVARCHAR(500) = 'ReplaceMe'
SELECT
CAST(
REPLACE(CAST(@xmlSource AS NVARCHAR(MAX))
,CAST(@xmlSource.query('//*[local-name(.) eq sql:variable("@NodeName")][1]') AS NVARCHAR(MAX))
,CAST(@xmlInsert AS NVARCHAR(MAX))
)
AS XML)
关于sql-server - T-SQL 替换 XML 节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39626227/