Read XML file to datatables using c# asp.net - sql

I want to read XML file and bulk copy to database
My xml is like :
<products>
<product>
<id>1</id>
<name>product one</name>
<subproducts>
<subproduct>
<color>Red</color>
<stock>1</stock>
</subproduct>
<subproduct>
<color>Green</color>
<stock>2</stock>
</subproduct>
</subproducts>
<images>
<image>http://qwqeq.com</image>
<image>http://asdasd.com</image>
</images>
</product>
</products>
I want to get three datatables which are for products, subproducts and images and will try to bulk insert to the database.
How can i aschieve this ?

The way you have tried must be something like below,
DataSet objDataSet = new DataSet();
objDataSet.ReadXml("FilePath.xml");
It just groups the nodes and forms tables.
You need to do something which is explained well in the below link.
http://csharp.net-informations.com/xml/how-to-read-xml.htm
Hope this helps!

You can pass the XML into a stored procedure as XML parameter and shredd it there:
DECLARE #xml XML=
N'<products>
<product>
<id>1</id>
<name>product one</name>
<subproducts>
<subproduct>
<color>Red</color>
<stock>1</stock>
</subproduct>
<subproduct>
<color>Green</color>
<stock>2</stock>
</subproduct>
</subproducts>
<images>
<image>http://qwqeq.com</image>
<image>http://asdasd.com</image>
</images>
</product>
</products>';
SELECT p.value(N'id[1]',N'int') AS productID
,p.value(N'name[1]',N'nvarchar(max)') AS productName
,sp.value(N'color[1]','nvarchar(max)') AS subproductColor
,sp.value(N'stock[1]','int') AS subproductStock
,img.value(N'image[1]',N'nvarchar(max)') AS imageURL
--INTO #tmpTbl
FROM #xml.nodes(N'/products/product') AS A(p)
OUTER APPLY p.nodes(N'subproducts/subproduct') AS B(sp)
OUTER APPLY p.nodes(N'images') AS C(img)
The result
productID productName subproductColor subproductStock imageURL
1 product one Red 1 http://qwqeq.com
1 product one Green 2 http://qwqeq.com
Use SELECT ... INTO #tmpTbl to write the result into a staging table. Then use SELECT DISTINCT ... FROM #tmpTbl to retrieve the values for your insertion into the final structure.

Related

SQL query for XML data

I have a SQL Server database table with a column called XML that contains XML data which is structured like this:
<Item xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://test/data">
<Roots>
<Root>
<Name>Field Name</Name>
<Value>Field Value</Value>
</Root>
<Root>
<Name>Field Name</Name>
<Value>Field Value</Value>
</Root>
</Roots>
I want to use T-SQL to get the Value where Name = Total. I have tried the following but it isn't returning any data:
SELECT [XML]
FROM [BusinessAccount]
WHERE [XML].value('(/Root/Name)[13]', 'VARCHAR(MAX)') LIKE '%Total%'
If anyone could tell me where I've gone wrong?
You are missing the required WITH XMLNAMESPACES for your XML and the path is incorrect.
If you want to bring back rows where the 13th element consists of the text Total you can use the below.
WITH XMLNAMESPACES (DEFAULT 'http://test/data')
SELECT [XML]
FROM [BusinessAccount]
WHERE 1 = [XML].exist('(/Item/Roots/Root/Name)[13][text() = "Total"]')
Otherwise you can add the WITH XMLNAMESPACES to your original query and fix the path there too.
You need to specify namespaces. You can then match <Name> and <Value> pairs and extract the contents of <Value> like so:
SELECT NameNode.value('declare namespace x="http://test/data"; (../x:Value)[1]', 'varchar(100)')
FROM [BusinessAccount]
CROSS APPLY [XML].nodes('declare namespace x="http://test/data"; //x:Root/x:Name') AS n(NameNode)
WHERE NameNode.value('.', 'varchar(100)') = 'Total'
Demo on db<>fiddle

Creating xml for SQL Server stored procedure

I have a function to insert an item into the database. It takes a lot of values as input and the values are passed as XML.
Consider a sample item XML:
<ROOT>
<Item
ItemName="CarlsApplication"
ItemTypeID="2">
<TSDefaultDescription DefaultitemDescription="C:\t.text"/>
<ItemSellers>
<ComputerObject Alias="" DisplayName="" ServiceName="" UserAccount="" />
<ComputerObject Alias="" DisplayName="" ServiceName="" UserAccount="" />
</ItemSellers>
<ItemOwners>
<ItemOwner Alias="rafchen" FirstName="Rafael" LastName="Chenkov"/>
</ItemOwners>
</Item>
</ROOT>
This has to be passed to stored procedure.
Now, each of these individual values in this XML, I have to extract from somewhere else. I can get the individual values like Item name etc, but how do I organize them into an XML that can be passed?
How do I construct this XML from the values I have?
I guess I will have to make some sort of template with this format and then put variables in that template and fill the variables to prepare the template.
Any help is greatly appreciated.
If I understand what you really want, You can use a query like this to generate that XML:
select
ItemName 'Item/#ItemName', --> Node:`Item` Attribute: `ItemName`
ItemTypeId 'Item/#ItemTypeId',
cast((
select
Alias 'ComputerObject/#Alias',
DisplayName 'ComputerObject/#DisplayName',
ServiceName 'ComputerObject/#ServiceName',
UserAccount 'ComputerObject/#UserAccount'
from
ItemSellers
where
ItemSellers.ItemId = Item.ItemId
for xml path('')) as xml) 'Item/ItemSellers', --> Node:`Item` Sub-Node:`ItemSellers`
cast((
select
Alias 'ItemOwner/#Alias',
FirstName 'ItemOwner/#FirstName',
LastName 'ItemOwner/#LastName'
from
ItemOwners
where
ItemOwners.ItemId = Item.ItemId
for xml path('')) as xml) 'Item/ItemOwners'
from
Item
for xml path('ROOT');
SQL Fiddle Demo

XML Output from SQL Server 2008

I am trying to create an XML output from SQL that has 3 nested statements but have pretty minimal experience in this area. The code I've written is below:
select
replace(replace(replace(
(
select ID as [#ID],
(select cast(Name as int) as [#Name],
(select num as [#Number],
from #tbl_new_claims_export
for xml path('Num'),root('Numbers'), type
)
from #tbl_new_claims_export
for xml path('LineItem'), type
)
from #tbl_new_claims_export
for XML PATH('Line'),ROOT('Lines')
),'><','>'+char(10)+'<'),'<Num', char(9)+'<Num'), '<Num>', char(9)+'<Num>') ;
I am trying to create an output that looks like this:
<Lines>
<Line ID ="1">
<LineItem Name ="Michael"/>
<Numbers>
<Num Number="24"</Num>
</Numbers>
</LineItem>
</Line>
For each Line, I want to see the Line, Name, and Number as shown above. However, it is showing multiple Names under each Line and then repeats the Number below. Can anybody help me troubleshoot this code?
Thanks.
Without sample data with 1:n examples and the expected output it is reading in the magic glass bulb...
Anyway, this
SELECT
1 AS [Line/#ID]
,'Michael' AS [LineItem/#Name]
,24 AS [Numbers/Num/#Number]
FOR XML PATH('Lines')
will produce exactly the output you specify:
<Lines>
<Line ID="1" />
<LineItem Name="Michael" />
<Numbers>
<Num Number="24" />
</Numbers>
</Lines>
If you need further help, please specify a minimal and reduced test scenario. Best would be a fiddle or some pasteable code like
DECLARE #tbl TABLE(ID INT, col1 VARCHAR(MAX)/*more columns*/);
INSERT INTO #tbl VALUES (1,'test1')/*more values*/

count occurrence of xml child nodes from two identical parent nodes

I'm trying to count the number child nodes within two identical parent nodes in an XML clob that I've stored in a table of mine.
The XML Clob has a format like this:
<ProductS>
<id>1</id>
<Discount></Discount>
<Discount></Discount>
</ProductS>
<ProductS>
<id>2</id>
<Discount></Discount>
</ProductS>
I want my xmlquery to go through this XML clob and identify how many Discounts there are in each ProductS and IGNORE those that have less or zero <Discount>.
So in the example above it should return 2.
Thanks.
I just realized that my answer is for SQL-SERVER only. I'll let it here in case this help other people
Here is a Query that will get you 1 record for each product with 1 or more Discount node. This is done by using the xml query function "count()"
declare #xml xml
set #xml = '<ProductS>
<id>1</id>
<Discount></Discount>
<Discount></Discount>
</ProductS>
<ProductS>
<id>2</id>
<Discount></Discount>
</ProductS>'
select
n.xmlNode.query('.') ProductNode
from #xml.nodes('/ProductS') n(xmlNode)
where
n.xmlNode.query('count(Discount)').value('.','int') > 0

FOR XML in SQL SERVER

I have this file output from sql server:
<ProductList>
<Product>
<Product_Department>Sales</Product_Department>
<Product_Category>A</Product_Category>
<Code>AA</Code>
<Description>AAA</Description>
<Price>10</Price>
</Product>
.
.
.
<Product>
.
.
.
</Product>
</ProductList>
The sql script is:
create proc xmlcollection
as
declare #XmlOutput xml
set #XmlOutput = (select * from Product
FOR XML AUTO, ROOT('ProductList'), ELEMENTS)
select #XmlOutput
go
The desired output of xml file would be:
<ProductList>
<Product DEP="Sales" CAT="A" CODE="AA" PRICE="10"></Product>
<Product.........................................></Product>
.
.
.
</ProductList>
How can I do that from FOR XML clause? Please help.
You need to use '#' to specify attribute values when using FOR XML.
See below:
SELECT
Product_Department AS '#DEP'
,Product_Category AS '#CAT'
,Code AS '#Code'
,[Description] AS '#DESC'
,Price AS '#PRICE'
FROM Product
FOR XML PATH ('Product'), ROOT ('ProductList')
As mentioned below, alternatively you could also use 'Type':
SELECT
Product_Department AS 'DEP'
,Product_Category AS 'CAT'
,Code AS 'CODE'
,[Description] AS 'DESC'
,Price AS 'PRICE'
FROM Product
FOR XML AUTO, TYPE, ROOT('ProductList')
This will return the following XML:
<ProductList>
<Product DEP="Sales" CAT="A" CODE="AA" DESC="AAA" PRICE="10" />
<Product DEP="Marketing" CAT="B" CODE="MM" DESC="BBB" PRICE="15" />
</ProductList>
I hope that helps.