XML中xmlns:i与xmlns:xsi属性差异及SQL Server查询解决方案
关于xmlns:i与xmlns:xsi的区别,以及SQL Server中查询含该属性XML列的解决方案
首先聊聊xmlns:i和xmlns:xsi的核心区别:
xmlns:xsi是行业通用的约定前缀,专门用来绑定http://www.w3.org/2001/XMLSchema-instance这个W3C标准命名空间——这个命名空间负责定义XML Schema实例相关的特殊属性,比如xsi:nil(标记节点值为空)、xsi:type(指定节点的实际数据类型)。xmlns:i只是把同一个标准命名空间绑定到了i这个自定义前缀上。本质上两者指向的是完全相同的命名空间URI,唯一的区别就是前缀名称不同:xsi是大家默认用的“别名”,i是你的场景里程序自定义的“别名”而已。
接下来解决你遇到的SQL Server查询返回NULL的问题——这其实是XML命名空间处理的典型坑:
你的查询语句之所以返回NULL,是因为SQL Server的XQuery引擎会严格校验XML的命名空间上下文,哪怕你要查询的节点没有使用前缀,只要文档里存在命名空间声明,就需要在查询时正确声明这些命名空间,否则引擎会认为你要找的节点不存在。
针对你给出的XML示例,正确的查询方式是使用WITH XMLNAMESPACES关键字提前声明文档中所有的命名空间,具体SQL语句如下:
WITH XMLNAMESPACES ( 'http://www.w3.org/2001/XMLSchema-instance' AS i, 'http://schemas.microsoft.com/2003/10/Serialization/' AS z ) SELECT MY_XML_COLUMN.value('(/MyRootNode/MyValue)[1]', 'varchar(100)') AS MyValue FROM MY_TABLE;
如果你的实际XML中,MyRootNode和MyValue属于某个默认命名空间(.NET XmlSerializer生成的XML通常会带默认命名空间,可能你示例里没写全),那还需要把默认命名空间也声明进去:
WITH XMLNAMESPACES ( DEFAULT 'http://your-actual-default-namespace.com', -- 替换成你XML里的默认命名空间URI 'http://www.w3.org/2001/XMLSchema-instance' AS i, 'http://schemas.microsoft.com/2003/10/Serialization/' AS z ) SELECT MY_XML_COLUMN.value('(/MyRootNode/MyValue)[1]', 'varchar(100)') AS MyValue FROM MY_TABLE;
至于为什么之前用xmlns:xsi的时候能正常返回?大概率是因为当时的XML没有其他命名空间干扰,或者默认命名空间未被设置,XQuery引擎可以直接匹配到目标节点。
如果你不想纠结命名空间的具体URI,也可以用通配符*:来忽略命名空间(但不推荐,因为可能匹配到无关节点):
SELECT MY_XML_COLUMN.value('(*:MyRootNode/*:MyValue)[1]', 'varchar(100)') AS MyValue FROM MY_TABLE;
最后补充一句:XML里的z:Id是.NET XmlSerializer用来处理对象引用的标记,不会影响节点查询,只要正确处理命名空间就能正常取值。
内容的提问来源于stack exchange,提问作者Firnas
相关产品推荐
相关产品推荐

