首页 > 解决方案 > SQL Server 插入 XML 节点正在添加命名空间

问题描述

我有一个现有的 XML 列,我想将一个节点附加到该列,但该节点正在添加一个不需要的命名空间。

DECLARE @x XML =
'<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="abc">
  <Setting key="display" display="ABC" group="service" enabled="true">
    <Value xsi:type="xsd:string">ABC</Value>
  </Setting>
</Test>'

CREATE TABLE #C ( x XML )

INSERT INTO #C
SELECT @X

declare @name varchar(50) = 'ABC'
UPDATE #C
SET X.modify('insert <Setting key="about" display="About" group="service" enabled="true">
           <Value xsi:type="xsd:string">string of text about {sql:variable("@name")} here.</Value>
         </Setting> as last into (/Test[1])')

select * from #C

导致新设置被添加为...

<Setting key="about" display="About" group="service" enabled="true">
    <Value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">string of text about ABC here.</Value>
</Setting>

但我真正想要的是

    <Setting key="about" display="About" group="service" enabled="true">
        <Value xsi:type="xsd:string">string of text about ABC here.</Value>
    </Setting>

标签: sql-serverxmltsqlxml-namespacesxml-dml

解决方案


SQL-Server 的 XML 引擎处理命名空间的方式 - 在某些情况下 - 非常烦人......重要的是,以上内容没有错......重复命名空间声明完全可以,但结果会膨胀,使人类难以阅读和理解 XML,并且它可能会在严格的验证器中失败。

原因是,这样的 XML 总是完整的。您可以将它放在 XML 中的任何位置。

在你的情况下,你会得到你想要的结果,通过提前告诉引擎命名空间:

隐式声明

UPDATE #C
SET X.modify('declare namespace xsi="http://www.w3.org/2001/XMLSchema-instance";
              insert <Setting key="about" display="About" group="service" enabled="true">
                         <Value xsi:type="xsd:string">string of text about {sql:variable("@name")} here.</Value>
                     </Setting> 
              as last into (/Test[1])');

WITH XMLNAMESPACES()

WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' AS xsi)
UPDATE #C
SET X.modify('insert <Setting key="about" display="About" group="service" enabled="true">
                         <Value xsi:type="xsd:string">string of text about {sql:variable("@name")} here.</Value>
                     </Setting> 
              as last into (/Test[1])');

推荐阅读