在SQL Server中,确定给定字符串是否为有效XML的最佳方法是什么?

时间:2011-03-21 18:20:54

标签: xml sql-server-2005 tsql

第三方组件正在填充表中的nvarchar列,其中包含一些值。大多数情况下,它是一个人类可读的字符串,但偶尔它是XML(如果在第三方comp中有一些内部异常)。

作为临时解决方案(直到他们修复它并始终使用字符串),我想解析XML数据并提取实际消息。

环境: SQL Server 2005;字符串总是小于1K;这张表中可能有几千行。


我遇到了几个解决方案,但我不确定它们是否足够好:

  1. 调用sp_xml_preparedocument存储过程并将其包装在TRY / CATCH块周围。检查返回值/句柄。
  2. 编写托管代码(在C#中),再次处理异常并查看它是否是有效的字符串。
  3. 这些方法似乎都没有效率。我正在寻找与ISNUMERIC()类似的东西:ISXML()函数。还有其他更好的检查字符串的方法吗?

4 个答案:

答案 0 :(得分:9)

  

我想解析XML数据并提取实际消息。

也许没有必要检查有效的XML。您可以在案例陈述中检查是否存在xml标记charindex,并使用substring提取错误消息。

这是一个带有简化XML字符串的示例,但我认为您可以理解。

declare @T table(ID int, Col1 nvarchar(1000))

insert into @T values
(1, 'No xml value 1'),
(2, 'No xml value 2'),
(3, '<root><item>Text value in xml</item></root>')

select
  case when charindex('<item>', Col1) = 0
  then Col1
  else
    substring(Col1, charindex('<item>', Col1)+6, charindex('</item>', Col1)-charindex('<item>', Col1)-6)
  end  
from @T

结果:

No xml value 1
No xml value 2
Text value in xml

答案 1 :(得分:4)

您可以创建XML架构并使用它来验证XML字符串。

有关其他信息,请参阅此处:http://msdn.microsoft.com/en-us/library/ms176009.aspx

以下是一个例子:

CREATE XML SCHEMA COLLECTION UserSchemaCollection AS 
N'<?xml version="1.0" encoding="UTF-16"?>
  <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name = "User" >
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name = "UserID" />
                <xsd:element name = "UserName" />
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
  </xsd:schema>';


DECLARE @x XML(UserSchemaCollection)
SELECT @x = '<User><UserID>1234</UserID><UserName>Sebastian</UserName></User>'

示例:

DECLARE @y XML(UserSchemaCollection)
SELECT @y = '<User><UserName>Sebastian</UserName></User>'

Msg 6965,Level 16,State 1,Line 2 XML验证:内容无效。预期元素:UserID where元素&#39; UserName&#39;被指定了。位置:/ :用户[1] / :用户名[1]

DECLARE @z XML(UserSchemaCollection)
SELECT @z = 'Some text'

Msg 6909,Level 16,State 1,Line 2 XML验证:此位置不允许使用文本节点,类型是使用仅元素内容或使用简单内容定义的。地点:/

答案 2 :(得分:4)

基于接受的答案,我创建了这个以检查有效的XML并可选地将输入字符串转换为XML(或从XML中提取所需的元素/属性),因为我发现 {{3}如果你只是传入纯文本,我没想到的话,成功地工作,所以需要进行另一次检查以防止最终转换为XML我需要工作以防源列只保存一些文本(示例行) 1):

Allocation

答案 3 :(得分:1)

我不知道最好的方法,但这是一种方式:

DECLARE @table TABLE (myXML XML)

INSERT INTO @table
SELECT  
'
    <Employee>
        <FirstName>Henry</FirstName>
        <LastName>Ford</LastName>
    </Employee>
'

SELECT myXML 
FROM @table 
FOR XML RAW

如果XML无效,则会抛出错误:

DECLARE @table TABLE (myXML XML)

INSERT INTO @table
SELECT  
'
    <Employee
        <FirstName>Henry</FirstName>
        <LastName>Ford</LastName>
    </Employee>
'

SELECT myXML 
FROM @table 
FOR XML RAW

只是为了澄清,你所要做的就是施展它:

BEGIN TRY
    DECLARE @myXML XML
    SET @myXML = CAST
    ('
        <Employee>
            <FirstName>Henry</FirstName>
            <LastName>Ford</LastName>
        </Employee>
    ' AS XML)
    SELECT 'VALID XML'
END TRY
BEGIN CATCH
    SELECT 'INVALID XML'
END CATCH;

VS

BEGIN TRY
    DECLARE @myXML XML
    SET @myXML = CAST
    ('
        <Employee
            <FirstName>Henry</FirstName>
            <LastName>Ford</LastName>
        </Employee>
    ' AS XML)
    SELECT 'VALID XML'
END TRY
BEGIN CATCH
    SELECT 'INVALID XML'
END CATCH;