Import XML File and transform into Relational Model (for DYNAMIC Columns) using Powershell

Rajnilari2015
Posted by in PowerShell category on for Beginner level | Points: 250 | Views : 3249 red flag
Rating: 4 out of 5  
 1 vote(s)

In this article, we will load XML data into the relational model using PowerShell but for dynamic columns.We will use SQL Server 2014 as our RDBMS.


 Download source code for Import XML File and transform into Relational Model (for DYNAMIC Columns) using Powershell

Introduction

Importing XML data into the relational database is being supported by the introduction of OPENXML and OPENROWSET.

In the previous article, we have seen how to Import XML File and transform into Relational Model (for STATIC Columns ) using Powershell.

As promised, this article will focus on performing the same task but for DYNAMIC Columns

So let's start our journey

Environment Setup

Let us first use the below XML say(Employees.xml)

<Employees>
    <Employee EmpId="Emp001" EmpName="Rajlakshmi" DOJ="02/03/2010"/>   
    <Employee EmpId="Emp002" EmpName="Niladri" DOJ="10/08/2010"/>
    <Employee EmpId="Emp003" EmpName="Arina" DOJ="01/01/2010"/>
    <Employee EmpId="Emp004" EmpName="RNA Team" DOJ="31/12/2010"/>
</Employees>

Using the code

Open any text editor (save the file as "Employees.ps1") and let us write the following command

 [xml]$xml = Get-Content D:\Employees.xml
 $xml.Employees.Employee | Format-List

Now open the SSMS, fire the below query

DECLARE @command  VARCHAR(100)
SET @command = 'powershell.exe  D:\Employees.ps1'

--Create a Temporary table
CREATE TABLE #TblResultXML(EmpId INT IDENTITY(1,1), ResultData VARCHAR(1000) NULL)

--Using xp_cmdshell, invoke the PowerShell script and insert that into the Temporary table
INSERT INTO  #TblResultXML (ResultData) EXEC master..xp_cmdshell @command 

SELECT *
FROM #TblResultXML

--Drop the Temporary table
DROP TABLE #TblResultXML

So our records has been inserted

.Our first task is to seperate the Key and the Values.Let's modify our query as under

DECLARE @command  VARCHAR(100)
SET @command = 'powershell.exe  D:\Employees.ps1'
DECLARE @sql NVARCHAR(MAX)

--Create a Temporary table
CREATE TABLE #TblResultXML(EmpId INT IDENTITY(1,1), ResultData VARCHAR(1000) NULL)

--Using xp_cmdshell, invoke the PowerShell script and insert that into the Temporary table
INSERT INTO  #TblResultXML (ResultData) EXEC master..xp_cmdshell @command 

Select @sql = '
-- Seperate the Keys and Values
;WITH keyValuesSeperateCTE AS(
SELECT 
	EmpId
	, [Key] = LEFT(ResultData, CHARINDEX('':'', ResultData)-1)
	, [Value] = RIGHT(ResultData, LEN(ResultData) - CHARINDEX('':'', ResultData))
FROM #TblResultXML
WHERE ResultData IS NOT NULL AND EmpId > 2
)	
SELECT * FROM keyValuesSeperateCTE'
EXEC sp_executesql @sql

--Drop the Temporary table
DROP TABLE #TblResultXML

We are building our SQL query in dynamic way. @sql is a NVARCHAR Type variable.It is use to store the query string that we are building at runtime/dynamically.Finally, we are executing the dynamic T-SQL statement by using sp_executesql

Result:

For a cleaner approach, we are using Common Table Expression(CTE).The very next step is to Group the "Keys" as under

DECLARE @command  VARCHAR(100)
SET @command = 'powershell.exe  D:\Employees.ps1'
DECLARE @sql NVARCHAR(MAX)

--Create a Temporary table
CREATE TABLE #TblResultXML(EmpId INT IDENTITY(1,1), ResultData VARCHAR(1000) NULL)

--Using xp_cmdshell, invoke the PowerShell script and insert that into the Temporary table
INSERT INTO  #TblResultXML (ResultData) EXEC master..xp_cmdshell @command 

Select @sql = '
-- Seperate the Keys and Values
;WITH keyValuesSeperateCTE AS(
SELECT 
         EmpId
       , [Key] = LEFT(ResultData, CHARINDEX('':'', ResultData)-1)
	, [Value] = RIGHT(ResultData, LEN(ResultData) - CHARINDEX('':'', ResultData))
FROM #TblResultXML
WHERE ResultData IS NOT NULL AND EmpId > 2
),
--Group the Keys 
groupKeysCTE AS(

SELECT 
	Id = ROW_NUMBER() OVER(PARTITION BY X.[Key] ORDER BY X.EmpId)
	,[Key] 
	,[Value]
FROM KeyValuesSeperateCTE X
)	
SELECT * FROM groupKeysCTE'
EXEC sp_executesql @sql

--Drop the Temporary table
DROP TABLE #TblResultXML

Result:

Now we are very close.As a last step we only need to transform the rows to columns by using PIVOTING as shown under

DECLARE @command  VARCHAR(100)
SET @command = 'powershell.exe  D:\Employees.ps1'
DECLARE @sql NVARCHAR(MAX)

--Create a Temporary table
CREATE TABLE #TblResultXML(EmpId INT IDENTITY(1,1), ResultData VARCHAR(1000) NULL)

--Using xp_cmdshell, invoke the PowerShell script and insert that into the Temporary table
INSERT INTO  #TblResultXML (ResultData) EXEC master..xp_cmdshell @command 

Select @sql = '

-- Seperate the Keys and Values
;WITH keyValuesSeperateCTE AS(
SELECT 
	EmpId
	, [Key] = LEFT(ResultData, CHARINDEX('':'', ResultData)-1)
	, [Value] = RIGHT(ResultData, LEN(ResultData) - CHARINDEX('':'', ResultData))
FROM #TblResultXML
WHERE ResultData IS NOT NULL AND EmpId > 2
),
--Group the Keys 
groupKeysCTE AS(
SELECT 
     Id = ROW_NUMBER() OVER(PARTITION BY X.[Key] ORDER BY X.EmpId)
     ,[Key] 
     ,[Value]
FROM KeyValuesSeperateCTE X
)	
SELECT '+ LEFT(col, LEN(col)-1) +' 
FROM groupKeysCTE
PIVOT(
	MAX(Value)
	FOR [Key] IN('+LEFT(col, len(col)-1)+')
      )  AS PIV		'
FROM (
	SELECT DISTINCT '['+LEFT(ResultData, CHARINDEX(':', ResultData)-1)+'], '
	FROM #TblResultXML
	FOR XML PATH('')
     ) AS X(col)		  
EXEC sp_executesql @sql
--Drop the Temporary table
DROP TABLE #TblResultXML

Result:

For flattening the columns into a single row or variable, we are using the below query

SELECT DISTINCT '['+LEFT(ResultData, CHARINDEX(':', ResultData)-1)+'], '
FROM #TblResultXML
FOR XML PATH('')

Result:

FOR XML PATH concatenates multiple rows into a single column string.

The


SELECT  LEFT(col, LEN(col)-1)  
FROM (
	SELECT DISTINCT '['+LEFT(ResultData, CHARINDEX(':', ResultData)-1)+'], '
	FROM #TblResultXML
	FOR XML PATH('')
) AS X(col)

Changes the XML output produced by using FOR XML PATH to a VARCHAR type

Now let us extend our example by modifying the original XML file (Employees.xml) as below

<Employees>
    <Employee EmpId="Emp001" EmpName="Rajlakshmi" DOJ="02/03/2010" Age="4"/>   
    <Employee EmpId="Emp002" EmpName="Niladri" DOJ="10/08/2010" Age="37"/>
    <Employee EmpId="Emp003" EmpName="Arina" DOJ="01/01/2010" Age="26"/>
    <Employee EmpId="Emp004" EmpName="RNA Team" DOJ="31/12/2010" Age="4"/>
</Employees>

And after executing our query, we will receive the below output

So it's working!!!

References

a)Script to create dynamic PIVOT queries in SQL Server

b)Pivots with Dynamic Columns in SQL Server 2005

Conclusion

In this article we learnt to Import XML File and transform into Relational Model (for DYNAMIC Columns) using Powershell. Hope this will be helpful.You can find the zipped files attached herewith.Thanks for reading the article.

Page copy protected against web site content infringement by Copyscape

About the Author

Rajnilari2015
Full Name: Niladri Biswas (RNA Team)
Member Level: Platinum
Member Status: Member,Microsoft_MVP,MVP
Member Since: 3/17/2015 2:41:06 AM
Country: India
-- Thanks & Regards, RNA Team


Login to vote for this post.

Comments or Responses

Posted by: Sheonarayan on: 10/10/2015 | Points: 25
Wow, great way. Thanks for sharing.
Posted by: Rajnilari2015 on: 10/10/2015 | Points: 25
Thank you Sir.

Login to post response

Comment using Facebook(Author doesn't get notification)