Reputation: 1739
I am trying to create an XML output using SQL. I am able to do it fine with basic lists, but not with list in lists. Basic Structure:
CREATE TABLE #TEMP1 ( ID1 INT
,Names VARCHAR(10)
,Address VARCHAR(50)
)
Create Table #TEMP2 ( ID2 INT
,ID1 INT
,ITEM VARCHAR(10)
,Quantity INT
)
INSERT INTO #TEMP1 (ID1,Names,Address)
VALUES (1,'Jack','Main St')
,(2,'Jill','Second St')
,(3,'Hill','3rd St')
INSERT INTO #TEMP2(ID2,ID1,ITEM,Quantity)
Values (1,1,'Curds',20)
,(2,2,'Way',30)
,(3,2,'Curds',40)
,(4,3,'Curds',50)
,(5,3,'Curds',60)
,(6,3,'Curds',70)
When I run the below XML, I get the desired result:
SELECT ID1 CusID
,Names CusName
,Address PrimAddress
FROM #TEMP1 Customer
FOR XML AUTO, ELEMENTS
<Customer>
<CusID>1</CusID>
<CusName>Jack</CusName>
<PrimAddress>Main St</PrimAddress>
</Customer>
<Customer>
<CusID>2</CusID>
<CusName>Jill</CusName>
<PrimAddress>Second St</PrimAddress>
</Customer>
<Customer>
<CusID>3</CusID>
<CusName>Hill</CusName>
<PrimAddress>3rd St</PrimAddress>
</Customer>
The problem occurs when I try to add the orders (#TEMP2) into the mix.
SELECT ID1 CusID
,Names CusName
,Address PrimAddress
,(SELECT ID2 PRODUCTID
,ITEM PRODUCTNAME
,Quantity
FROM #TEMP2 Items
where ID1 = Customer.ID1
FOR XML AUTO, ELEMENTS)
FROM #TEMP1 Customer
FOR XML AUTO, ELEMENTS
OutPut has a bunch of special character symbols instead of clean XML:
<Customer>
<CusID>1</CusID>
<CusName>Jack</CusName>
<PrimAddress>Main St</PrimAddress><Items><PRODUCTID>1</PRODUCTID><PRODUCTNAME>Curds</PRODUCTNAME><Quantity>20</Quantity></Items></Customer>
<Customer>
<CusID>2</CusID>
<CusName>Jill</CusName>
<PrimAddress>Second St</PrimAddress><Items><PRODUCTID>2</PRODUCTID><PRODUCTNAME>Way</PRODUCTNAME><Quantity>30</Quantity></Items><Items><PRODUCTID>3</PRODUCTID><PRODUCTNAME>Curds</PRODUCTNAME><Quantity>40</Quantity></Items></Customer>
<Customer>
<CusID>3</CusID>
<CusName>Hill</CusName>
<PrimAddress>3rd St</PrimAddress><Items><PRODUCTID>4</PRODUCTID><PRODUCTNAME>Curds</PRODUCTNAME><Quantity>50</Quantity></Items><Items><PRODUCTID>5</PRODUCTID><PRODUCTNAME>Curds</PRODUCTNAME><Quantity>60</Quantity></Items><Items><PRODUCTID>6</PRODUCTID><PRODUCTNAME>Curds</PRODUCTNAME><Quantity>70</Quantity></Items></Customer>
Desired outcome is something like the below. May not be perfect XML, but the main point is to remove all the special characters (not trying to do a replace or something like that) :
<Customer>
<CusID>1</CusID>
<CusName>Jack</CusName>
<PrimAddress>Main St</PrimAddress>
<Items>
<PRODUCTID>1</PRODUCTID>
<PRODUCTNAME>Curds</PRODUCTNAME>
<Quantity>20</Quantity>
</Items>
</Customer>
<Customer>
<CusID>2</CusID>
<CusName>Jill</CusName>
<PrimAddress>Second St</PrimAddress>
<Items>
<Item></Item>
<PRODUCTID>2</PRODUCTID>
<PRODUCTNAME>Way</PRODUCTNAME>
<Quantity>30</Quantity>
</Item>
</Items>
<Items>
<PRODUCTID>3</PRODUCTID>
<PRODUCTNAME>Curds</PRODUCTNAME>
<Quantity>40</Quantity>
</Items>
</Customer>
Upvotes: 2
Views: 1407
Reputation: 67291
I think it's this you are looking for:
CREATE TABLE #TEMP1 ( ID1 INT
,Names VARCHAR(10)
,Address VARCHAR(50)
)
Create Table #TEMP2 ( ID2 INT
,ID1 INT
,ITEM VARCHAR(10)
,Quantity INT
)
INSERT INTO #TEMP1 (ID1,Names,Address)
VALUES (1,'Jack','Main St')
,(2,'Jill','Second St')
,(3,'Hill','3rd St')
INSERT INTO #TEMP2(ID2,ID1,ITEM,Quantity)
Values (1,1,'Curds',20)
,(2,2,'Way',30)
,(3,2,'Curds',40)
,(4,3,'Curds',50)
,(5,3,'Curds',60)
,(6,3,'Curds',70);
SELECT ID1 AS CusID
,Names AS CusName
,[Address] AS PrimAddress
,(SELECT items.ID2 AS PRODUCTID
,items.ITEM AS PRODUCTNAME
,items.Quantity
FROM #TEMP2 Items
WHERE items.ID1 = Customer.ID1
FOR XML PATH('Item'),ROOT('Items'), TYPE) AS [*]
FROM #TEMP1 Customer
FOR XML PATH('Customer'),ROOT('Customers');
The result
<Customers>
<Customer>
<CusID>1</CusID>
<CusName>Jack</CusName>
<PrimAddress>Main St</PrimAddress>
<Items>
<Item>
<PRODUCTID>1</PRODUCTID>
<PRODUCTNAME>Curds</PRODUCTNAME>
<Quantity>20</Quantity>
</Item>
</Items>
</Customer>
<Customer>
<CusID>2</CusID>
<CusName>Jill</CusName>
<PrimAddress>Second St</PrimAddress>
<Items>
<Item>
<PRODUCTID>2</PRODUCTID>
<PRODUCTNAME>Way</PRODUCTNAME>
<Quantity>30</Quantity>
</Item>
<Item>
<PRODUCTID>3</PRODUCTID>
<PRODUCTNAME>Curds</PRODUCTNAME>
<Quantity>40</Quantity>
</Item>
</Items>
</Customer>
<Customer>
<CusID>3</CusID>
<CusName>Hill</CusName>
<PrimAddress>3rd St</PrimAddress>
<Items>
<Item>
<PRODUCTID>4</PRODUCTID>
<PRODUCTNAME>Curds</PRODUCTNAME>
<Quantity>50</Quantity>
</Item>
<Item>
<PRODUCTID>5</PRODUCTID>
<PRODUCTNAME>Curds</PRODUCTNAME>
<Quantity>60</Quantity>
</Item>
<Item>
<PRODUCTID>6</PRODUCTID>
<PRODUCTNAME>Curds</PRODUCTNAME>
<Quantity>70</Quantity>
</Item>
</Items>
</Customer>
</Customers>
Upvotes: 1
Reputation: 1739
Would have liked to see it add in the logic for looping throught the Items, but this works I think.
Select
(SELECT ID1 CusID
,Names CusName
,Address PrimAddress
,(SELECT ID2 PRODUCTID
,ITEM PRODUCTNAME
,Quantity
FROM #TEMP2 Items
where ID1 = Customer.ID1
FOR XML PATH(''), TYPE, ELEMENTS) AS Items
FROM #TEMP1 Customer
FOR XML AUTO, ELEMENTS)
Thanks too : https://www.codeproject.com/Articles/54584/Controlling-the-XML-output-when-using-the-FOR-XML
Upvotes: 0