SQL Server 存储过程解析 BizTalk XML 子节点为何返回 NULL?
数据小陈
结论
子元素也带有 ns0 命名空间前缀,因此读取时,XQuery 路径也要包含该前缀;文本节点则应写作 text()。当前查询的根节点路径带有 ns0,但字段路径没有命名空间前缀,并且把 text() 写成了 text,所以没有匹配到子节点的值。
题目给出的 XML 中,MessageID、CTDateTime、VisitNo 和 AccessionNo 都属于 URI http://schemas.microsoft.com/Sql/2008/05/Procedures/dbo 对应的命名空间。
修改存储过程
为 XML 列设置清晰的别名,并在每个子节点路径中添加 ns0::
ALTER PROCEDURE [dbo].[HHN_MohCTOrder]
@xml XML
AS
BEGIN
;WITH XMLNAMESPACES (
'http://schemas.microsoft.com/Sql/2008/05/Procedures/dbo' AS ns0
)
SELECT
n.value('(ns0:MessageID/text())[1]', 'varchar(13)') AS MessageID,
n.value('(ns0:CTDateTime/text())[1]', 'varchar(14)') AS CTDateTime,
n.value('(ns0:VisitNo/text())[1]', 'varchar(12)') AS VisitNo,
n.value('(ns0:AccessionNo/text())[1]', 'varchar(12)') AS AccessionNo
FROM @xml.nodes('/ns0:HHN_MohCTOrder') AS t(n);
END
nodes() 会将匹配到的根节点作为上下文行,n.value() 再从该节点读取相应的子元素。[1] 用来满足 value() 对单个结果的要求。此写法假设传入参数的结构与题目所示一致,且 namespace URI 与实际消息完全相同。
检查传入的 XML
如果修改后仍然读不到值,可以先查看存储过程收到的 XML:
SELECT @xml;
检查根元素、子元素名称和命名空间 URI。XML namespace 根据 URI 匹配,前缀名称可以不同;查询中声明的 ns0 只需映射到消息使用的同一 URI。如果实际 XML 使用了不同的 URI,需要相应调整 XMLNAMESPACES 声明。
备注:内容仅供参考。
