2013-02-28 3 views
1

Permettez-moi d'indiquer que je suis un novice XML. Cela dit, mon problème est que j'ai un serveur SQL qui crée des données XML et place cela dans un fichier qui doit passer par une porte de sécurité à un autre serveur. La porte a une liste de plusieurs mots "sales" qui provoqueront l'échec des fichiers s'ils sont inclus. Ce dont j'ai besoin, c'est un moyen pour SQL de rechercher les données XML, chaque nœud, et si la valeur "sale" est présente, effacez-la (remplacez par vide). Le XML n'est pas fortement typé, et le mot "sale" pourrait éventuellement faire partie d'une chaîne plus longue. Dans ce cas, le reste de la chaîne doit rester intact. Par exemple, si le mot «sale» est «maintenez», la chaîne «Nous considérons que ces vérités sont évidentes» deviendrait «Nous ces vérités évidentes».SQL Server XML String Manipluation

Encore une fois, ce mot "sale" pourrait être dans n'importe quel nœud, et les balises ne seront pas toujours les mêmes. J'ai besoin d'écrire une procédure ou un déclencheur qui analyse la valeur XML en fonction de la liste de mots à nettoyer pour le nettoyer.

+0

Quelle version de SQL Server? Si ce n'est pas fortement typé, est-ce au moins dans une colonne de type 'xml'? –

+0

2008 R2. oui, la colonne est de type de données XML – user1873604

+0

Donc, quand vous dites que ce n'est pas fortement typé, vous voulez dire qu'il n'a aucun ensemble de schémas associés? –

Répondre

0

Détruisez le code XML en une table avec une ligne pour chaque noeud. La table a besoin d'un identifiant qui correspond à la position du nœud dans le XML déchiqueté pour pouvoir écrire les changements. Ayez vos mots vides dans une table et pour chaque mot, utilisez replace pour les supprimer de la table avec les valeurs de nœuds.

Enfin, vous parcourez les valeurs nettoyées et les réécrivez sur le nœud XML à la fois pour les nœuds qui ont été réellement modifiés.

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

Remarque: Dans certains cas, le code ci-dessus ne traitera pas des valeurs où la modification crée elle-même la mauvaise valeur.

<item>fioneve</item> 

sera modifié pour

<item>five</item> 
+0

Merci beaucoup!ça va prendre quelques heures avant que j'aie l'occasion de l'essayer, mais ça a l'air génial! – user1873604

+0

A travaillé comme un champion! Merci encore! – user1873604

+0

@ user1873604 De rien. –