【发布时间】:2018-09-20 16:58:20
【问题描述】:
我正在使用 SQL Server 的 CONVERT XML 函数将字符串转换为 XML。输入字符串有时包含错误数据,我需要在 SQL Server 的函数中清理它。
数据如下:
<a>test</a>test<b>test
并用这个转换:
select CONVERT(XML,'<a>test</a>test<b>test')
使用 CONVERT 时,会出现“输入意外结束”的错误。 b 标记甚至根本不是标记,它只是某人与有效 XML 一起键入的内容。
我需要去掉它的 b 标签,或者在末尾加上一个斜杠,这样它就是一个自闭合标签。
SQL Server 中有什么方法可以识别未闭合的标签吗?我能弄清楚的唯一方法是编写我自己的 XML 解析器……这不是我现在想做的事情。数据已经在 SQL Server 中,因此不可能在用户输入中修复它。
任何帮助将不胜感激。
ETA:咬紧牙关,只是解析它。下面非常迂腐的代码。请注意,这不会修复所有未关闭的标签......只有那些在任何地方都没有使用该名称的结束标签的标签。任何希望真正找到未封闭标签的人......祝你好运!
欢迎对此代码进行任何改进!
DECLARE @OPENTAGS TABLE (
tag VARCHAR(64)
);
DECLARE @CLOSETAGS TABLE (
tag VARCHAR(64)
);
DECLARE @P INT=0;
DECLARE @Tag VARCHAR(64);
DECLARE @IsOpen INT=0;
DECLARE @IsClosingTag INT=0;
DECLARE @C nchar(1);
WHILE @P<LEN(@InputString)
BEGIN
SET @C = SUBSTRING(@InputString,@P+1,1)
IF @IsOpen=0
BEGIN
IF @C='<'
BEGIN
SET @IsOpen=1;
SET @IsClosingTag=0;
SET @Tag='';
END
END
ELSE
BEGIN
IF @C='/'
BEGIN
IF LEN(@Tag)=0
BEGIN
SET @IsClosingTag=1;
END
ELSE
BEGIN
SET @IsOpen=0;
SET @Tag='';
END
END
IF @C='>'
BEGIN
IF @IsClosingTag=0
BEGIN
INSERT INTO @OPENTAGS (tag) VALUES(@Tag)
END
ELSE
BEGIN
INSERT INTO @CLOSETAGS (tag) VALUES(@Tag)
END
SET @IsOpen=0;
SET @Tag='';
END
IF (ASCII(@C)>=65 AND ASCII(@C)<=90) OR (ASCII(@C)>=97 AND ASCII(@C)<=122)
BEGIN
SET @Tag=@Tag+@C;
END
END
SET @P = @P + 1;
END
IF (SELECT COUNT(DISTINCT tag) FROM @OPENTAGS) > (SELECT COUNT(DISTINCT tag) FROM @CLOSETAGS)
BEGIN
DECLARE @@badtag nvarchar(64);
DECLARE badtags CURSOR FOR
SELECT * FROM @OPENTAGS WHERE tag NOT IN (SELECT tag FROM @CLOSETAGS);
OPEN badtags;
FETCH NEXT FROM badtags INTO @@badtag;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @InputString = REPLACE(@InputString,'<' + @@badtag + '>', '<' + @@badtag + '/>');
FETCH NEXT FROM badtags INTO @@badtag;
END;
CLOSE badtags;
DEALLOCATE badtags;
END
【问题讨论】:
-
也许您可以捕获异常并让查询继续?看看stackoverflow.com/questions/4442772/…。
标签: sql sql-server xml