我有来自SQL Server的主数据,如下图所示,我想按照以下格式生成XML,并从PowerBuilder以SOAP XML的形式发送。
CREATE TABLE dbo.Orders
(
OrderNo varchar(10) NOT NULL,
PakDesc varchar(50) NOT NULL
)
GO
INSERT INTO Orders values('11111','Test1' )
GO
CREATE TABLE dbo.Components
(
OrderNo varchar(10) NOT NULL,
CompNo varchar(10) NOT NULL,
CompDesc varchar(50) NOT NULL,
Qty int NOT NULL
)
GO
INSERT INTO Components values('11111','01234', 'Comp1', 10 )
INSERT INTO Components values('11111','56789', 'Comp2', 5 )
GO
希望的XML输出
<entrylist>
<name>OrderNo</name>
<value>11111</value>
</entrylist>
<entrylist>
<name>PakDesc</name>
<value>Test1</value>
</entrylist>
<entrylist>
<name>CompNo1</name>
<value>01234</value>
</entrylist>
<entrylist>
<name>CompDesc1</name>
<value>Comp1</value>
</entrylist>
<entrylist>
<name>Qty1</name>
<value>10</value>
</entrylist>
<entrylist>
<name>CompNo2</name>
<value>56789</value>
</entrylist>
<entrylist>
<name>CompDesc2</name>
<value>Comp2</value>
</entrylist>
<entrylist>
<name>Qty2</name>
<value>5</value>
</entrylist>
在PowerBuilder中,我在Datawindow中得到这些数据,我可以浏览每一行和每一列,并使用CREATE PBDOM_Element创建一个XML元素。
但我想知道,如果有任何其他方式,我可以很容易地生成类似的XML?这可以在SQL Server中生成像这样的输出?
这是一个基于XQuery FLWOR表达式的解决方案。
这是一个两步的过程,在一个单一的T-SQL语句。
首先,为了模拟masterdetails结构,我们创建一个原始的XML,将master数据作为属性,将细节作为元素。其次,我们通过FLWOR表达式来塑造最终输出的XML。
SQL
-- DDL and sample data population, start
DECLARE @Orders TABLE (OrderNo varchar(10) NOT NULL, PakDesc varchar(50) NOT NULL);
INSERT INTO @Orders values('11111','Test1' );
DECLARE @Components TABLE
(
ID INT IDENTITY(1,1) PRIMARY KEY,
OrderNo varchar(10) NOT NULL,
CompNo varchar(10) NOT NULL,
CompDesc varchar(50) NOT NULL,
Qty int NOT NULL
);
INSERT INTO @Components VALUES
('11111','01234', 'Comp1', 10 )
,('11111','56789', 'Comp2', 5 );
-- DDL and sample data population, end
SELECT
(
SELECT o.OrderNo AS [@OrderNo], o.PakDesc AS [@PakDesc]
--, c.ID AS [@ID]
, ROW_NUMBER() OVER(ORDER BY o.OrderNo) AS [@ID]
, c.CompNo, c.CompDesc, c.Qty
FROM @Orders AS o LEFT OUTER JOIN
@Components AS c ON c.OrderNo = o.OrderNo
FOR XML PATH('r'), TYPE, ROOT('root')
).query('
for $y in /root/r (: master level :)
let $index := $y/@ID
return (if ($index eq 1) then
(
for $z in $y/@*[local-name(.) ne "ID"] (: all attributes except @ID :)
return <entrylist>
<name>{local-name($z)}</name>
<value>{data($z)}</value>
</entrylist>
)
else ()
,
for $x in $y/* (: details level :)
return <entrylist>
<name>{concat(local-name($x), $index)}</name>
<value>{data($x)}</value>
</entrylist>)
');
产量
<entrylist>
<name>OrderNo</name>
<value>11111</value>
</entrylist>
<entrylist>
<name>PakDesc</name>
<value>Test1</value>
</entrylist>
<entrylist>
<name>CompNo1</name>
<value>01234</value>
</entrylist>
<entrylist>
<name>CompDesc1</name>
<value>Comp1</value>
</entrylist>
<entrylist>
<name>Qty1</name>
<value>10</value>
</entrylist>
<entrylist>
<name>CompNo2</name>
<value>56789</value>
</entrylist>
<entrylist>
<name>CompDesc2</name>
<value>Comp2</value>
</entrylist>
<entrylist>
<name>Qty2</name>
<value>5</value>
</entrylist>