SQL中生成的XML结构不正确

SQL中生成的XML结构不正确,sql,sql-server,xml,xml-namespaces,for-xml-path,Sql,Sql Server,Xml,Xml Namespaces,For Xml Path,Iv还有另一个问题,我只是将我的UNION更改为UNION ALL,它工作正常,但我想在开始时添加另一个XML路径-这将是两个查询的常量 (SELECT 1 AS "ns0:kindOfItem", code AS "ns0:wholeCode", REPLACE(weight, ',', '.') AS "ns0:weight", 1 AS "ns0:ammountOfNumbers", (SELECT price AS "ns0:value", 'EUR' as "ns0:currency"

Iv还有另一个问题,我只是将我的UNION更改为UNION ALL,它工作正常,但我想在开始时添加另一个XML路径-这将是两个查询的常量

(SELECT 1 AS "ns0:kindOfItem",
code AS "ns0:wholeCode",
REPLACE(weight, ',', '.') AS "ns0:weight",
1 AS "ns0:ammountOfNumbers",
(SELECT price AS "ns0:value",
'EUR' as "ns0:currency"
FOR XML PATH ('ns0:sendedItems'), TYPE),
(SELECT 
'EUR' as "ns0:currency"
FOR XML PATH ('ns0:present'), TYPE)
FROM [PL].[dbo].[dk_documents] where id in (1,2,3)

UNION ALL

(SELECT 1 AS "ns0:kindOfItem",
code AS "ns0:wholeCode",
REPLACE(weight, ',', '.') AS "ns0:weight",
1 AS "ns0:ammountOfNumbers",
(SELECT price AS "ns0:value",
'EUR' as "ns0:currency"
FOR XML PATH ('ns0:sendedItems'), TYPE),
(SELECT 
'EUR' as "ns0:currency"
FOR XML PATH ('ns0:present'), TYPE)
FROM [PL2].[dbo].[dk_documents] where id in (1,2,3)
FOR XML PATH('test'))
它工作正常,但我想要这样的东西:

SELECT 1 as test,
(SELECT 1 AS "ns0:kindOfItem",
code AS "ns0:wholeCode",
REPLACE(weight, ',', '.') AS "ns0:weight",
1 AS "ns0:ammountOfNumbers",
(SELECT price AS "ns0:value",
'EUR' as "ns0:currency"
FOR XML PATH ('ns0:sendedItems'), TYPE),
(SELECT 
'EUR' as "ns0:currency"
FOR XML PATH ('ns0:present'), TYPE)
FROM [PL].[dbo].[dk_documents] where id in (1,2,3)

UNION ALL

(SELECT 1 AS "ns0:kindOfItem",
code AS "ns0:wholeCode",
REPLACE(weight, ',', '.') AS "ns0:weight",
1 AS "ns0:ammountOfNumbers",
(SELECT price AS "ns0:value",
'EUR' as "ns0:currency"
 FOR XML PATH ('ns0:sendedItems'), TYPE),
(SELECT 
'EUR' as "ns0:currency"
FOR XML PATH ('ns0:present'), TYPE)
FROM [PL2].[dbo].[dk_documents] where id in (1,2,3)
FOR XML PATH('test'))
FOR XML PATH('anotherPath')
我得到了这个错误:

    Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
输出应该是

   <test>1</test>
     <>All of tese columns from QUERY with union ALL</>
它给了我一个输出:

 <test xmlns="Dummy">
   <test>1</test>
   <anotherOne>2</anotherOne>
   <id xmlns="Dummy">1</id>
   <symbol xmlns="Dummy">test10</symbol>
   <id xmlns="Dummy">2</id>
   <symbol xmlns="Dummy">test10</symbol>
   <id xmlns="Dummy">3</id>
   <symbol xmlns="Dummy">test10</symbol>
   <id xmlns="Dummy">4</id>
   <symbol xmlns="Dummy">test11</symbol>
   <id xmlns="Dummy">5</id>
   <symbol xmlns="Dummy">test11</symbol>
   <id xmlns="Dummy">6</id>
   <symbol xmlns="Dummy">test11</symbol>
</test>
我想:

  <test xmlns="Dummy">
    <test>1</test>
    <anotherOne>2</anotherOne>
      <id>1</id>
      <symbol>test10</symbol>
      <id>2</id>
      <symbol>test10</symbol>
      <id>3</id>
      <symbol>test10</symbol>
      <id>4</id>
      <symbol>test11</symbol>
      <id>5</id>
      <symbol>test11</symbol>
      <id>6</id>
      <symbol>test11</symbol>
  </test>

您可以测试下面的SQL Select语句

我希望有帮助

declare @xml xml
declare @xml1 xml
set @xml1 = '<test>1</test>'
declare @xml2 xml
set @xml2 = ( select top 4 name from sys.databases FOR XML PATH('database') )
set @xml = (SELECT @xml1, @xml2 FOR XML PATH(''))
select  @xml
输出将如下所示

正如在您的网站上指出的,重复的名称空间并没有错,只是令人讨厌,而且-如果有很多长的URI,它们会将您的XML扩展到惊人的大小

在那里我放置了一个链接到一个已经存在的。诀窍是创建不带名称空间的XML,并将名称空间添加到finally SELECT。。。仅适用于XML路径:

但我必须承认,经过长时间的尝试和错误,我发现,如果涉及默认名称空间,似乎存在一个bug。我尝试的任何方法都会导致重复的命名空间声明或重复的空命名空间声明

所以我能找到的唯一解决办法就是我现在去洗我的手指:-:

DECLARE @table1 TABLE(id INT,symbol VARCHAR(100));
INSERT INTO @table1 VALUES
 (1,'Test 1')
,(2,'Test 2')
,(3,'Test 3')
,(4,'Test 4');

DECLARE @nordic_table2 TABLE(id INT,nrdok VARCHAR(100));
INSERT INTO @nordic_table2 VALUES
 (1,'Test 1')
,(2,'Test 2')
,(3,'Test 3')
,(4,'Test 4');


DECLARE @XmlWithoutNamespace XML=
(
 SELECT 1 as test
       ,2 as anotherOne
       ,(
           SELECT * 
           FROM 
           (
            SELECT id, symbol  from @table1
            WHERE id in (1,2,3)
            UNION ALL
            SELECT id, nrdok from @nordic_table2
            WHERE id in (4,5,6)
           ) AS yolo
           FOR XML PATH(''),TYPE
       )
 FOR XML PATH('')
);

SELECT
CAST(
    '<test xmlns="Dummy">'
    +
    CAST(@XmlWithoutNamespace AS NVARCHAR(MAX))
    +
    '</test>'
AS XML);
结果将是这样,这是更好地阅读和查询

<test xmlns="Dummy">
  <test>1</test>
  <anotherOne>2</anotherOne>
  <symbol id="1">Test 1</symbol>
  <symbol id="2">Test 2</symbol>
  <symbol id="3">Test 3</symbol>
  <symbol id="4">Test 4</symbol>
</test>
结果如何

<test xmlns="Dummy" xmlns:abc="SomeTestUri">
  <abc:test>1</abc:test>
  <anotherOne>2</anotherOne>
  <abc:symbol abc:id="1">Test 1</abc:symbol>
  <abc:symbol abc:id="2">Test 2</abc:symbol>
  <abc:symbol abc:id="3">Test 3</abc:symbol>
  <abc:symbol abc:id="4">Test 4</abc:symbol>
</test>

您缺少XML路径“test”的输入。为了获得更好的答案,请提供一个包含可直接测试的示例数据的自包含脚本。此SO问题的问题和解决方案:您确定这是您想要/需要的结构吗?对我来说,这很奇怪。也许,对于第二个测试,您应该使用这样的东西…<问题是关于重复的名称空间声明以及如何避免它们,您的答案甚至没有涉及到这一点……是的,但我不能使用前缀,例如。然后我不能像ns0:test那样使用它,因为这告诉我我没有声明前缀。请查看您发送给您的电子邮件,以便通过profileHi@Pro100与您联系,请参阅我的更新2
<test xmlns="Dummy">
  <test>1</test>
  <anotherOne>2</anotherOne>
  <symbol id="1">Test 1</symbol>
  <symbol id="2">Test 2</symbol>
  <symbol id="3">Test 3</symbol>
  <symbol id="4">Test 4</symbol>
</test>
--Just a container to collect the XML parts
DECLARE @CollectXML TABLE(ID INT IDENTITY,Content XML,CleanedAsString NVARCHAR(MAX));

--The final ",ROOT('xyz')" will force the namespace's declaration into the root node
WITH XMLNAMESPACES('SomeTestUri' AS abc)
INSERT INTO @CollectXML(Content)
SELECT
(
     SELECT 1 as [abc:test]
           ,2 as anotherOne
     FOR XML PATH(''),ROOT('xyz'),TYPE
);
--No we use ugly string manipulation to cut out the inner part without the namespace declaration
UPDATE @CollectXML SET CleanedAsString=
(
    SELECT Rest
    FROM @CollectXML
    CROSS APPLY (SELECT CAST(Content AS NVARCHAR(MAX))) AS Casted(XmlAsString)
    CROSS APPLY (SELECT REVERSE(SUBSTRING(XmlAsString,CHARINDEX('>',XmlAsString)+1,LEN(XmlAsString)))) AS Cut1(part1Reverse)
    CROSS APPLY (SELECT REVERSE(SUBSTRING(part1Reverse,CHARINDEX('<',part1Reverse)+1,LEN(part1Reverse)))) AS Cut2(Rest)
    WHERE ID=1
)
WHERE ID=1;

--The same with the second part
WITH XMLNAMESPACES('SomeTestUri' AS abc)
INSERT INTO @CollectXML(Content)
SELECT 
(
    SELECT id AS [@abc:id]
          ,symbol AS [*]
    FROM 
    (
    SELECT id, symbol  from @table1
    WHERE id in (1,2,3)
    UNION ALL
    SELECT id, nrdok from @nordic_table2
    WHERE id in (4,5,6)
    ) AS yolo
    FOR XML PATH('abc:symbol'),ROOT('xyz'),TYPE --the not needed root will take the namespace declaration out of the deeper elements
);
--and the ugly string manipulation
UPDATE @CollectXML SET CleanedAsString=
(
    SELECT Rest
    FROM @CollectXML
    CROSS APPLY (SELECT CAST(Content AS NVARCHAR(MAX))) AS Casted(XmlAsString)
    CROSS APPLY (SELECT REVERSE(SUBSTRING(XmlAsString,CHARINDEX('>',XmlAsString)+1,LEN(XmlAsString)))) AS Cut1(part1Reverse)
    CROSS APPLY (SELECT REVERSE(SUBSTRING(part1Reverse,CHARINDEX('<',part1Reverse)+1,LEN(part1Reverse)))) AS Cut2(Rest)
    WHERE ID=2
)
WHERE ID=2;

--The XML is put together and - as the very last step! - casted back to XML
SELECT
CAST(
    '<test xmlns="Dummy" xmlns:abc="SomeTestUri">'
    +
    (SELECT CleanedAsString FROM @CollectXML WHERE ID=1)
    +
    (SELECT CleanedAsString FROM @CollectXML WHERE ID=2)
    +
    '</test>'
AS XML);
<test xmlns="Dummy" xmlns:abc="SomeTestUri">
  <abc:test>1</abc:test>
  <anotherOne>2</anotherOne>
  <abc:symbol abc:id="1">Test 1</abc:symbol>
  <abc:symbol abc:id="2">Test 2</abc:symbol>
  <abc:symbol abc:id="3">Test 3</abc:symbol>
  <abc:symbol abc:id="4">Test 4</abc:symbol>
</test>