0

在我之前的问题 SQL Server XML String Manipulation

我得到了下面的答案(感谢 Mikael Eriksson)来粉碎 XML 文档,并从字符中删除不需要的单词。我现在需要更进一步,去掉超过 255 个 Unicode 字符。当我的 XML 中有这些字符时,它们会作为问号存储在 @T 表变量(在下面的代码中)中。我怎样才能让这些字符作为实际的 Unicode 字符出现,这样我就可以把它们去掉?

我有一个功能可以很好地删除不需要的字符,但是由于 Unicode 作为问号出现,它不会触及它们

 -- 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
4

1 回答 1

2

这部分看起来:

insert into @BadWords values
('one'),
('three'),
('five'),
('hold')

Unicode 字符串文字需要 N 前缀。如果没有 N,您的代码会将它们视为 VARCHAR,并且您会得到多字节字符的问号。还有其他地方你也必须使用 Unicode 友好的字符串。XML 通常是 UTF-8,因此应该能够处理 Unicode 字符,尽管标准不鼓励这些. 您的代码应如下所示:

insert into @BadWords values
(N'one'),
(N'three'),
(N'five'),
(N'hold')
于 2013-04-15T16:55:26.793 回答