【问题标题】:Converting varchar to XML and parsing the XML failing将 varchar 转换为 XML 并解析 XML 失败
【发布时间】:2020-09-12 23:57:15
【问题描述】:

我正在尝试设计一个查询来搜索 EMR 数据库中的审核日志。问题是审计信息存储在 varchar 列中,有时它只是对发生的事情的文本描述(我不在乎),有时它包含有效的 XML(我知道这是一个设计缺陷,但我可以'不要更改它,因为我没有创建 EMR)

我创建了一个表值函数来解析 xml 并返回数据,但 select 语句无法执行,因为有时函数中的 xml 转换会失败。我不能对函数中的转换进行 try/catch,我也可以从函数调用存储过程来使用 try/catch 进行转换,所以我不知道该怎么做。

从审核中选择前 1 个 * (nolock) 外部应用 dbo.cus_GetDeletedAttachmentInfo(Audit.Audituid) 作为详细信息

错误 XML解析:第1行,字符136,非法xml字符

【问题讨论】:

  • 这是 MS SQL Server 吗?什么版本?

标签: xml tsql function parsing


【解决方案1】:

您的标记中有一个非法字符,当您尝试转换为 xml 时,您可能需要注意这一点。我做了这样的事情:

declare @Text varchar(max);

select @Text = '<root><stuff>&</stuff></root>'


begin try
    select Cast(@Text as xml)
end try
begin catch
    Select Error_message()

    Select 'Let''s account for ampersand manually by converting'

    select cast(replace(@Text, '&', '&amp;') as xml)
end catch

您需要考虑诸如与号和其他未标记的字符之类的内容,否则 SQL Server 中强制转换或转换的默认行为是失败并说明失败的原因。 XML 需要标记特殊字符。通常有像这里这样的标记列表(没有尝试过所有这些,因为这只是一个例子):

http://rabbit.eng.miami.edu/info/htmlchars.html

【讨论】:

  • 它可能没有任何非法字符并且不是有效的 XML。仍然转换是朝着正确方向迈出的一步。 +1
  • 我现在收到另一个错误 XML 解析:第 1 行,字符 39,无法切换编码
  • 您需要通过考虑许多潜在的无效字符来确定数据是否是有效的 XML。我的示例只是最常见的示例,通常是有人在字符串字段中放置一个 & 符号。您可以随时发布 varchar 字段,我们可以尝试以这种方式解决它。我会编写一个过程来进行转换,尝试在 try/catch 块中尝试许多替换选项。有时正如 Blam 上面所说,你真的有无效的 xml。当有人给出文本而不将其放在验证器周围时,这就是问题,它是否不需要合法 xml。
【解决方案2】:

http://rabbit.eng.miami.edu/info/htmlchars.html 中提到的所有字符都没有失败

我检查了以下两组。只有第2集有问题

SELECT
    cast( 
        REPLACE(
        REPLACE(fldvalue,'<', '&lt;')
        ,'&','&amp;')
        
         as xml) 
    
FROM
(
    -- set 1
    select fldvalue = '<abc>test</abc>' -- Pure text
    UNION
    select fldvalue = '<abc>$test</abc>' -- with $ symbol
    union
    select fldvalue = '<abc>%test</abc>' -- with % symbol
    UNION
    select fldvalue = '<abc>>1test</abc>' -- with > symbol
    UNION
    select fldvalue = '>>1test' -- with >> symbol
    UNION
    select fldvalue = '<abc>test"</abc>' -- with " symbol
    UNION
    select fldvalue = '¢test' -- with ¢ symbol
    UNION
    select fldvalue = '£test' -- with £ symbol
    UNION
    select fldvalue = '¥test' -- with ¥ symbol
    UNION
    select fldvalue = '©test' -- with © symbol
    UNION
    select fldvalue = '½test'  -- with ½ symbol
    
    
    -- set 2
    UNION
    select fldvalue = '<def><test</def>'
    UNION
    select fldvalue = '&1test'
    
) A

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-28
    • 1970-01-01
    • 2021-10-29
    • 2015-05-12
    • 2018-03-20
    • 1970-01-01
    • 2013-07-30
    相关资源
    最近更新 更多