有一个删除命名空间here的解决方案!,但我需要它在SQL函数中工作,我收到此错误:
FOR XML子句在视图,内联函数,派生表和子查询中包含set运算符时无效。要解决此问题,请使用派生表语法包装包含set运算符的SELECT,并在其上应用FOR XML。
有人能帮助我吗?
谢谢Xtyan
来自评论:这是所需的XML输出
<zoo xmlns:an="uri:animal">
<an:animal species="Mouse">
<an:legs>
<an:leg>Front Right</an:leg>
<an:leg>Front Left</an:leg>
<an:leg>Back Right</an:leg>
<an:leg>Back Left</an:leg>
</an:legs>
</an:animal>
<an:animal species="Chicken">
<an:legs>
<an:leg>Right</an:leg>
<an:leg>Left</an:leg>
</an:legs>
</an:animal>
<an:animal species="Snake" />
</zoo>
答案 0 :(得分:0)
你可能不会喜欢这个...
我没有为此找到通用的解决方案......使用重复的命名空间创建它是没有问题的。这没错,但很讨厌:
declare @xml as xml;
WITH XMLNAMESPACES('uri:animal' as an)
select @xml = (
select
a.c2 as "@an:species"
, (
select l.c3 as "text()"
from t2 l where l.c2 = a.c1
for xml path('an:leg'), type
) as "an:legs"
from t1 a
for xml path('an:animal'),root('zoo'));
但这太丑了......
以下解决方案使用FLWOR
在创建XML后重新创建XML,但这不是通用的。有必要将此命名空间的一个元素添加到<zoo>
,否则将在更深层次上重复创建命名空间。我添加了attribut an:Dummy
。
create table t1 ( c1 int, c2 varchar(50))
create table t2 ( c1 int, c2 int, c3 varchar(50))
insert t1 values
(1, 'Mouse'),
(2, 'Chicken'),
(3, 'Snake');
insert t2 values
(1, 1, 'Front Right'),
(2, 1, 'Front Left'),
(3, 1, 'Back Right'),
(4, 1, 'Back Left'),
(5, 2, 'Right'),
(6, 2, 'Left');
GO
--the function
CREATE FUNCTION dbo.TestFunc()
RETURNS XML
AS
BEGIN
declare @xml as xml;
WITH XMLNAMESPACES('uri:animal' as an)
select @xml = (
select
a.c2 as "@an:species"
, (
select l.c3 as "text()"
from t2 l where l.c2 = a.c1
for xml path('an:leg'), type
) as "an:legs"
from t1 a
for xml path('an:animal'));
set @xml=@xml.query('declare namespace an="uri:animal";
<zoo an:Dummy="dummy">
{
for $a in /an:animal
return <an:animal an:species="{$a/@an:species}"><an:legs>
{
for $l in $a/an:legs/an:leg
return <an:leg>{$l/text()}</an:leg>
}
</an:legs></an:animal>
}
</zoo>');
return @xml;
END
GO
--the call
SELECT dbo.TestFunc();
GO
--clean up
drop function dbo.TestFunc;
drop table t1
drop table t2
结果
<zoo xmlns:an="uri:animal" an:Dummy="dummy">
<an:animal an:species="Mouse">
<an:legs>
<an:leg>Front Right</an:leg>
<an:leg>Front Left</an:leg>
<an:leg>Back Right</an:leg>
<an:leg>Back Left</an:leg>
</an:legs>
</an:animal>
<an:animal an:species="Chicken">
<an:legs>
<an:leg>Right</an:leg>
<an:leg>Left</an:leg>
</an:legs>
</an:animal>
<an:animal an:species="Snake">
<an:legs />
</an:animal>
</zoo>
好吧,我想我在第一次尝试时完全错了。以下是一个示例,其中函数返回XML而不添加名称空间。
我使用后面的一个答案,它提前构建内部XML而没有命名空间,并创建完整的XML作为第二次使用命名空间调用。请检查一下:
create table t1 ( c1 int, c2 varchar(50))
create table t2 ( c1 int, c2 int, c3 varchar(50))
insert t1 values
(1, 'Mouse'),
(2, 'Chicken'),
(3, 'Snake');
insert t2 values
(1, 1, 'Front Right'),
(2, 1, 'Front Left'),
(3, 1, 'Back Right'),
(4, 1, 'Back Left'),
(5, 2, 'Right'),
(6, 2, 'Left');
GO
- 功能
CREATE FUNCTION dbo.TestFunc()
RETURNS XML
AS
BEGIN
declare @xml as xml;
select @xml = (
select
a.c2 as "@species"
, (select l.c3 as "text()"
from t2 l where l.c2 = a.c1
for xml path('leg'), type) as "legs"
from t1 a
for xml path('animal'));
declare @resultXML XML;
;with XmlNamespaces( 'uri:animal' as an)
select @ResultXML= (SELECT @xml for xml path('') , root('zoo'),TYPE);
return @resultXML;
END
GO
- 电话
SELECT dbo.TestFunc();
GO
- 清理
drop function dbo.TestFunc;
drop table t1
drop table t2
结果
<zoo xmlns:an="uri:animal">
<animal species="Mouse">
<legs>
<leg>Front Right</leg>
<leg>Front Left</leg>
<leg>Back Right</leg>
<leg>Back Left</leg>
</legs>
</animal>
<animal species="Chicken">
<legs>
<leg>Right</leg>
<leg>Left</leg>
</legs>
</animal>
<animal species="Snake" />
</zoo>