1

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

例如,如果“脏”字是“持有”,则字符串“我们认为这些真理是不言而喻的”将变成“我们这些真理是不言而喻的”。

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

4

1 回答 1

0

将 XML 分解为一个表,每个节点都有一行。该表需要一个与已分解 XML 中的节点位置相对应的 id,以便能够写回更改。

将您的坏词放在一个表中,并为每个词使用replace节点值从表中删除它们。

最后,您遍历清理过的值并将它们一次写回 XML 一个节点,用于实际修改的节点。

-- 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>
于 2013-03-01T06:48:00.703 回答