让我说明我是XML新手。也就是说,我的问题是我有一个创建XML数据的SQL Server,并将其放入必须通过安全门到另一个服务器的文件中。该门有一个包含几个“脏”字的列表,如果包含它们将导致文件失败。我需要的是SQL搜索XML数据,每个节点以及是否存在“脏”值的方法,将其剥离(替换为空白)。 XML不是强类型的,“脏”字可能是更长字符串的一部分。在这种情况下,字符串的其余部分必须保持完整。
例如,如果“脏”字是“保持”,那么字符串“我们认为这些真理是不言而喻的”就会变成“我们这些真理是不言而喻的。”
同样,这个“脏”字可能在任何节点中,并且标签不会总是相同。我需要编写一个过程或触发器,根据脏字列表分析XML值以进行清理。
答案 0 :(得分:0)
将XML分解为一个表,每个节点都有一行。该表需要一个id,该id对应于碎片XML中节点的位置,以便能够回写更改。
将错误的单词放在表格中,并使用replace
将每个单词从表中删除,并将其与节点值一起删除。
最后,循环遍历已清理的值,并一次将它们写回到一个节点,以便实际修改的节点。
-- A table to hold the bad words
declare @BadWords table
(
ID int identity,
Value nvarchar(10)
)
-- These are the bad ones.
insert into @BadWords values
('one'),
('three'),
('five'),
('hold')
-- XML that needs cleaning
declare @XML xml = '
<root>
<itemone ID="1one1">1one1</itemone>
<itemtwo>2two2</itemtwo>
<items>
<item>1one1</item>
<item>2two2</item>
<item>onetwothreefourfive</item>
</items>
<hold>We hold these truths to be self evident</hold>
</root>
'
-- A helper table to hold the values to modify
declare @T table
(
ID int identity,
Pos int,
OldValue nvarchar(max),
NewValue nvarchar(max),
Attribute bit
)
-- Get all attributes from the XML
insert into @T(Pos, OldValue, NewValue, Attribute)
select row_number() over(order by T.N),
T.N.value('.', 'nvarchar(max)'),
T.N.value('.', 'nvarchar(max)'),
1
from @XML.nodes('//@*') as T(N)
-- Get all values from the XML
insert into @T(Pos, OldValue, NewValue, Attribute)
select row_number() over(order by T.N),
T.N.value('text()[1]', 'nvarchar(max)'),
T.N.value('text()[1]', 'nvarchar(max)'),
0
from @XML.nodes('//*') as T(N)
declare @ID int
declare @Pos int
declare @Value nvarchar(max)
declare @Attribute bit
-- Remove the bad words from @T, one bad word at a time
select @ID = max(ID) from @BadWords
while @ID > 0
begin
select @Value = Value
from @BadWords
where ID = @ID
update @T
set NewValue = replace(NewValue, @Value, '')
set @ID -= 1
end
-- Write the cleaned values back to the XML
select @ID = max(ID) from @T
while @ID > 0
begin
select @Value = nullif(NewValue, OldValue),
@Attribute = Attribute,
@Pos = Pos
from @T
where ID = @ID
print @Attribute
if @Value is not null
if @Attribute = 1
set @XML.modify('replace value of ((//@*)[sql:variable("@Pos")])[1]
with sql:variable("@Value")')
else
set @XML.modify('replace value of ((//*)[sql:variable("@Pos")]/text())[1]
with sql:variable("@Value")')
set @ID -= 1
end
select @XML
注意:在某些情况下,上面的代码不会处理修改本身会产生错误值的值。
<item>fioneve</item>
将被修改为
<item>five</item>