using System;
using System.IO;
using System.Xml;
using System.Xml.Xsl;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Xml.Schema;
namespace SqlHelperClr
{
public static class Xml
{
[SqlFunction]
public static SqlString XmlValidate(SqlXml InputXml, SqlXml ValidationXsd)
{
if (InputXml.IsNull)
throw new ArgumentNullException("InputXml", "InputXml is NULL.");
if (ValidationXsd.IsNull)
throw new ArgumentNullException("ValidationXsd", "ValidationXsd is NULL.");
using (XmlReader xmlSchemaReader = ValidationXsd.CreateReader())
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add("http://schemanamespace.example.com/", xmlSchemaReader);
settings.ValidationType = ValidationType.Schema;
using (XmlReader xmlReader = XmlReader.Create(InputXml.CreateReader(), settings))
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlReader);
ValidationEventArgs capturedEventArgs = null;
// Declare anonymous validation event handler to save the validation event arguments to a 'captured variable'
ValidationEventHandler eventHandler = new ValidationEventHandler(
(obj, e) =>
{
capturedEventArgs = e;
});
try
{
doc.Validate(eventHandler);
}
catch (Exception ex)
{
return String.Format("ERROR; Severity {0}: {1}", capturedEventArgs.Severity.ToString(), capturedEventArgs.Message);
}
return "OK";
}
}
}
}
}
将 CLR 程序集添加到 Microsoft SQL Server
生成程序集,然后将输出 DLL 文件复制到 SQL Server 实例可访问的位置。然后运行以下命令在数据库中注册 CLR 程序集:
USE [Mydatabase]
CREATE ASSEMBLY [SqlHelperClr]
FROM 'C:\SqlAssemblies\SqlHelperClr.dll'
WITH PERMISSION_SET = UNSAFE;
创建一个将调用 XmlValidate 的标量函数
USE [Mydatabase]
CREATE FUNCTION dbo.fn_ValidateXsd (@InputXml XML, @ValidationXsd XML)
RETURNS NVARCHAR(1000)
AS EXTERNAL NAME [SqlHelperClr].[SqlHelperClr.Xml].[XmlValidate];
-- [AssemblyName].[NamespaceNames.StaticClassName].[MethodName]
使用 fn_ValidateXsd
DECLARE @XmlDoc Xml = '<Root><NodeA>Blah</NodeA></Root>'
DECLARE @XmlSchema Xml = '' -- Schema goes here
DECLARE @Validation_Message NVARCHAR(1000)
SET @Validation_Message = dbo.fn_ValidateXsd(@XmlDoc, @XmlSchema)
我认为使用 T-SQL 不可能做到这一点,但是您可以使用 C# 和 .NET CLR 程序集来实现您所需要的。
脚步
public static
可以为您完成工作的方法。针对 XSD 验证 XML 文档的公共静态方法
将 CLR 程序集添加到 Microsoft SQL Server
生成程序集,然后将输出 DLL 文件复制到 SQL Server 实例可访问的位置。然后运行以下命令在数据库中注册 CLR 程序集:
创建一个将调用 XmlValidate 的标量函数
使用 fn_ValidateXsd
我强烈建议您从 Xml 模式集合中已经拥有的用于执行此操作的函数中的代码开始,如以下问题所示:
SQL 2012 CLR 错误:“在进入...之前处于活动状态的上下文事务”?
您可以创建第二个几乎相同但使用 XSD 本身而不是模式集合名称的函数,然后它可以以相同的方式进行验证,但不需要从数据库中获取它。而且,由于此函数正在执行任何数据访问以获取 XSD,因此可以将其标记为
IsDeterministic=true
允许它参与并行计划(或者,换句话说,这将阻止函数强制执行串行计划)。这样,您就有了一致的验证方法,只是 XSD 的来源不同。这个函数和你的其他问题(上面链接)中的函数都可以在同一个
SAFE
程序集中。我看不出有理由使用UNSAFE
大会来做到这一点。