第三方组件正在填充表中的nvarchar
列,其中包含一些值。大多数情况下,它是一个人类可读的字符串,但偶尔它是XML(如果在第三方comp中有一些内部异常)。
作为临时解决方案(直到他们修复它并始终使用字符串),我想解析XML数据并提取实际消息。
环境: SQL Server 2005;字符串总是小于1K;这张表中可能有几千行。
我遇到了几个解决方案,但我不确定它们是否足够好:
sp_xml_preparedocument
存储过程并将其包装在TRY / CATCH块周围。检查返回值/句柄。这些方法似乎都没有效率。我正在寻找与ISNUMERIC()
类似的东西:ISXML()
函数。还有其他更好的检查字符串的方法吗?
答案 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;