从 SQL 服务器或 powerBuilder 中的主详细信息行创建 XML

Create XML from Master detail rows in SQL Server or powerBuilder

我有来自 SQL 服务器的主详细数据,如下所示,并希望按照以下格式生成 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 服务器中生成输出吗?

这是一个基于 XQuery FLWOR 表达式的解决方案。

它是一个 T-SQL 语句中的两步过程。

首先,为了模拟 master/details 结构,我们创建了一个原始的 XML,它将主数据作为属性,将详细信息作为元素。其次,我们通过 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>)
');

Output

<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>