Sql server 用于XML查询的T-SQL中的名称空间存在问题

Sql server 用于XML查询的T-SQL中的名称空间存在问题,sql-server,xml,xml-namespaces,for-xml,Sql Server,Xml,Xml Namespaces,For Xml,我有一个关于使用SQLServerforXML创建带有名称空间的XML文档的问题。我需要创建一个如下的文档,其中根元素(xmlns:ijk=“h:/I.j.k”)中有一个名称空间定义,子元素属性(ijk:LMNO=“3333”)中有一个名称空间引用 我正在生成要发布到Web服务的XML: <ROOT xmlns:ijk="h:/i.j.k" RSTU="1111"> <CHILD CDEF="2222" ijk:LMNO="3333" /> </ROOT>

我有一个关于使用SQLServerforXML创建带有名称空间的XML文档的问题。我需要创建一个如下的文档,其中根元素(
xmlns:ijk=“h:/I.j.k”
)中有一个名称空间定义,子元素属性(
ijk:LMNO=“3333”
)中有一个名称空间引用

我正在生成要发布到Web服务的XML:

<ROOT xmlns:ijk="h:/i.j.k" RSTU="1111">
  <CHILD CDEF="2222" ijk:LMNO="3333" />
</ROOT>
结果

<ROOT RSTU="1111">
  <CHILD CDEF="2222" LMNO="3333" />
</ROOT>
结果:

<ROOT xmlns:xyz="h:/x.y.z" xmlns:ijk="h:/i.j.k" RSTU="1111">
    <CHILD xmlns:xyz="h:/x.y.z" xmlns:ijk="h:/i.j.k" CDEF="2222" ijk:LMNO="3333" />
</ROOT>
<ROOT xmlns:ijk="h:/i.j.k" RSTU="1111">
  <CHILD CDEF="2222" LMNO="3333" />
</ROOT>
结果:

<ROOT xmlns:xyz="h:/x.y.z" xmlns:ijk="h:/i.j.k" RSTU="1111">
    <CHILD xmlns:xyz="h:/x.y.z" xmlns:ijk="h:/i.j.k" CDEF="2222" ijk:LMNO="3333" />
</ROOT>
<ROOT xmlns:ijk="h:/i.j.k" RSTU="1111">
  <CHILD CDEF="2222" LMNO="3333" />
</ROOT>
结果:

<ROOT xmlns:xyz="h:/x.y.z" xmlns:ijk="h:/i.j.k" RSTU="1111">
    <CHILD xmlns:xyz="h:/x.y.z" xmlns:ijk="h:/i.j.k" CDEF="2222" ijk:LMNO="3333" />
</ROOT>
<ROOT xmlns:ijk="h:/i.j.k" RSTU="1111">
  <CHILD CDEF="2222" LMNO="3333" />
</ROOT>
Msg 6846,第16级,状态2,第34行
XML列名“ijk:LMNO”缺少XML名称空间前缀“ijk”声明

是否可以编写生成XML的T-SQL FOR XML查询,其中:

  • 命名空间仅在根元素中定义,并且

  • 根元素具有命名空间定义以外的数据属性,并且

  • 在子元素的属性名称中使用对命名空间的引用

  • 我复习了。在本主题中,根元素只有名称空间定义,没有数据属性。

    您的结果如何

    <ROOT xmlns:xyz="h:/x.y.z" xmlns:ijk="h:/i.j.k" RSTU="1111">
        <CHILD xmlns:xyz="h:/x.y.z" xmlns:ijk="h:/i.j.k" CDEF="2222" ijk:LMNO="3333" />
    </ROOT>
    
    
    
    似乎您有一个无关的
    xyz
    名称空间,但其余的名称空间似乎有效。定义名称空间与将名称空间应用于元素或属性不同,如果未应用已定义的名称空间,则可以忽略它们(即,在
    LMNO
    元素上预先添加)。两次定义名称空间是多余的,但不应无效

    XML是一个很挑剔的标准,所以可能真正需要验证的是XML


    当然,这不会改变您的问题,但正如验证器有奇怪的期望一样,许多XML生成器在可选值上没有提供这种灵活性。他们通常采用“这就是你得到的”方法。

    这很难看,但却是一种解决办法

    SELECT
        CAST(REPLACE(CAST(
        (SELECT
        [xmlns:xyz] = 'h:/x.y.z',
        [xmlns:ijk] = 'h:/i.j.k',
        [RSTU] = 1111,
        (SELECT
             [@CDEF] = 2222, [@ns_ijk_LMNO] = 3333
         FOR XML PATH('ROOT'), TYPE)
         FOR XML RAW('CHILD'), TYPE) AS NVARCHAR(MAX)),'ns_ijk_','ijk:') AS XML);
    
    结果

    <CHILD xmlns:xyz="h:/x.y.z" xmlns:ijk="h:/i.j.k" RSTU="1111">
      <ROOT CDEF="2222" ijk:LMNO="3333" />
    </CHILD>
    
    
    
    通过使用外部
    SELECT
    RAW
    模式,可以像放置属性一样放置名称空间声明

    XML路径的内部
    将不使用这些名称空间(使用
    和XMLNAMESPACES
    的其他行为),但不可能在其中使用名称空间前缀

    因此,我在属性名中添加了一些内容,将整个XML转换为
    NVARCHAR(MAX)
    ,替换我的虚拟对象并将其转换回

    请去投票。这真烦人


    重复的名称空间(使用子选择时)没有错误,但会使输出膨胀,并且可能在验证程序中发生冲突

    可能的副本请访问、登录并投票。带有子选择项的重复名称空间是几个世纪以来的故事…@Shnugo。我尝试了连接问题,但是连接被关闭,现在处于只读模式,所以,唉,我不能投票支持这些微软人!他们尽一切努力保持这一开放性:-DI包含了无关的
    xyz
    命名空间,因为我发布到的Web服务要求我在根目录中包含XML文档中未显式引用的命名空间定义。是的,我知道我可以进入字符模式并“润色”XML,但我之所以避免这样做,是因为以下原因:1)当我坚持使用纯
    for XML
    时,我总是得到格式良好的XML。2) 字符数据和T-SQL内部结构化xml存储之间的来回切换会影响性能。3) 这太差劲了,这是很光荣的,但是你会迷路的。。。后退和用力可能有副作用,但不应造成任何伤害。格式良好的XML保持格式良好。这是缓慢和丑陋的,但唯一的办法。