What you want to see on DotNetFunda.com ?
Go to DotNetFunda.com
Twitter TwitterLinkedIn
YouTubeGoogle
 Online : 212 |  Welcome, Guest!   Register  Login
Home > Articles > Sql Server > Extract values from XML attributes and present in comma saperated values using XQuery in SQL Server

Extract values from XML attributes and present in comma saperated values using XQuery in SQL Server

Article posted by Niladri.Biswas on 6/10/2012 | Views: 1589 | Category: Sql Server | Level: Beginner | Points: 250 red flag


In this article we will figure out as how to extract values from XML Attributes and present in comma separated values using XQuery

Download


 Download source code for Extract values from XML attributes and present in comma saperated values using XQuery in SQL Server


Introduction

In a recent requirement of mine, there has been a problem being stated as under

There are many employees into the system and they can have multiple emails.The emails are being stored into xml attributes as under

<EmployeeEmails> 
<Email Value="FirstEmail@employee.com"></Email>
<Email Value="SecondEmail@employee.com"></Email>
<Email Value="ThirdEmail@employee.com"></Email>
</EmployeeEmails>

What we need to generate is a comma separated list as given below.

Emails
------
FirstEmail@employee.com,SecondEmail@employee.com,ThirdEmail@employee.com

Solution 1: Using Node function

Let us first try to extract the node values by using the .nodes() function as shown under

DECLARE @InputData XML = <EmployeeEmails> 
<Email Value="FirstEmail@employee.com"></Email>
<Email Value="SecondEmail@employee.com"></Email>
<Email Value="ThirdEmail@employee.com"></Email>
</EmployeeEmails>

SELECT EmailColumn.value('.','varchar(100)') AS EmailData
FROM @InputData.nodes('/EmployeeEmails/Email/@Value') AS EmailTable(EmailColumn)

/*
EmailData
-------------------------
FirstEmail@employee.com
SecondEmail@employee.com
ThirdEmail@employee.com
*/

The .nodes() function creates an "inline" table of XML fragments for each "row" in the table that contains one <Email> node with "Value" attribute(Kindly note that we retrieve the values for the attribute by specifying @ATTRIBUTE NAME). We can then query on and extract the contents of the XML attribute.

Once we get the row-wise records,next we can apply FOR XML PATH to get the rows transformed into columns with comma seperated list as shown under

DECLARE @InputData XML =<EmployeeEmails> 
<Email Value="FirstEmail@employee.com"></Email>
<Email Value="SecondEmail@employee.com"></Email>
<Email Value="ThirdEmail@employee.com"></Email>
</EmployeeEmails>
;WITH EmailCTE AS
(
SELECT EmailColumn.value('.','varchar(100)') AS EmailData
FROM @InputData.nodes('/EmployeeEmails/Email/@Value') AS EmailTable(EmailColumn)
)

SELECT ',' + CAST(EmailData AS VARCHAR(MAX))
FROM EmailCTE
FOR XML PATH('')

/*
XML_F52E2B61-18A1-11d1-B105-00805F49916B
-------------------------------------------------------------------------
,FirstEmail@employee.com,SecondEmail@employee.com,ThirdEmail@employee.com
*/

We can make out that the data is not formatted properly as there is a comma in the before any data.Just to give a final touch to the solution, we can employ Stuff function inorder to extract the extra comma at the beginning.The full query with desired output is as under

DECLARE @InputData XML =<EmployeeEmails> 
<Email Value="FirstEmail@employee.com"></Email>
<Email Value="SecondEmail@employee.com"></Email>
<Email Value="ThirdEmail@employee.com"></Email>
</EmployeeEmails>
;WITH EmailCTE AS
(
SELECT EmailColumn.value('.','varchar(100)') AS EmailData
FROM @InputData.nodes('/EmployeeEmails/Email/@Value') AS EmailTable(EmailColumn)
)

SELECT Emails = STUFF(EmailList,1,1,'') from
(
SELECT ',' + CAST(EmailData AS VARCHAR(MAX))
FROM EmailCTE
FOR XML PATH('')
)X(EmailList)

/*
Emails
-------------------------------------------------------------------------
FirstEmail@employee.com,SecondEmail@employee.com,ThirdEmail@employee.com
*/

Solution 2: Using Query function

Let us first execute the below code

DECLARE @InputData XML =<EmployeeEmails> 
<Email Value="FirstEmail@employee.com"></Email>
<Email Value="SecondEmail@employee.com"></Email>
<Email Value="ThirdEmail@employee.com"></Email>
</EmployeeEmails>

SELECT @InputData.query('data(EmployeeEmails/Email/@Value)') As Emails

/*
Emails
------------------------------------------------------------------------
FirstEmail@employee.com SecondEmail@employee.com ThirdEmail@employee.com

*/

The above query returns a space separated list with the values stored in the XML fragment.To fulfill our objective we can use Replace function to replace the spaces with comma's. But the query() method returns the data of XML type which will hinder to do so.Henceforth, first we need to convert the XML data type to varchar and then we can use the Replace function.

The below query will,however, convert the XML result to string result

DECLARE @InputData XML = <EmployeeEmails> 
<Email Value="FirstEmail@employee.com"></Email>
<Email Value="SecondEmail@employee.com"></Email>
<Email Value="ThirdEmail@employee.com"></Email>
</EmployeeEmails>
SELECT @InputData.query('data(EmployeeEmails/Email/@Value)').value('.','varchar(100)') As Emails

Finally, we can use the replace function to accomplish the goal

DECLARE @InputData XML = <EmployeeEmails> 
<Email Value="FirstEmail@employee.com"></Email>
<Email Value="SecondEmail@employee.com"></Email>
<Email Value="ThirdEmail@employee.com"></Email>
</EmployeeEmails>
SELECT REPLACE
(
@InputData.query('data(EmployeeEmails/Email/@Value)').value('.','varchar(100)')

,' ' -- replace the white spaces

,',' -- replace the white spaces with commas
) AS Emails

/*
Emails
-------------------------------------------------------------------------
FirstEmail@employee.com,SecondEmail@employee.com,ThirdEmail@employee.com

*/

Conclusion

So in this short article, we have seen as how to parse the XML attribute in order to obtain the data by using Nodes() and Query() functions.Hope this will be helpful to others.Zipped file is attached.

If you like this article, subscribe to our RSS Feed. You can also subscribe via email to our Interview Questions, Codes and Forums section.

Page copy protected against web site content infringement by Copyscape
Found interesting? Add this to:



Please Sign In to vote for this post.

Experience:6 year(s)
Home page:http://www.dotnetfunda.com
Member since:Monday, October 25, 2010
Level:Diamond
Status: [Member]
Biography:Lead Engineer at HCL Technologies Ltd., having 6 years of experience in IT field.
I love to explore new technologies and love challenges and try to help others as much as possible not only by coding but also by all possible means.
>> Write Response - Respond to this post and get points
Related Posts

In my previous article, http://www.dotnetfunda.com/articles/article20.aspx, I have demonstrated on how source control can be made available on stored procedures during the initial stages. Now, let us consider a scenario where source control was lacking for stored procedures for an online database which already was in production.

Were you ever in need of debugging a stored procedure in SQL Server 2005. Any .NET Developer is well versed with debugging .NET applications. The .pdb files will be used internally to serve the purpose. Pdb files will have the mapping information from Native to MSIL and ultimately to the .NET code. I will not get into the internals of how this happens as this article falls under the SQL Server category.

In this post we will solve the problem of finding the "Factorial of number(s)" which appeared as beginners challenge.

Full Text Index is used to perform queries to find-out the character data. These queries can include word or phrase searching. We can create a full-text index on a table or indexed view in the database. Only one full-text index is allowed per table or indexed view.

In this Article you can learn how to create and use DML TRIGGERS .

More ...
About Us | Contact Us | The Team | Advertise | Software Development | Write for us | Testimonials | Privacy Policy | Terms of Use | Link Exchange | Members | Go Top
General Notice: If you find plagiarised (copied) contents on this page, please let us know the original source along with your correct email id (to communicate) for further action.
Copyright © DotNetFunda.Com. All Rights Reserved. Copying or mimicking the site design and layout is prohibited. Logos, company names used here if any are only for reference purposes and they may be respective owner's right or trademarks. | 5/26/2013 3:37:07 AM