sql—如何在for xml path中将属性放在根元素上,而只放在根元素上?

7xllpg7q  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(360)

我正在从SQLServer表生成xml。
这是我的密码:

;WITH XMLNAMESPACES
( 
     'http://www.w3.org/2001/XMLSchema-instance' AS xsi 
    --,DEFAULT 'http://www.w3.org/2001/XMLSchema-instance'  -- xmlns 
) 
SELECT 
    'T_Contracts' AS "@tableName",
    (SELECT * FROM T_Contracts 
     FOR XML PATH('row'), TYPE, ELEMENTS xsinil)
FOR XML PATH('table'), TYPE, ELEMENTS xsinil

我希望结果如下所示(注:属性 tableName 在根元素上):

<table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" tableName="T_Contracts">
  <row>
    <VTR_UID>779FE899-4E81-4D8C-BF9B-3F17BC1DF146</VTR_UID>
    <VTR_MDT_ID>0</VTR_MDT_ID>
    <VTR_VTP_UID xsi:nil="true" />
    <VTR_Nr>0050/132251</VTR_Nr>
  </row>
</table>

但是它在row元素上复制了xsi名称空间。。。

<table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" tableName="T_Contracts">
  <row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <VTR_UID>779FE899-4E81-4D8C-BF9B-3F17BC1DF146</VTR_UID>
    <VTR_MDT_ID>0</VTR_MDT_ID>
    <VTR_VTP_UID xsi:nil="true" />
    <VTR_Nr>0050/132251</VTR_Nr>
  </row>
</table>

将属性添加到根元素并且只添加到根元素的正确方法是什么?
笔记
空值必须作为 <columnName xsi:nil="true" /> 不能省略。
(没有 xml.modify 选择后)
请注意,这不是现有问题的重复。

jaql4c8m

jaql4c8m1#

这种带有子查询的重复名称空间的恼人行为在msconnect上被报道了10多年,获得了数千张选票。这个平台被驳回了,这个问题也被驳回了,微软也没有办法解决这个问题。
公平地说:重复名称空间声明并没有错。它只是膨胀了基于字符串的输出。。。
更奇怪的是根级别节点上不支持的属性。。。
好吧,如果你需要头痛,你可以去看看 OPTION EXPLICIT :-)
马克·吉洛特接受的答案不会产生 xsi:nil="true" 你需要的属性。它只会用适当的根节点 Package 结果。
最后:xml方法无法解决此问题,您可以尝试以下方法:
更新:找到一个方法,见下文。。。

DECLARE @tbl TABLE(ID INT,SomeValue INT);
INSERT INTO @tbl VALUES(1,1),(2,NULL);

SELECT CAST(REPLACE(CAST(
(
    SELECT *
    FROM @tbl 
    FOR XML PATH('row'),ROOT('table'),TYPE, ELEMENTS XSINIL
) AS nvarchar(MAX)),'<table ','<table tableName="T_Contracts" ') AS XML);

结果呢

<table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" tableName="T_Contracts">
  <row>
    <ID>1</ID>
    <SomeValue>1</SomeValue>
  </row>
  <row>
    <ID>2</ID>
    <SomeValue xsi:nil="true" />
  </row>
</table>

简而言之:
我们创建不带子查询的xml,并将带有string方法的属性添加到casted xml中。
由于属性的位置并不重要,我们可以在任何地方添加它。
或者,您可以搜索第一个结束语 > 使用 STUFF() 在那里。。。
更新
heureka,我刚找到一种方法,不用用弦来做这个,但很笨拙:-)

DECLARE @tbl TABLE(ID INT,SomeValue INT);
INSERT INTO @tbl VALUES(1,1),(2,NULL);

SELECT
(
SELECT 'T_Contracts' AS [@tableName]
      ,(
        SELECT 'SomeRowAttr' AS [@testAttr] --added this to test row-level attributes
              ,*
        FROM @tbl 
        FOR XML PATH('row'),TYPE, ELEMENTS XSINIL
       )
FOR XML PATH('table'),TYPE, ELEMENTS XSINIL
).query('<table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">{/table/@*}
         {
            for $nd in /table/row
            return
            <row>{$nd/@*}
            {
                $nd/*
            }
            </row>
         }
         </table>');

结果呢

<table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" tableName="T_Contracts">
  <row testAttr="SomeRowAttr">
    <ID>1</ID>
    <SomeValue>1</SomeValue>
  </row>
  <row testAttr="SomeRowAttr">
    <ID>2</ID>
    <SomeValue xsi:nil="true" />
  </row>
</table>
yduiuuwa

yduiuuwa2#

为什么不手动构建根元素?
例子:

with CTE as (
  select (select * from T_Contracts for xml path('row')) as MyXML
)
select '<table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" tableName="T_Contracts">' +
        MyXML + 
        '</table>'  
from CTE

相关问题