SQL Server XML字符串操作

时间:2013-02-28 02:29:37

标签: sql-server xml sql-server-2008-r2

让我说明我是XML新手。也就是说,我的问题是我有一个创建XML数据的SQL Server,并将其放入必须通过安全门到另一个服务器的文件中。该门有一个包含几个“脏”字的列表,如果包含它们将导致文件失败。我需要的是SQL搜索XML数据,每个节点以及是否存在“脏”值的方法,将其剥离(替换为空白)。 XML不是强类型的,“脏”字可能是更长字符串的一部分。在这种情况下,字符串的其余部分必须保持完整。

例如,如果“脏”字是“保持”,那么字符串“我们认为这些真理是不言而喻的”就会变成“我们这些真理是不言而喻的。”

同样,这个“脏”字可能在任何节点中,并且标签不会总是相同。我需要编写一个过程或触发器,根据脏字列表分析XML值以进行清理。

1 个答案:

答案 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>