question

chetanmedivoxx avatar image
chetanmedivoxx asked

XML read in sql server t-sql

DECLARE @XML XML SELECT @XML = NameDateStatus Chetan 07/22/2016Current " I need result like that |--------------|----------------| |Column1 | Column2 | |--------------|----------------| |Name | Chetan | |Date | 7/22/2016 | |Status | Current | |--------------|----------------|
sql serverxml
9 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Oleg avatar image Oleg commented ·
@chetanmedivoxx The XML you posted is rubbish. In order for it to become valid, the first **tr** tag located under **thead** needs to close on line 10, but that line opens a new **tr** tag instead. This does not make any sense. Another problem is that lack of single quotes in the statement setting the value of your xml variable. Do you know why the quotes are missing?
0 Likes 0 ·
chetanmedivoxx avatar image chetanmedivoxx commented ·
Please take a look below
DECLARE @XML XML
SELECT @XML ='
    <tr>
        <td>Name</td>
        <td>Date</td>
        <td>Status</td>
    <tr>
    <tr>
        <td><content ID="material-5570">Chetan</content></td>
        <td>07/22/2016</td>
        <td>Current</td>
    </tr> ';
I need result like that

Column1         Column2
 -----------    ------------
 Name           Chetan
 Date           7/22/2016
 Status         Current
0 Likes 0 ·
chetanmedivoxx avatar image chetanmedivoxx commented ·
Hello please ignore last one sorry for that DECLARE @XML XML SELECT @XML =' NameDateStatusChetan07/22/2016Current' I need result like that Column1 | Column2 |Name | Chetan |Date | 7/22/2016 |Status | Current
0 Likes 0 ·
chetanmedivoxx avatar image chetanmedivoxx commented ·
omg! i dont know what is happening here am confused NameDateStatus Chetan 07/22/2016Current
0 Likes 0 ·
Oleg avatar image Oleg commented ·
@chetanmedivoxx I hope that you are just kidding, right? It is the second time in a row you post a rubbish XML fragment. If you DO OPEN the tag named **tr** then you MUST close this tag at some point. In your example, you open **tr**, add 3 **td** child nodes to it at which point the **tr** tag MUST BE CLOSED. Instead, you re-open another **tr** tag so that now you end up with first *tr** followed by another **tr** (supposed to be closing of the tag instead) followed by another **tr** and only that last one gets properly closed, the first 2 remain open. Therefore, this is not a valid XML fragment. Also, it is not clear what you want to happen if there were more table rows. In your example, there are only 2 rows 3 columns which you need to pivot (transpose) into 3 rows 2 columns. Does it mean that it you had, say 5 table rows then you would want to have the results transposed into 3 rows 5 columns (Column1 through Column5)? Please clarify.
0 Likes 0 ·
ThomasRushton avatar image ThomasRushton ♦♦ commented ·
@Oleg - I suspect that some of @chetanmedivoxx's problems with XML posting are the way that the platform mangles XML code unless you're very very careful.
0 Likes 0 ·
Oleg avatar image Oleg commented ·
@ThomasRushton I think the problem in question text was the failure to close the first TR tag, opening it again instead. So, the header looked like <tr>some td tags<tr> where <tr>some td tags</tr> was expected. It is easy enough for OP to click the parse icon in SSMS before posting the question just to make sure that XML is valid. Sadly, this never happened. @chetanmedivoxx I added the answer, please let me know if it works for you. Thank you.
0 Likes 0 ·
chetanmedivoxx avatar image chetanmedivoxx commented ·
its help me thank you so much @ThomasRushton @Oleg
0 Likes 0 ·
Oleg avatar image Oleg commented ·
@chetanmedivoxx I edited the answer adding the script you need, but the answer went into moderation, so it will become available once it is approved. @ThomasRushton ♦♦ @Kev Riley ♦♦ Guys, if you are online, could you please help me out with this one? Thank you.
0 Likes 0 ·
Oleg avatar image
Oleg answered
Sample data in question provides an admittedly invalid, but working (after the **tr** tag is, finally, closed properly) HTML fragment defined as XML data type. The reason that HTML is invalid is due to the usage of the **TD** tags inside of the table header definition. Usually, the **TH** tags are used for table cells of the table header. However, the browsers are known to be very forgiving, and capable of absorbing developers' ignorance. This means that it is OK for someone to pace TD tags where TH tags are expected and still have HTML which the browsers can render correctly. With the sample data, which unfortunately provides the sample of only 2 table rows without clarifying what to do if there are more rows, the script to get the desired results is very simple. It is based on the idea that the number of table rows (2) and table cells in each row (3) is known in advance. Just selecting the td inner text will produce 6 rows, which need to be transposed into 3 rows, 2 columns. Here is the script which will work for the sample data: -- static solution, can be used if the number of rows in HTML table is 2. select [Column1], [Column2] from ( select x.value('.[1]', 'varchar(50)') CellValue, (row_number() over (order by (select null)) - 1) % 3 + 1 RowNumber, 'Column' + cast(ntile(2) over (order by (select null)) as varchar) ColumnName from @XML.nodes('//../td') r(x) ) src pivot (max(CellValue) for ColumnName in ([Column1], [Column2])) pvt Based on the sample data in question, the query above produces the following results: Column1 Column2 ---------- ---------- Name Chetan Date 07/22/2016 Status Current If the number of HTML table rows is greater than 2 then the script above will not work. I never received any clarification about what to do in this case, but will assume that whatever number of HTML table rows needs to be transposed to that number of columns in the results. For example, should the HTML table in question have 10 rows, the results should be 3 rows 10 columns, with column named like Column1 through Column10. The assumption is still that the number of columns in HTML table is 3. To make it work, the script needs to be dynamic (because hard coding 2 into ntile will no longer work). Please note that there is a need to declare and set 3 extra variables (the original xml variable is needed as well in addition to these 3 new ones). Of course it goes without saying that the dynamic script below will work with any number of HTML table rows (I mean it will work with the original sample data too). If the number of HTML table columns is not equal to 3 then the script will have to be subjected to minor touch up to accommodate this scenario. declare @rows int; -- number of rows in the HTML table declare @columns varchar(max); -- final list of transformed columns declare @sql nvarchar(max); -- dynamic script to execute; declare @XML xml; -- original variable select @XML = 'some html goes here'; -- dynamic script is needed if HTML table can have multiple, unknown in advance number of rows -- the solution assumes that the number of columns in HTML table is still 3, thus 3 is still hardcoded. -- figure out how many rows are in the HTML table select @rows = count(1) / 3 from @XML.nodes('//../td') r(x); -- prepare dynamic list of columns, which depends on the number of rows in HTML table select @columns = stuff(( select top (@rows) ', ' + quotename('Column' + cast(row_number() over (order by (select null)) as varchar)) from @XML.nodes('//../td') r(x) -- better to use a suitable tally table here for xml path('')), 1, 2, ''); select @sql = ' select ' + @columns + ' from ( select x.value(''.[1]'', ''varchar(50)'') CellValue, (row_number() over (order by (select null)) - 1) % 3 + 1 RowNumber, ''Column'' + cast(ntile(' + cast(@rows as varchar) + ') over (order by (select null)) as varchar) ColumnName from @InputXml.nodes(''//../td'') r(x) ) src pivot (max(CellValue) for ColumnName in (' + @columns + ')) pvt '; exec sp_executesql @statement = @sql, @params = N'@InputXml xml', @InputXml = @XML; go **Edit to add a script to render the HTML table data as is, without pivoting.** If the number of both columns and rows is dynamic then the script needs to be dynamic as well. Because the number of column in the HTML table is determined by the number of TD child tags of THEAD/TR, this part can be used to figure the column numbers and names and then this information can be used to generate and execute the final select. Here is the script, which includes the sample XML data consisting of 5 columns and 7 data rows (in addition to the header row which determines the columns' numbers and names): declare @xml xml; declare @sql nvarchar(max); -- dynamic script to execute select @XML = ' NameDateStatusOtherAnotherChetan07/22/2016Current1AMedivoxx08/22/2016Past2BName309/22/2016Current3CName410/22/2016Past4DName511/22/2016Current5EName612/22/2016Past6FName701/22/2017CurrentOther7G'; select @sql = ' select ' + stuff(( select ', ' + char(10) + ' x.value(''td' + quotename(row_number() over (order by (select null))) + ''', ''varchar(50)'')' + quotename(x.value('.[1]', 'varchar(50)')) from @XML.nodes('//thead/tr/td') r(x) for xml path('') ), 1, 3, '' ) + ' from @InputXml.nodes(''//tbody/tr'') r(x)' --print @sql; exec sp_executesql @statement = @sql, @params = N'@InputXml xml', @InputXml = @XML; go Based on the sample data in XML variable, the script above produces the following results (5 columns, 7 rows, as expected): Name Date Status Other Another ---------- ---------- ---------- ---------- ---------- Chetan 07/22/2016 Current 1 A Medivoxx 08/22/2016 Past 2 B Name3 09/22/2016 Current 3 C Name4 10/22/2016 Past 4 D Name5 11/22/2016 Current 5 E Name6 12/22/2016 Past 6 F Name7 01/22/2017 Current 7 G Hope this helps. Oleg
8 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

chetanmedivoxx avatar image chetanmedivoxx commented ·
@Oleg thank you so much for your help it help me a lot and very sorry for inconvenient for XML tag i need one more help from same xml in tbody part there is multiple rows and i need result like its all time dynamic i dont know how many rows in tbody please help me am try to get solution from your given code but please help me. Name Date Status ------------------------------------------------------ Chetan 07/22/2016 Current Medivoxx 08/22/2016 Past thanks a lot chetan koriya
0 Likes 0 ·
Oleg avatar image Oleg commented ·
@chetanmedivoxx The number of **columns** in HTML table is determined by the number of TD tags for any single TR. The number is expected to be the same for any TR, unless colspan is used. The number of **rows** in HTML table is determined by the number of TR tags in TBODY (the single TR tag in THEAD is the row which determines the column headers). You originally asked the data to be pivoted so that you get 3 rows and as many columns as necessary depending on the number of rows in HTML table. I provided you a solution (dynamic script in my answer) which handles any number of rows in HTML table, converting them to columns in the final result. Now it looks like you DO NOT need the data to be pivoted. In this case, if the number of columns is static (3 columns named Name, Date and Status, not sure why you need reserved keywords as names) then you can use this select which will work for any number of rows in HTML table: select x.value('td[1]', 'varchar(50)') [Name], x.value('td[2]', 'varchar(50)') [Date], x.value('td[3]', 'varchar(50)') [Status] from @XML.nodes('//tbody/tr') r(x)
0 Likes 0 ·
chetanmedivoxx avatar image chetanmedivoxx commented ·
yes i got this it is static but header column is not fix it may be some time 3,4,5 like that so i wants to handle it dynamically please help me.
0 Likes 0 ·
Oleg avatar image Oleg commented ·
@chetanmedivoxx OK, I will assume that the number of TD tags under TR of THEAD can be any number, not necessarily 3 and will use this information to determine both the number of column and the column names (from inner text of TD tags in THEAD section). The number of rows does not matter because at the end of the day this is a select statement so it simply selects all rows regardless of how many TR tags are in TBODY. I will also assume that you no longer need the results to be pivoted, they have to be in natural shape, much like they are in the HTML table, not rotated. I will add the script to the bottom of my answer later today.
0 Likes 0 ·
chetanmedivoxx avatar image chetanmedivoxx commented ·
yes @Oleg you got right thank you so much am waiting...:-)
0 Likes 0 ·
Show more comments
chetanmedivoxx avatar image
chetanmedivoxx answered

Hello guys, i have xml file that have value and value contain double qoat in that xml is given below please help me select data from that.

DECLARE @XMLstr AS NVARCHAR(MAX)
SELECT @XMLstr =
DECLARE @xml XML
SELECT @xml = CAST(REPLACE(@XMLstr, '''', '''''') AS XML)
SELECT @xml FOR XML PATH('')

actually i wants to store quote in table "2/2018 Just like we store height foot and inch 5'6 like that "2/2018 please help me.

2 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

WRBI avatar image WRBI commented ·
I can't down vote this, but you already had a question open for this and responded with the above. I've replied in the the other question.
0 Likes 0 ·
chetanmedivoxx avatar image chetanmedivoxx commented ·
yes thank you for replying :-)
0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.