Using SQL read html data as XML - html

I have to read HTML table data as XML. But I am not able to get all the information as in my required format.
declare #xml xml='<body bgcolor="#FFFFFF">
<div id="Edit01" style="position:absolute; left:5px; top:4px; width:462px; height:196px; z-index:1">
<table width="462" border="0" cellspacing="0" cellpadding="0">
<tr>
<td colspan="5" width="462">
<span class="auditnoteheader">Charges: </span>
</td>
</tr>
<tr>
<td colspan="5" width="462">
<span class="AuditNoteText">Submitted by ELSGH </span>
</td>
</tr>
<tr>
<td colspan="5" width="462">
<span class="AuditNoteText">Jul 20 2018 9:15PM Eastern Standard Time</span>
</td>
</tr>
<tr class="AuditNoteSubHeader">
<td width="8" />
<td width="230" valign="top">Charge</td>
<td width="110" valign="top">Old Charge Status</td>
<td width="114" valign="top">New Charge Status</td>
</tr>
<tr class="AuditNoteText">
<td width="8" />
<td width="230" valign="top">
<font color="009900">99214 OFFICE OUTPATIENT VISIT 25 MINUTES</font>
</td>
<td width="110" valign="top">
<font color="009900">Review</font>
</td>
<td width="114" valign="top">
<font color="009900">Submitted</font>
</td>
</tr>
<tr class="AuditNoteText">
<td width="8" />
<td width="230" valign="top">
<font color="009900">36415 COLLECTION VENOUS BLOOD</font>
</td>
<td width="110" valign="top">
<font color="009900">Review</font>
</td>
<td width="114" valign="top">
<font color="009900">Submitted</font>
</td>
</tr>
<tr class="AuditNoteSeparater">
<td colspan="5" height="2">
--------------------------------------------------------------------------------------------
</td>
</tr>
</table>
</div>
</body>'
I was trying using this query.
SELECT TR.AT1.query('data(span)') ,TR.AT1.query('*') ,TR.AT1.value('.','varchar(max)')
FROM #xml.nodes('/body/div/table') as T(N)
cross apply T.N.nodes('./tr/td') as TR(AT1)
cross apply TR.AT1.nodes('.') as para(p1)
Inside body tag I am getting multiple tables. first 3 tag(can be different) is table information. Next row with class="AuditNoteSubHeader" is table header and after it all class="AuditNoteText" contains table data. I need to extract this all information. Can any one please help on this ?
My expected output is:
for AuditNoteText I am getting multiple rows, So to differentiate it I had given numbers like AuditNoteText1, AuditNoteText2.

Your expected output is not the best format in my eyes. If this is not an external need, you might try something like this:
;WITH AllTr AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RowIndex
,tr.value('#class','nvarchar(max)') AS trClass
,tr.query('.') AS trNode
FROM #xml.nodes('//table/tr') A(tr)
)
,AllTd AS
(
SELECT AllTr.*
,ROW_NUMBER() OVER(PARTITION BY RowIndex ORDER BY (SELECT NULL)) AS ColumnIndex
,td.value('(.//*/#class)[1]','nvarchar(max)') AS tdClass
,td.value('(.//text())[1]','nvarchar(max)') AS tdText
FROM AllTr
OUTER APPLY trNode.nodes('tr/td[.//text()]') A(td)
)
SELECT RowIndex
,ColumnIndex
,trClass
,tdClass
,tdText
FROM AllTd;
This will provide a row counter and a partitioned column counter. This might be better than name numbered class names.

;WITH C1 AS (
SELECT ISNULL(T.N.value('#class', 'varchar(50)'), TR1.AT1.value('#class', 'varchar(50)')) Hdr
, CONVERT(VARCHAR, DENSE_RANK() OVER ( PARTITION BY TR1.AT1 ORDER BY N )-1) AS HdrNum
, TR.AT1.value('.', 'varchar(max)') AS Data
FROM #xml.nodes('/body/div/table/tr,/body/div/table/tr/td/span') AS T ( N )
CROSS APPLY T.N.nodes('./td') AS TR ( AT1 )
OUTER APPLY T.N.nodes('./td/span') AS TR1 ( AT1 )
WHERE TR.AT1.value('.', 'varchar(max)') NOT LIKE '%---%'
AND TR.AT1.value('.', 'varchar(max)') <> ''
)
SELECT Hdr + CASE WHEN HdrNum = '0' THEN '' ELSE HdrNum END AS Hdr
, Data
FROM C1 ORDER BY hdr

Related

No alerts after incorrect after submitting

I have this class in Java: Tables(String eventName, List<StudentNameAndEstimate> list)
<table class="table">
<caption>My events</caption>
<tr>
<th>Name</th>
<th>Student</th>
<th>Progress</th>
</tr>
<tr th:for="">
<td th:text="${event.getEventName()}"></td>
???
</tr>
</table>
I don't understand how write list next in HTML.
I want to this table in result:
event1 student1 5
student2 4
student3 2
student4 5
...
studentN 5
event2 student1 5
...
It was only necessary to shove it into <th:block> </th:block>
<table class="table">
<caption>My events</caption>
<tr>
<th>Name</th>
<th>Student's Name</th>
<th>Estimate</th>
</tr>
<tr th:each="event:${events}">
<td th:text="${event.getEventName()}"></td>
<th:block th:each="stud:${event.getStudentEstimates()}">
<td th:text="${stud.getStudentName()}"></td>
<td th:text="${stud.getEstimate()}"></td>
</th:block>
</tr>
</table>

Select n items starting with each alphabet from a-z in MySQL

I have tried asking this question previously but moderators closed the question citing it as not clear. Hope this time I make it clear.
I've a services table with up to 1000 services. The table has id & service_title column. So, I basically want to get 10 services each for each alphabet starting from A to Z. If there are fewer than 10 items starting with any particular alphabet than I want to get them all. Also I want them in alphabetical order if possible.
Here's my services table.
So my output table should look something like the one displayed below. For the sake of simplicity I've shown 2 services starting with each alphabet from A to J.
<table border="1">
<caption>Services</caption>
<thead>
<tr>
<th>id</th>
<th>name</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Auditing</td>
</tr>
<tr>
<td>2</td>
<td>Accounting</td>
</tr>
<tr>
<td>3</td>
<td>Brick laying</td>
</tr>
<tr>
<td>4</td>
<td>Builders</td>
</tr>
<tr>
<td>5</td>
<td>Carpet Cleaning</td>
</tr>
<tr>
<td>6</td>
<td>Carpenters</td>
</tr>
<tr>
<td>7</td>
<td>Demolition</td>
</tr>
<tr>
<td>8</td>
<td>Dog Walking</td>
</tr>
<tr>
<td>9</td>
<td>Electrician</td>
</tr>
<tr>
<td>10</td>
<td>Equipment Hire</td>
</tr>
<tr>
<td>11</td>
<td>Fencing & Gates</td>
</tr>
<tr>
<td>12</td>
<td>Fright Services</td>
</tr>
<tr>
<td>13</td>
<td>Gardeners</td>
</tr>
<tr>
<td>14</td>
<td>Gate keepers</td>
</tr>
<tr>
<td>15</td>
<td>Handyman</td>
</tr>
<tr>
<td>16</td>
<td>Health service</td>
</tr>
<tr>
<td>17</td>
<td>Interview Trainer</td>
</tr>
<tr>
<td>18</td>
<td>Iterpersonal Relationship Coach</td>
</tr>
<tr>
<td>19</td>
<td>Joinery Experts</td>
</tr>
<tr>
<td>20</td>
<td>Jacket Maker</td>
</tr>
</tbody>
</table>
Here's the code I've come up with till now
SELECT *
FROM (
SELECT id, service_title,
#count := IF(#value = service_title, #count + 1, 1) AS count
FROM services, (SELECT #count := 1, #value := NULL) a
WHERE services.service_title REGEXP '^[A-z]+$'
) a
WHERE a.count <= 10
Order by service_title
I've listed some services in my sample output table which are not listed in the sample items on the table image, please do not raise that as as issue as I can't display all items on the sample table image.
You may try below query with minor updates from your query -
SELECT *
FROM (SELECT id,
#count := IF(LEFT(#value, 1) = LEFT(service_title, 1), #count + 1, 1) AS cnt,
#value := service_title service_title
FROM services, (SELECT #count := 0, #value := 0) vars
WHERE services.service_title REGEXP '^[A-z]+'
ORDER BY service_title, id
) a
WHERE a.cnt <= 10
Order by service_title, id
Demo.

Not getting SQLQuery quite right - Double info

I use this QUERY
SELECT id_mov, movimientos.id_expte, expte.id_expte, id_dr, detalle, fecha, plazo, expte
FROM movimientos
JOIN expte ON expte.id_expte=expte.id_expte
ORDER BY fecha DESC
And get this response
<table class="table" id="table">
<thead style="background-color:#337ab7">
<tr>
<th>Fecha</th>
<th>Movimiento</th>
<th>Expediente</th>
</tr>
</thead>
<tbody>
<tr>
<td>2016-02-10</td>
<td>Inicio demanda - Adj bono profesional, tasa y aporte.</td>
<td>351516</td>
</tr>
</tbody><tbody>
<tr>
<td>2016-02-10</td>
<td>Inicio demanda - Prox mov adjuntar bonos y demas cosas.</td>
<td>351516</td>
</tr>
</tbody><tbody>
<tr>
<td>2016-02-10</td>
<td>Inicio demanda - Adj bono profesional, tasa y aporte.</td>
<td>134512</td>
</tr>
</tbody><tbody>
<tr>
<td>2016-02-10</td>
<td>Inicio demanda - Prox mov adjuntar bonos y demas cosas.</td>
<td>134512</td>
</tr>
</tbody></table>
Now, my problem is that MOVIMIENTOS table has only 2 records but when i echo my query results with a WHILE it returns a list of 4 registries, when it should just be 2.
Any help is much apreciated. I'm new at this.
You don't join the table on the correct fields .. try using
SELECT id_mov, movimientos.id_expte, expte.id_expte, id_dr, detalle,
fecha, plazo, expte
FROM movimientos
JOIN expte ON movimientos.id_expte=expte.id_expte
ORDER BY fecha DESC

Selecting from and including table rows that contain some text in xpath

I'm new to Html Agility Pack and Xpath. I have a table part of which is:
...
<tbody class="tdata">
<tr bgcolor="#ffffff">
<td nowrap>CRR004</td>
<td nowrap>Carrie</td>
<td nowrap>021</td>
<td nowrap>COAL</td>
<td nowrap>0.800</td>
<td nowrap>55.000</td>
<td nowrap>55.800</td>
<td nowrap>FCR A</td>
<td nowrap> </td>
<td nowrap> </td>
<td nowrap> </td>
</tr></tbody>
...
<tbody class="tdata">
<tr bgcolor="#ffffff">
<td nowrap>CRR004</td>
<td nowrap>Carrie</td>
<td nowrap>021</td>
<td nowrap>COAL</td>
<td nowrap>0.800</td>
<td nowrap>99.500</td>
<td nowrap>100.300</td>
<td nowrap>FCL B</td>
<td nowrap> </td>
<td nowrap> </td>
<td nowrap> </td>
</tr></tbody>
<tbody class="tdata">
<tr bgcolor="#ffffff">
<td nowrap>CRR004</td>
<td nowrap>Carrie</td>
<td nowrap>034</td>
<td nowrap>BONE</td>
<td nowrap>0.100</td>
<td nowrap>100.300</td>
<td nowrap>100.400</td>
<td nowrap>FCL B</td>
<td nowrap> </td>
<td nowrap> </td>
<td nowrap> </td>
</tr></tbody>
<tbody class="tdata">
<tr bgcolor="#ffffff">
<td nowrap>CRR004</td>
<td nowrap>Carrie</td>
<td nowrap>021</td>
<td nowrap>COAL</td>
<td nowrap>0.400</td>
<td nowrap>100.400</td>
<td nowrap>100.800</td>
<td nowrap>FCL B</td>
<td nowrap> </td>
<td nowrap> </td>
<td nowrap> </td>
</tr></tbody>
Using Html Agility Pack, I can grab the entire table with:
doc.DocumentNode.SelectNodes("//tbody[#class='tdata']/tr")
But I only want to select from the row whose 8th column contains "FCR A" to the last row containing "FCL B". That is from row 2 to row 14.
CRR004 Carrie 540 SS 1.100 53.900 55.000
CRR004 Carrie 021 COAL 0.800 55.000 55.800 FCR A
CRR004 Carrie 124 SH 4.200 55.800 60.000
CRR004 Carrie 320 S SH 1.400 60.000 61.400
CRR004 Carrie 540 SS 2.400 61.400 63.800
CRR004 Carrie 320 S SH 0.300 63.800 64.100
CRR004 Carrie 540 SS 15.900 64.100 80.000
CRR004 Carrie 749 SS W/COAL STR 10.000 80.000 90.000
CRR004 Carrie 540 SS 7.200 90.000 97.200
CRR004 Carrie 124 SH 0.500 97.200 97.700
CRR004 Carrie 114 BLACK SH 1.800 97.700 99.500
CRR004 Carrie 021 COAL 0.800 99.500 100.300 FCL B
CRR004 Carrie 034 BONE 0.100 100.300 100.400 FCL B
CRR004 Carrie 021 COAL 0.400 100.400 100.800 FCL B
CRR004 Carrie 120 CL SH 0.800 100.800 101.600
I tried doc.DocumentNode.SelectNodes("//tbody[#class='tdata']/tr[following-sibling::td[8]='FCR A' and preceding-sibling::td[8]='FCL B']")) among others to no avail. Any help will be very much appreciated. Thanks.
After playing around with Splash's suggestion, this works:
//tr[contains(.,'FCR A')]|//tr[following::tr[td[8][.= 'FCL B']][last()] and preceding::tr[td[8][.= 'FCR A']][last()]]|//tr[contains(.,'FCL B')]
But a shorter expression will also be appreciated.

How to create nested cells inside the same table TD

I have the following table:-
<table class="table table-striped">
<thead>
<tr>
<th></th>
</tr>
</thead>
<tbody>
#foreach(var permisionMag in Model.PermisionManagement)
{
<tr>
<td>#permisionMag.Name</td>
#{
int i = 0;
<td class="f">
#foreach(var item in permisionMag.TechnologyTypes.OrderBy(a => a.Name)) {
#(i+1) #item.Name
i = i + 1;
}
<br />
</td>
}
</tr>
}
</tbody>
</table>
But currently i need the second column to have nested rows instead of showing the rows inside the same TD? any advice on this?
You can not generate directly table cells, you have to generate a new table inside the second table cell.
You could also render #item.Name as a span/div and style that to create the illusion of a nested table(jsFiddle example).
You can use rowspan on the first column :
<table class="table table-striped">
<thead>
<tr>
<th></th>
</tr>
</thead>
<tbody>#foreach(var permisionMag in Model.PermisionManagement) {
<tr>
<td rowspan="#permisionMag.TechnologyTypes.Count()">#permisionMag.Name</td>
#{
int i = 0;
foreach (var item in permisionMag.TechnologyTypes.OrderBy(a => a.Name))
{
i = i + 1;
if( i > 1) {
</tr><tr>
}
<td class="f">
#(i+1) #item.Name
</td>
}
}
</tr>
}
</tbody>
</table>
See expecting result
I hope it helps.
If I understand your question, then you probably want to do this:
#foreach(var permisionMag in Model.PermisionManagement) {
<tr>
<td rowspan="#permisionMag.TechnologyTypes.Count()">#permisionMag.Name</td>
#{int i = 0;
#foreach (var item in permisionMag.TechnologyTypes.OrderBy(a => a.Name)) {
<td class="f">
#(i+1) #item.Name
i = i + 1;
</td>
</tr>
<tr>
}
</tr>
}
}
But it should essentially build you something like this:
----------------
| Name | Item1 |
| | ----- |
| | Item2 |
| | ----- |
| | Item3 |
| | ----- |
| | Item4 |
----------------