我有以下 CLR 存储过程,该过程在此命令上引发错误
xmlDoc.LoadXml(inputXml);
代码
public static int spGetTaxOfficeXML(SqlXml _inputXml)
{
// this procedure rename Row elements name with NodeName attribute value
string inputXml = _inputXml.ToString();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(inputXml);
// procedure Logic
SqlContext.Pipe.Send(inputXml);
return 0;
}
当 XML 文本作为文本在 Visual Studio 内的变量中时,它运行良好。但是当我将代码作为 CLR 上传到 SQL 服务器并尝试从 SQL Management Studio 执行它时:
DECLARE @XML XML
SET @XML = '<NodeA><NodeB></NodeB><NodeC AttributeX=""><Row NodeName="RowA" AttributeA="" AttributeB="abcd" AttributeC="efgh" /><Row NodeName="RowB" AttributeA="wxyz" /><Row NodeName="RowC" AttributeB="qwer" AttributeC="tyui" /><Row NodeName="RowD" AttributeA="stuv" AttributeB="erty" AttributeC="fghj" /></NodeC></NodeA>'
EXEC dbo.spGetTaxOfficeXML @XML
然后抛出这个错误:
Msg 6522, Level 16, State 1, Procedure spGetTaxOfficeXML, Line 0
A .NET Framework error occurred during execution of user-defined routine or aggregate "spGetTaxOfficeXML":
System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.
System.Xml.XmlException:
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace()
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.LoadXml(String xml)
at StoredProcedures.spGetTaxOfficeXML(String inputXml)
我尝试使用以下代码解决错误,因为我虽然 utf8 字节可能导致错误,但它没有帮助。
// if byte mark exception happens
string _byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
if (inputXml.StartsWith(_byteOrderMarkUtf8))
{
inputXml = inputXml.Remove(0, _byteOrderMarkUtf8.Length);
}
这里有什么问题?
问题是您对该
SqlXml.ToString()
方法返回的值做出了错误的假设,然后在 Visual Studio 中进行测试时,您注入了一个值但没有检查ToString()
实际返回的内容(即:“System.Data.SqlTypes .SqlXml”)。SqlContext.Pipe.Send(inputXml);
尽管如果您将线放在线的上方,您可能会看到这一点xmlDoc.LoadXml(inputXml);
;-)。在使用这些
Sql*
类型时,您几乎总是希望通过Value
它们都拥有的属性来访问它们。该Value
属性确实返回了您想要获取的 XML 的字符串版本。但是,这不太理想,因为您会将 XML 转换为字符串,只是在您调用XmlDocument.LoadXml()
.更好的方法是使用
SqlXml.CreateReader()
返回 的方法XmlReader
,并且可以与该XmlDocument.Load()
方法一起使用。我重新编写了您的测试代码(如下),作为显示所有 3 种变体的示例:
使用原始测试 SQL 运行上面的代码会在“消息”选项卡中返回以下内容:
PS 你不需要担心 UTF-8,特别是对于从 SQL Server 内部生成的 NCHAR / NVARCHAR / XML 数据,因为 SQL Server 是 UTF-16 LE。