Le meilleur moyen de supprimer les balises html d'une chaîne dans le serveur SQL?

112

J'ai des données dans SQL Server 2005 qui contiennent des balises html et j'aimerais supprimer tout cela, ne laissant que le texte entre les balises. Idéalement, remplacer également des éléments tels que &lt;par <, etc.

Existe-t-il un moyen simple de le faire ou quelqu'un a-t-il déjà un exemple de code t-sql?

Je n'ai pas la possibilité d'ajouter des procs stockés étendus, etc.

Je veux juste récupérer les données avec du HTML dépouillé, ne pas les mettre à jour, donc idéalement, elles seraient écrites comme une fonction définie par l'utilisateur, pour faciliter la réutilisation.

Donc, par exemple, convertir ceci:

<B>Some useful text</B>&nbsp;
<A onclick="return openInfo(this)"
   href="http://there.com/3ce984e88d0531bac5349"
   target=globalhelp>
   <IMG title="Source Description" height=15 alt="Source Description" 
        src="/ri/new_info.gif" width=15 align=top border=0>
</A>&gt;&nbsp;<b>more text</b></TD></TR>

pour ça:

Some useful text > more text
Rory
la source

Réponses:

162

Il y a un UDF qui fera cela décrit ici:

Fonction définie par l'utilisateur pour supprimer le HTML

CREATE FUNCTION [dbo].[udf_StripHTML] (@HTMLText VARCHAR(MAX))
RETURNS VARCHAR(MAX) AS
BEGIN
    DECLARE @Start INT
    DECLARE @End INT
    DECLARE @Length INT
    SET @Start = CHARINDEX('<',@HTMLText)
    SET @End = CHARINDEX('>',@HTMLText,CHARINDEX('<',@HTMLText))
    SET @Length = (@End - @Start) + 1
    WHILE @Start > 0 AND @End > 0 AND @Length > 0
    BEGIN
        SET @HTMLText = STUFF(@HTMLText,@Start,@Length,'')
        SET @Start = CHARINDEX('<',@HTMLText)
        SET @End = CHARINDEX('>',@HTMLText,CHARINDEX('<',@HTMLText))
        SET @Length = (@End - @Start) + 1
    END
    RETURN LTRIM(RTRIM(@HTMLText))
END
GO

Edit: notez que c'est pour SQL Server 2005, mais si vous remplacez le mot-clé MAX par quelque chose comme 4000, cela fonctionnera également dans SQL Server 2000.

RedFilter
la source
9
Grand merci. Les commentaires y renvoient vers une version améliorée: lazycoders.blogspot.com/2007/06/… qui traite plus d'entités html.
Rory
4
Notez qu'en tant que UDF gourmand en chaînes dans SQL Server 2005 ou version ultérieure, il s'agit d'un candidat idéal pour implémenter une fonction CLR UDF pour une augmentation massive des performances. Plus d'informations sur le faire ici: stackoverflow.com/questions/34509/…
RedFilter
10
Notez que la publication de lazycoders contient deux fautes de frappe. Supprimez les guillemets simples autour de CHAR(13) + CHAR(10)dans deux des sections qui les contiennent. Assez subtil, je ne l'ai pas attrapé jusqu'à ce qu'il dépasse la longueur d'un champ court (chose intéressante, et nécessaire pour moi, tous les remplacements sont plus courts que la chaîne d'origine).
revoir
1
Qu'en est-il des valeurs codées HTML? aurait besoin d'eux décodés. Merci.
JDPeckham
2
J'ai utilisé les lazycoders, plus la correction de faute de frappe de @goodeye ci-dessus - fonctionne très bien. Pour gagner du temps, la version du blog lazycoders est ici: lazycoders.blogspot.com/2007/06
...
18

Dérivé de la réponse de @Goner Doug, avec quelques éléments mis à jour:
- en utilisant REPLACE si possible
- la conversion d'entités prédéfinies comme &eacute;(j'ai choisi celles dont j'avais besoin :-)
- une conversion des balises de liste<ul> and <li>

ALTER FUNCTION [dbo].[udf_StripHTML]
--by Patrick Honorez --- www.idevlop.com
--inspired by http://stackoverflow.com/questions/457701/best-way-to-strip-html-tags-from-a-string-in-sql-server/39253602#39253602
(
@HTMLText varchar(MAX)
)
RETURNS varchar(MAX)
AS
BEGIN
DECLARE @Start  int
DECLARE @End    int
DECLARE @Length int

set @HTMLText = replace(@htmlText, '<br>',CHAR(13) + CHAR(10))
set @HTMLText = replace(@htmlText, '<br/>',CHAR(13) + CHAR(10))
set @HTMLText = replace(@htmlText, '<br />',CHAR(13) + CHAR(10))
set @HTMLText = replace(@htmlText, '<li>','- ')
set @HTMLText = replace(@htmlText, '</li>',CHAR(13) + CHAR(10))

set @HTMLText = replace(@htmlText, '&rsquo;' collate Latin1_General_CS_AS, ''''  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&quot;' collate Latin1_General_CS_AS, '"'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&amp;' collate Latin1_General_CS_AS, '&'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&euro;' collate Latin1_General_CS_AS, '€'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&lt;' collate Latin1_General_CS_AS, '<'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&gt;' collate Latin1_General_CS_AS, '>'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&oelig;' collate Latin1_General_CS_AS, 'oe'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&nbsp;' collate Latin1_General_CS_AS, ' '  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&copy;' collate Latin1_General_CS_AS, '©'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&laquo;' collate Latin1_General_CS_AS, '«'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&reg;' collate Latin1_General_CS_AS, '®'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&plusmn;' collate Latin1_General_CS_AS, '±'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&sup2;' collate Latin1_General_CS_AS, '²'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&sup3;' collate Latin1_General_CS_AS, '³'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&micro;' collate Latin1_General_CS_AS, 'µ'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&middot;' collate Latin1_General_CS_AS, '·'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&ordm;' collate Latin1_General_CS_AS, 'º'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&raquo;' collate Latin1_General_CS_AS, '»'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&frac14;' collate Latin1_General_CS_AS, '¼'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&frac12;' collate Latin1_General_CS_AS, '½'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&frac34;' collate Latin1_General_CS_AS, '¾'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&Aelig' collate Latin1_General_CS_AS, 'Æ'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&Ccedil;' collate Latin1_General_CS_AS, 'Ç'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&Egrave;' collate Latin1_General_CS_AS, 'È'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&Eacute;' collate Latin1_General_CS_AS, 'É'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&Ecirc;' collate Latin1_General_CS_AS, 'Ê'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&Ouml;' collate Latin1_General_CS_AS, 'Ö'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&agrave;' collate Latin1_General_CS_AS, 'à'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&acirc;' collate Latin1_General_CS_AS, 'â'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&auml;' collate Latin1_General_CS_AS, 'ä'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&aelig;' collate Latin1_General_CS_AS, 'æ'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&ccedil;' collate Latin1_General_CS_AS, 'ç'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&egrave;' collate Latin1_General_CS_AS, 'è'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&eacute;' collate Latin1_General_CS_AS, 'é'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&ecirc;' collate Latin1_General_CS_AS, 'ê'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&euml;' collate Latin1_General_CS_AS, 'ë'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&icirc;' collate Latin1_General_CS_AS, 'î'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&ocirc;' collate Latin1_General_CS_AS, 'ô'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&ouml;' collate Latin1_General_CS_AS, 'ö'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&divide;' collate Latin1_General_CS_AS, '÷'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&oslash;' collate Latin1_General_CS_AS, 'ø'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&ugrave;' collate Latin1_General_CS_AS, 'ù'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&uacute;' collate Latin1_General_CS_AS, 'ú'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&ucirc;' collate Latin1_General_CS_AS, 'û'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&uuml;' collate Latin1_General_CS_AS, 'ü'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&quot;' collate Latin1_General_CS_AS, '"'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&amp;' collate Latin1_General_CS_AS, '&'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&lsaquo;' collate Latin1_General_CS_AS, '<'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&rsaquo;' collate Latin1_General_CS_AS, '>'  collate Latin1_General_CS_AS)


-- Remove anything between <STYLE> tags
SET @Start = CHARINDEX('<STYLE', @HTMLText)
SET @End = CHARINDEX('</STYLE>', @HTMLText, CHARINDEX('<', @HTMLText)) + 7
SET @Length = (@End - @Start) + 1

WHILE (@Start > 0 AND @End > 0 AND @Length > 0) BEGIN
SET @HTMLText = STUFF(@HTMLText, @Start, @Length, '')
SET @Start = CHARINDEX('<STYLE', @HTMLText)
SET @End = CHARINDEX('</STYLE>', @HTMLText, CHARINDEX('</STYLE>', @HTMLText)) + 7
SET @Length = (@End - @Start) + 1
END

-- Remove anything between <whatever> tags
SET @Start = CHARINDEX('<', @HTMLText)
SET @End = CHARINDEX('>', @HTMLText, CHARINDEX('<', @HTMLText))
SET @Length = (@End - @Start) + 1

WHILE (@Start > 0 AND @End > 0 AND @Length > 0) BEGIN
SET @HTMLText = STUFF(@HTMLText, @Start, @Length, '')
SET @Start = CHARINDEX('<', @HTMLText)
SET @End = CHARINDEX('>', @HTMLText, CHARINDEX('<', @HTMLText))
SET @Length = (@End - @Start) + 1
END

RETURN LTRIM(RTRIM(@HTMLText))

END
Patrick Honorez
la source
4
Je l'ai utilisé et j'adore ça, mais j'ai ajouté un remplacement de plus au groupe supérieur: </p> J'ai changé pour un char 13 + char 10 également puisque la fin d'une balise de paragraphe indique généralement une nouvelle ligne. Cela a parfaitement fonctionné dans mon scénario particulier
DR
1
Cette réponse a fonctionné très bien pour la plupart, mais il y a une hypothèse que toutes vos balises HTML sont valides. Dans mon cas, il y avait un problème de troncature sur le téléchargement VARCHAR qui a éliminé certaines balises de fermeture. Un simple PATINDEX RTrim a fait l'affaire pour supprimer tout le reste.
matt123788
2
En plus du changement effectué par @DR (plus quelques autres qui nécessitaient des retours chariot), j'ai également déplacé les remplacements qui en résultent <et >jusqu'à la toute fin. Sinon, ils ont été supprimés avec les balises.
a_hardin
8

Si votre HTML est bien formé, je pense que c'est une meilleure solution:

create function dbo.StripHTML( @text varchar(max) ) returns varchar(max) as
begin
    declare @textXML xml
    declare @result varchar(max)
    set @textXML = REPLACE( @text, '&', '' );
    with doc(contents) as
    (
        select chunks.chunk.query('.') from @textXML.nodes('/') as chunks(chunk)
    )
    select @result = contents.value('.', 'varchar(max)') from doc
    return @result
end
go

select dbo.StripHTML('This <i>is</i> an <b>html</b> test')
mecNumber4
la source
1
Cela a fonctionné pour moi. +1. Mais pourriez-vous s'il vous plaît expliquer votre code afin que les développeurs le comprennent plus facilement? :)
Saeed Neamati
il semble qu'il charge le html en tant que document xml puis en sélectionne toutes les valeurs. Remarque: ce code émet sur & nbsp;
JDPeckham
2
Mettez un hack pour ne pas bombarder les codes HTML. Évidemment, juste un hack rapide pour une utilisation en interne ou autre (tout comme avec UDF accepté).
dudeNumber4
Il doit être bien formé, il n'est donc pas aussi tolérant aux pannes que celui de RedFilter.
Micah B.
1
HTML n'est pas un sous-ensemble de XML. XHTML l'est, mais HTML n'est plus dans cette voie.
David
7

Voici une version mise à jour de cette fonction qui intègre la réponse RedFilter (l'original de Pinal) avec les ajouts LazyCoders et les corrections de faute de frappe ET mon propre ajout pour gérer les <STYLE>balises en ligne dans le HTML.

ALTER FUNCTION [dbo].[udf_StripHTML]
(
@HTMLText varchar(MAX)
)
RETURNS varchar(MAX)
AS
BEGIN
DECLARE @Start  int
DECLARE @End    int
DECLARE @Length int

-- Replace the HTML entity &amp; with the '&' character (this needs to be done first, as
-- '&' might be double encoded as '&amp;amp;')
SET @Start = CHARINDEX('&amp;', @HTMLText)
SET @End = @Start + 4
SET @Length = (@End - @Start) + 1

WHILE (@Start > 0 AND @End > 0 AND @Length > 0) BEGIN
SET @HTMLText = STUFF(@HTMLText, @Start, @Length, '&')
SET @Start = CHARINDEX('&amp;', @HTMLText)
SET @End = @Start + 4
SET @Length = (@End - @Start) + 1
END

-- Replace the HTML entity &lt; with the '<' character
SET @Start = CHARINDEX('&lt;', @HTMLText)
SET @End = @Start + 3
SET @Length = (@End - @Start) + 1

WHILE (@Start > 0 AND @End > 0 AND @Length > 0) BEGIN
SET @HTMLText = STUFF(@HTMLText, @Start, @Length, '<')
SET @Start = CHARINDEX('&lt;', @HTMLText)
SET @End = @Start + 3
SET @Length = (@End - @Start) + 1
END

-- Replace the HTML entity &gt; with the '>' character
SET @Start = CHARINDEX('&gt;', @HTMLText)
SET @End = @Start + 3
SET @Length = (@End - @Start) + 1

WHILE (@Start > 0 AND @End > 0 AND @Length > 0) BEGIN
SET @HTMLText = STUFF(@HTMLText, @Start, @Length, '>')
SET @Start = CHARINDEX('&gt;', @HTMLText)
SET @End = @Start + 3
SET @Length = (@End - @Start) + 1
END

-- Replace the HTML entity &amp; with the '&' character
SET @Start = CHARINDEX('&amp;amp;', @HTMLText)
SET @End = @Start + 4
SET @Length = (@End - @Start) + 1

WHILE (@Start > 0 AND @End > 0 AND @Length > 0) BEGIN
SET @HTMLText = STUFF(@HTMLText, @Start, @Length, '&')
SET @Start = CHARINDEX('&amp;amp;', @HTMLText)
SET @End = @Start + 4
SET @Length = (@End - @Start) + 1
END

-- Replace the HTML entity &nbsp; with the ' ' character
SET @Start = CHARINDEX('&nbsp;', @HTMLText)
SET @End = @Start + 5
SET @Length = (@End - @Start) + 1

WHILE (@Start > 0 AND @End > 0 AND @Length > 0) BEGIN
SET @HTMLText = STUFF(@HTMLText, @Start, @Length, ' ')
SET @Start = CHARINDEX('&nbsp;', @HTMLText)
SET @End = @Start + 5
SET @Length = (@End - @Start) + 1
END

-- Replace any <br> tags with a newline
SET @Start = CHARINDEX('<br>', @HTMLText)
SET @End = @Start + 3
SET @Length = (@End - @Start) + 1

WHILE (@Start > 0 AND @End > 0 AND @Length > 0) BEGIN
SET @HTMLText = STUFF(@HTMLText, @Start, @Length, CHAR(13) + CHAR(10))
SET @Start = CHARINDEX('<br>', @HTMLText)
SET @End = @Start + 3
SET @Length = (@End - @Start) + 1
END

-- Replace any <br/> tags with a newline
SET @Start = CHARINDEX('<br/>', @HTMLText)
SET @End = @Start + 4
SET @Length = (@End - @Start) + 1

WHILE (@Start > 0 AND @End > 0 AND @Length > 0) BEGIN
SET @HTMLText = STUFF(@HTMLText, @Start, @Length, CHAR(13) + CHAR(10))
SET @Start = CHARINDEX('<br/>', @HTMLText)
SET @End = @Start + 4
SET @Length = (@End - @Start) + 1
END

-- Replace any <br /> tags with a newline
SET @Start = CHARINDEX('<br />', @HTMLText)
SET @End = @Start + 5
SET @Length = (@End - @Start) + 1

WHILE (@Start > 0 AND @End > 0 AND @Length > 0) BEGIN
SET @HTMLText = STUFF(@HTMLText, @Start, @Length, CHAR(13) + CHAR(10))
SET @Start = CHARINDEX('<br />', @HTMLText)
SET @End = @Start + 5
SET @Length = (@End - @Start) + 1
END

-- Remove anything between <STYLE> tags
SET @Start = CHARINDEX('<STYLE', @HTMLText)
SET @End = CHARINDEX('</STYLE>', @HTMLText, CHARINDEX('<', @HTMLText)) + 7
SET @Length = (@End - @Start) + 1

WHILE (@Start > 0 AND @End > 0 AND @Length > 0) BEGIN
SET @HTMLText = STUFF(@HTMLText, @Start, @Length, '')
SET @Start = CHARINDEX('<STYLE', @HTMLText)
SET @End = CHARINDEX('</STYLE>', @HTMLText, CHARINDEX('</STYLE>', @HTMLText)) + 7
SET @Length = (@End - @Start) + 1
END

-- Remove anything between <whatever> tags
SET @Start = CHARINDEX('<', @HTMLText)
SET @End = CHARINDEX('>', @HTMLText, CHARINDEX('<', @HTMLText))
SET @Length = (@End - @Start) + 1

WHILE (@Start > 0 AND @End > 0 AND @Length > 0) BEGIN
SET @HTMLText = STUFF(@HTMLText, @Start, @Length, '')
SET @Start = CHARINDEX('<', @HTMLText)
SET @End = CHARINDEX('>', @HTMLText, CHARINDEX('<', @HTMLText))
SET @Length = (@End - @Start) + 1
END

RETURN LTRIM(RTRIM(@HTMLText))

END
Goner Doug
la source
1
Pour mon information, une raison d'utiliser STUFF()au lieu de REPLACE()(quelle serait la plus courte IMO)?
Patrick Honorez
Je n'y avais pas vraiment pensé. J'ai simplement copié / modifié l'original, comme indiqué. Remplacer pourrait très bien être une meilleure option. Je me demande s'il y a une comparaison de performances entre les deux fonctions à considérer ...
Goner Doug
1
@GonerDoug applaudit pour cela, lisait les commentaires acceptés, cela a vraiment besoin d'être mis à jour.
Jono
4

Ce n'est pas une nouvelle solution complète mais une correction pour la solution d' afwebservant :

--note comments to see the corrections

CREATE FUNCTION [dbo].[StripHTML] (@HTMLText VARCHAR(MAX))  
RETURNS VARCHAR(MAX)  
AS  
BEGIN  
 DECLARE @Start  INT  
 DECLARE @End    INT  
 DECLARE @Length INT  
 --DECLARE @TempStr varchar(255) (this is not used)  

 SET @Start = CHARINDEX('<',@HTMLText)  
 SET @End = CHARINDEX('>',@HTMLText,CHARINDEX('<',@HTMLText))  
 SET @Length = (@End - @Start) + 1  

 WHILE @Start > 0 AND @End > 0 AND @Length > 0  
 BEGIN  
   IF (UPPER(SUBSTRING(@HTMLText, @Start, 4)) <> '<BR>') AND (UPPER(SUBSTRING(@HTMLText, @Start, 5)) <> '</BR>')  
    begin  
      SET @HTMLText = STUFF(@HTMLText,@Start,@Length,'')  
      end  
-- this ELSE and SET is important
   ELSE  
      SET @Length = 0;  

-- minus @Length here below is important
   SET @Start = CHARINDEX('<',@HTMLText, @End-@Length)  
   SET @End = CHARINDEX('>',@HTMLText,CHARINDEX('<',@HTMLText, @Start))  
-- instead of -1 it should be +1
   SET @Length = (@End - @Start) + 1  
 END  

 RETURN RTRIM(LTRIM(@HTMLText))  
END  
David
la source
Cela a fonctionné pour moi après avoir utilisé nvarchar au lieu de varchar parce que j'utilise des caractères unicode dans les balises html
Shadi Namrouti
3

Essaye ça. C'est une version modifiée de celle publiée par RedFilter ... ce SQL supprime toutes les balises sauf BR, B et P avec tous les attributs associés:

CREATE FUNCTION [dbo].[StripHtml] (@HTMLText VARCHAR(MAX))
RETURNS VARCHAR(MAX)
AS
BEGIN
 DECLARE @Start  INT
 DECLARE @End    INT
 DECLARE @Length INT
 DECLARE @TempStr varchar(255)

 SET @Start = CHARINDEX('<',@HTMLText)
 SET @End = CHARINDEX('>',@HTMLText,CHARINDEX('<',@HTMLText))
 SET @Length = (@End - @Start) + 1

 WHILE @Start > 0 AND @End > 0 AND @Length > 0
 BEGIN
   IF (UPPER(SUBSTRING(@HTMLText, @Start, 3)) <> '<BR') AND (UPPER(SUBSTRING(@HTMLText, @Start, 2)) <> '<P') AND (UPPER(SUBSTRING(@HTMLText, @Start, 2)) <> '<B') AND (UPPER(SUBSTRING(@HTMLText, @Start, 3)) <> '</B')
   BEGIN
      SET @HTMLText = STUFF(@HTMLText,@Start,@Length,'')
   END

   SET @Start = CHARINDEX('<',@HTMLText, @End)
   SET @End = CHARINDEX('>',@HTMLText,CHARINDEX('<',@HTMLText, @Start))
   SET @Length = (@End - @Start) - 1
 END

 RETURN RTRIM(LTRIM(@HTMLText))
END
codeaf
la source
n'a pas fonctionné pour moi SELECT dbo.StripHtml ('<b> somestuff </b>'); renvoie cette chaîne exacte
ladieu
@ladieu, c'est attendu. Vérifiez la toute première ligne de la réponse ("ce SQL supprime toutes les balises sauf BR, B et P avec tous les attributs qui l'accompagnent").
Peter Herdenborg
cette fonction SQL est incorrecte. Veuillez vous référer à la réponse ci-dessous pour la fonction corrigée.
futureelite7
@ futureelite7 utiliser "ci-dessous" et "ci-dessus" comme référence pour savoir où trouver les réponses sur une page SO n'a pas de sens, car l'ordre des réponses peut être modifié en utilisant les onglets en haut (et plus encore, le vote peut changer l'ordre des réponses). Veuillez spécifier une réponse en utilisant le nom de l'auteur qui l'a postée
Caius Jard
3

Que diriez-vous d'utiliser XQuery avec une seule ligne:

DECLARE @MalformedXML xml, @StrippedText varchar(max)
SET @MalformedXML = @xml.query('for $x in //. return ($x)//text()')
SET @StrippedText = CAST(@MalformedXML as varchar(max))

Cela parcourt tous les éléments et renvoie uniquement le texte ().

Pour éviter la concaténation du texte entre les éléments sans espaces, utilisez:

DECLARE @MalformedXML xml, @StrippedText varchar(max)
SET @MalformedXML = @xml.query('for $x in //. return concat((($x)//text())[1]," ")')
SET @StrippedText = CAST(@MalformedXML as varchar(max))

Et pour répondre à "Comment utilisez-vous ceci pour une colonne:

  SELECT CAST(html_column.query('for $x in //. return concat((($x)//text()) as varchar(max))
  FROM table

Pour le code ci-dessus, assurez-vous que votre html_columnest de type de données xml, sinon, vous devez enregistrer une version castée du html sous xml. Je ferais cela comme un exercice séparé lorsque vous chargez des données HTML, car SQL lancera une erreur s'il trouve du xml mal formé, par exemple des balises de début / fin incompatibles, des caractères invalides.

Ceux-ci sont excellents lorsque vous souhaitez créer des phrases Seachh, supprimer du HTML, etc.

Notez simplement que cela renvoie le type xml, donc CAST ou COVERT en texte le cas échéant. La version xml de ce type de données est inutile, car il ne s'agit pas d'un XML bien formé.

Arvin Amir
la source
Sans la solution réelle à diffuser à partir de xml, j'ai l'impression que c'est au mieux une solution partielle.
Dennis Jaheruddin
CAST (@xml comme varchar (max)). Ou CONVERT (xml), @XML). On suppose que la plupart des développeurs comprendraient cela.
Arvin Amir
1
Il est tout à fait raisonnable de supposer que les développeurs savent comment lancer un casting, mais gardez à l'esprit que quelqu'un qui lit votre réponse peut ne pas voir directement que le casting `` simplement '' est tout ce qui doit être fait. Surtout parce qu'il est mentionné que l'on peut lancer le cas échéant . - Je n'essaie pas d'être négatif, j'espère juste que cela vous aidera à créer des réponses plus faciles à reconnaître comme utiles!
Dennis Jaheruddin
Alors, quelle partie de ceci est le nom de la colonne? Disons que j'ai une table appelée dataavec une colonne appelée htmlet que je veux sélectionner toutes les valeurs de cette colonne mais supprimer les balises html, comment pourrais-je utiliser votre réponse pour y parvenir?
Felix Eve
2

Voici une version qui ne nécessite pas d'UDF et fonctionne même si le HTML contient des balises sans balises de fermeture correspondantes.

TRY_CAST(REPLACE(REPLACE(REPLACE([HtmlCol], '>', '/> '), '</', '<'), '--/>', '-->') AS XML).value('.', 'NVARCHAR(MAX)')
Clément
la source
1

Alors que la réponse d'Arvin Amir se rapproche d'une solution complète en une seule ligne, vous pouvez déposer n'importe où; il a un léger bogue dans son instruction select (il manque la fin de la ligne), et je voulais gérer les références de caractères les plus courantes.

Ce que j'ai fini par faire, c'est ceci:

SELECT replace(replace(replace(CAST(CAST(replace([columnNameHere], '&', '&amp;') as xml).query('for $x in //. return concat((($x)//text())[1]," ")') as varchar(max)), '&amp;', '&'), '&nbsp;', ' '), '&#x20;', ' ')
FROM [tableName]

Sans le code de référence de caractère, cela peut être simplifié:

SELECT CAST(CAST([columnNameHere] as xml).query('for $x in //. return concat((($x)//text())[1]," ")') as varchar(max))
FROM [tableName]
Brian Heward
la source
0

Le code de Patrick Honorez a besoin d'un léger changement.

Il renvoie des résultats incomplets pour le code HTML contenant &lt;ou&gt;

C'est parce que le code sous la section

- Supprimer tout ce qui se trouve entre les balises

remplacera en fait le <> à rien. Le correctif consiste à appliquer les deux lignes ci-dessous à la fin:

set @HTMLText = replace(@htmlText, '&lt;' collate Latin1_General_CS_AS, '<'  collate Latin1_General_CS_AS)
set @HTMLText = replace(@htmlText, '&gt;' collate Latin1_General_CS_AS, '>'  collate Latin1_General_CS_AS)
Maghi85
la source