在SQL Server中查找未关闭的XML标记

时间:2018-09-20 16:58:21

标签: sql sql-server xml

我正在使用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

1 个答案:

答案 0 :(得分:0)

简短的回答:不,没有内置的东西。如您所知,SQL Server可以判断XML无效。它不能做的是告诉您确切的位置。最好的办法是捕获错误,将不良数据写入某些“拒绝”表,然后解析SQL外部的拒绝项,以找出问题所在。