【问题标题】:Find Unclosed XML tags in SQL Server在 SQL Server 中查找未关闭的 XML 标记
【发布时间】: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

【问题讨论】:

标签: sql sql-server xml


【解决方案1】:

简短回答:不,没有任何内置功能。正如您所发现的,SQL Server 可以判断 XML 无效。它不能做的是告诉你确切的位置。最好的办法是捕获错误,将错误数据写入某个“拒绝”表,然后在 SQL 之外解析拒绝以找出问题所在。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-05
    • 2020-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多